click tracking

http://is.gd/FluidAndroidLayouts

Many devices

Various size, resolution, density, ratio

Name Diagonal Resolution PPI Ratio
HTC Magic 3.2" 320x480 181 2:3
Nexus One 3.7" 480x800 252 3:5
HTC Evo 3D 4.3" 960x540 256 16:9
Galaxy Note 5.3" 800x1280 285 5:8
Kindle Fire 7" 1024x600 169 16:9
NOOK Color 7" 1024x600 169 16:9
HTC JetStream 10.1" 1280x800 149 5:8
http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density

No absolute co-ordinates

  • Everything is relative
  • Think proportionally
  • Backgrounds: sketchable or tileable
  • Allow scrolling

Initial implementation

Flowchart with other screens

Styled Character Screen

Actual Character Screen

Divide by ratio

layout_weight

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="match_parent"
  android:layout_width="match_parent"
  android:orientation="horizontal" >
  <View
    android:layout_height="match_parent"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:background="#c90" />
  <View
    android:layout_height="match_parent"
    android:layout_width="0dp"
    android:layout_weight="2"
    android:background="#630" />
</LinearLayout>

Variable width background

res/drawable/box.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="15dp" />
  <gradient
    android:startColor="#7000"
    android:centerColor="#3000"
    android:endColor="#7000"
    android:angle="270" />
</shape>

box.xml as background

<TextView
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="@drawable/box"
/>

Variable height

Assign remaining height

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_weight="1" />
</LinearLayout>

Scroll

<ScrollView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
    <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
  </LinearLayout>
</ScrollView>

Character tracing area

Weight sum

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:weightSum="9">
  <View
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="5"
    android:layout_gravity="center" />
</LinearLayout>

What about the height?


Custom view

  • onLayout()
    Where is the view?
  • onMeasure()
    How big?
  • onDraw()
    What is inside?

SquareView

public class SquareView extends View {
  // Constructors omitted

  public void onMeasure(
      int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
    setMeasuredDimension(size, size);
  }
}

Take the smaller dimension


Texture background

res/drawable/wood_panel_background.xml

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
  android:src="@drawable/wood_panel"
  android:tileMode="mirror"
  android:dither="true" />

Tile mode

clamp
Replicates the edge color
android:tileMode="clamp"
repeat
Repeats the bitmap in both direction
android:tileMode="repeat"
mirror
Repeats with alternating mirror images
android:tileMode="mirror"

7-inch

Workbook

Auto fit columns

<GridView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:numColumns="auto_fit"
  android:padding="@dimen/workbook_padding"
  android:horizontalSpacing="@dimen/workbook_spacing"
  android:verticalSpacing="@dimen/workbook_spacing"
  android:columnWidth="@dimen/workbook_column_width"
  android:scrollbarStyle="outsideOverlay" />

res/values/dimens.xml

<resources>
  <dimen name="workbook_spacing">13dp</dimen>
  <dimen name="workbook_column_width">120dp</dimen>
<resources>

7-inch

Bookshelf

Bookshelf building blocks


           

BookshelfGridView

public class BookshelfGridView extends GridView {
  // Constructors etc

  protected void dispatchDraw(Canvas canvas) {
    for (int y = top; y < height; y += mWoodPanelHeight) {
      for (int x = mLeftWidth; x < width; x += mWoodPanelWidth) {
        canvas.drawBitmap(mWoodPanelImage, x, y, null);
      }
    }

    for (int y = top; y < height; y += mShelfHeight) {
      // Draw left edge
      // Draw shelf
      // Draw right edge
    }

    super.dispatchDraw(canvas);
  }
}

Splash screen

RelativeLayout & FrameLayout

<FrameLayout>

  <RelativeLayout>
    <Button
      android:id="@+id/start_button"
      android:layout_centerInParent="true" />
    <ImageView
      android:id="@+id/monkey"
      android:layout_toLeftOf="@id/start_button"
      android:layout_centerVertical="true" />
  </RelativeLayout>

  <ImageView
    android:id="@+id/title"
    android:layout_gravity="center_horizontal"
    android:adjustViewBounds="true" />

</FrameLayout>

How about phones?

  • Smaller screen
  • Portrait vs landscape

Too wide for a phone

Portrait layout

   

onClick in xml

<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/info"
  android:onClick="toggleInfo" />
public void toggleInfo(View v) {
  // Switch between character tracing and info display
}

Resource folders

  • res/layout
  • res/layout-land
  • res/values
  • res/values-large
  • res/drawable
  • res/drawable-hdpi
  • res/drawable-large-land

One orientation per device

public static boolean isLargeScreen(Activity activity) {
  DisplayMetrics metrics
      = activity.getResources().getDisplayMetrics();
  int longSize = Math.max(metrics.widthPixels, metrics.heightPixels);
  return (longSize / metrics.density > 960);
}
public static int getPreferredScreenOrientation(Activity activity) {
  return isLargeScreen(activity) ?
      ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE :
      ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
// In activity
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setRequestedOrientation(Util.getPreferredScreenOrientation(this));
}

No sensor

<!-- AndroidManifest.xml -->
<activity
  android:name=".CharacterActivity"
  android:screenOrientation="nosensor" />

Workbook

Bookshelf

Splash

Tool box

  • RelativeLayout
  • Proportional width and height
  • Allow scrolling
  • Resource folders (orientation, size, density)
  • Shape xml
  • 9-patch
  • Background tiles
  • DisplayMetrics
  • Custom view

Be flexible

Thank you!