Beautiful Android by Eric Burke Square Inc. Friday, October 7, - - PowerPoint PPT Presentation

beautiful android
SMART_READER_LITE
LIVE PREVIEW

Beautiful Android by Eric Burke Square Inc. Friday, October 7, - - PowerPoint PPT Presentation

Beautiful Android by Eric Burke Square Inc. Friday, October 7, 2011 Android Developers? Friday, October 7, 2011 Friday, October 7, 2011 Friday, October 7, 2011 Friday, October 7, 2011 Friday, October 7, 2011 Friday, October 7, 2011 Time


slide-1
SLIDE 1

Beautiful Android

by Eric Burke Square Inc.

Friday, October 7, 2011

slide-2
SLIDE 2

Android Developers?

Friday, October 7, 2011

slide-3
SLIDE 3

Friday, October 7, 2011

slide-4
SLIDE 4

Friday, October 7, 2011

slide-5
SLIDE 5

Friday, October 7, 2011

slide-6
SLIDE 6

Friday, October 7, 2011

slide-7
SLIDE 7

Friday, October 7, 2011

slide-8
SLIDE 8

Time for Code

Friday, October 7, 2011

slide-9
SLIDE 9

public class EditablePhoto extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = getDefaultSize( getSuggestedMinimumWidth(), widthMeasureSpec); int measuredHeight = getDefaultSize( getSuggestedMinimumHeight(), heightMeasureSpec); // Ensure this view is always square. int min = Math.min(measuredHeight, measuredWidth); setMeasuredDimension(min, min); } }

Keep it Square

Friday, October 7, 2011

slide-10
SLIDE 10

public class EditablePhoto extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = getDefaultSize( getSuggestedMinimumWidth(), widthMeasureSpec); int measuredHeight = getDefaultSize( getSuggestedMinimumHeight(), heightMeasureSpec); // Ensure this view is always square. int min = Math.min(measuredHeight, measuredWidth); setMeasuredDimension(min, min); } }

Keep it Square

Friday, October 7, 2011

slide-11
SLIDE 11

public class EditablePhoto extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = getDefaultSize( getSuggestedMinimumWidth(), widthMeasureSpec); int measuredHeight = getDefaultSize( getSuggestedMinimumHeight(), heightMeasureSpec); // Ensure this view is always square. int min = Math.min(measuredHeight, measuredWidth); setMeasuredDimension(min, min); } }

Keep it Square

Friday, October 7, 2011

slide-12
SLIDE 12

Friday, October 7, 2011

slide-13
SLIDE 13

Let’s round these corners.

Friday, October 7, 2011

slide-14
SLIDE 14

Path clip = new Path(); clip.addRoundRect(...); canvas.clipPath(clip); canvas.drawBitmap(photo, 0, 0, null); canvas.restore();

Don’t Do This.

Friday, October 7, 2011

slide-15
SLIDE 15

Ugly Corners

Friday, October 7, 2011

slide-16
SLIDE 16

public class EditablePhoto extends View { private Bitmap image; private Drawable placeholder; private Bitmap framedPhoto; ... @Override protected void onDraw(Canvas canvas) { if (placeholder == null && image == null) return; if (framedPhoto == null) { createFramedPhoto(Math.min(getWidth(), getHeight())); } canvas.drawBitmap(framedPhoto, 0, 0, null); } ...

Lazy Bitmap

Friday, October 7, 2011

slide-17
SLIDE 17

public class EditablePhoto extends View { private Bitmap image; private Drawable placeholder; private Bitmap framedPhoto; ... @Override protected void onDraw(Canvas canvas) { if (placeholder == null && image == null) return; if (framedPhoto == null) { createFramedPhoto(Math.min(getWidth(), getHeight())); } canvas.drawBitmap(framedPhoto, 0, 0, null); } ...

Lazy Bitmap

Friday, October 7, 2011

slide-18
SLIDE 18

public class EditablePhoto extends View { private Bitmap image; private Drawable placeholder; private Bitmap framedPhoto; ... @Override protected void onDraw(Canvas canvas) { if (placeholder == null && image == null) return; if (framedPhoto == null) { createFramedPhoto(Math.min(getWidth(), getHeight())); } canvas.drawBitmap(framedPhoto, 0, 0, null); } ...

Lazy Bitmap

Friday, October 7, 2011

slide-19
SLIDE 19

public class EditablePhoto extends View { private Bitmap image; private Drawable placeholder; private Bitmap framedPhoto; ... @Override protected void onDraw(Canvas canvas) { if (placeholder == null && image == null) return; if (framedPhoto == null) { createFramedPhoto(Math.min(getWidth(), getHeight())); } canvas.drawBitmap(framedPhoto, 0, 0, null); } ...

Lazy Bitmap

Friday, October 7, 2011

slide-20
SLIDE 20

Alpha Compositing

Source: http://en.wikipedia.org/wiki/Alpha_compositing

Friday, October 7, 2011

slide-21
SLIDE 21

private void createFramedPhoto(int size) { // Start with either the placeholder or the image. Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeholder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float outerRadius = size / 18f;

Offscreen Bitmap

Friday, October 7, 2011

slide-22
SLIDE 22

private void createFramedPhoto(int size) { // Start with either the placeholder or the image. Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeholder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float outerRadius = size / 18f;

Offscreen Bitmap

Friday, October 7, 2011

slide-23
SLIDE 23

private void createFramedPhoto(int size) { // Start with either the placeholder or the image. Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeholder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float outerRadius = size / 18f;

Offscreen Bitmap

Friday, October 7, 2011

slide-24
SLIDE 24

private void createFramedPhoto(int size) { // Start with either the placeholder or the image. Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeholder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float outerRadius = size / 18f;

Offscreen Bitmap

Friday, October 7, 2011

slide-25
SLIDE 25

Draw a Red Rectangle

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); canvas.drawRoundRect(outerRect, outerRadius, outerRadius, paint);

Friday, October 7, 2011

slide-26
SLIDE 26

Transparent Corners

paint.setXfermode(new PorterDuffXfermode( PorterDuff.Mode.SRC_IN));

Friday, October 7, 2011

slide-27
SLIDE 27

// Compose the image with the red rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint. canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();

Composing the Image

Friday, October 7, 2011

slide-28
SLIDE 28

// Compose the image with the red rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint. canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();

Composing the Image

Friday, October 7, 2011

slide-29
SLIDE 29

// Compose the image with the red rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint. canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();

Composing the Image

Friday, October 7, 2011

slide-30
SLIDE 30

// Compose the image with the red rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint. canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();

Composing the Image

Drawing over the red rectangle.

Friday, October 7, 2011

slide-31
SLIDE 31

// Compose the image with the red rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint. canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();

Composing the Image

Friday, October 7, 2011

slide-32
SLIDE 32

Rounded Corners

Friday, October 7, 2011

slide-33
SLIDE 33

Framing the Photo

  • 1. Create offscreen bitmap.

Friday, October 7, 2011

slide-34
SLIDE 34

Framing the Photo

  • 2. Draw an opaque rounded rectangle.

Friday, October 7, 2011

slide-35
SLIDE 35

Framing the Photo

  • 3. Set the Porter Duff mode.

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));

Friday, October 7, 2011

slide-36
SLIDE 36

Framing the Photo

  • 4. Draw a translucent rounded rectangle.

Transparent center viewport.

Friday, October 7, 2011

slide-37
SLIDE 37

Friday, October 7, 2011

slide-38
SLIDE 38

Friday, October 7, 2011

slide-39
SLIDE 39

Friday, October 7, 2011

slide-40
SLIDE 40

plastic_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Nearly white at the top, light gray at the bottom. --> <gradient android:startColor="#fff7f7f7" android:endColor="#ffe2e3e5" android:angle="270"/> </shape>

res/drawable/plastic_background.xml

Friday, October 7, 2011

slide-41
SLIDE 41

PlasticLinearLayout

public class PlasticLinearLayout extends LinearLayout { public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_window_background); } }

Friday, October 7, 2011

slide-42
SLIDE 42

Friday, October 7, 2011

slide-43
SLIDE 43

Friday, October 7, 2011

slide-44
SLIDE 44

Triangular Shine

private void createShinePath() { int width = getWidth(); int height = (int) (0.85 * getHeight()); shinePath = new Path(); shinePath.moveTo(0, 0); shinePath.lineTo(width, 0); shinePath.lineTo(width, height); shinePath.close(); shinePaint.setShader(new LinearGradient(0, 0, 0, height, 0x66ffffff, 0x10ffffff, CLAMP)); }

Friday, October 7, 2011

slide-45
SLIDE 45

Triangular Shine

private void createShinePath() { int width = getWidth(); int height = (int) (0.85 * getHeight()); shinePath = new Path(); shinePath.moveTo(0, 0); shinePath.lineTo(width, 0); shinePath.lineTo(width, height); shinePath.close(); shinePaint.setShader(new LinearGradient(0, 0, 0, height, 0x66ffffff, 0x10ffffff, CLAMP)); }

Friday, October 7, 2011

slide-46
SLIDE 46

Triangular Shine

private void createShinePath() { int width = getWidth(); int height = (int) (0.85 * getHeight()); shinePath = new Path(); shinePath.moveTo(0, 0); shinePath.lineTo(width, 0); shinePath.lineTo(width, height); shinePath.close(); shinePaint.setShader(new LinearGradient(0, 0, 0, height, 0x66ffffff, 0x10ffffff, CLAMP)); }

Friday, October 7, 2011

slide-47
SLIDE 47

Friday, October 7, 2011

slide-48
SLIDE 48

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-49
SLIDE 49

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-50
SLIDE 50

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-51
SLIDE 51

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-52
SLIDE 52

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-53
SLIDE 53

public class PlasticLinearLayout extends LinearLayout { private final Paint shinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path shinePath; public PlasticLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // The subtle gradient draws behind everything. setBackgroundResource(R.drawable.plastic_background); } @Override protected void dispatchDraw(Canvas canvas) { if (shinePath == null) { createShinePath(); } // Draw the shine behind the children. canvas.drawPath(shinePath, shinePaint); // Draw the children. super.dispatchDraw(canvas); }

Friday, October 7, 2011

slide-54
SLIDE 54

@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); // Invalidate the path whenever the size changes. shinePath = null; } /** * Creates a triangle shape that draws the subtle glossy * shine. */ private void createShinePath() { ... } }

Friday, October 7, 2011

slide-55
SLIDE 55

@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); // Invalidate the path whenever the size changes. shinePath = null; } /** * Creates a triangle shape that draws the subtle glossy * shine. */ private void createShinePath() { ... } }

Friday, October 7, 2011

slide-56
SLIDE 56

Usage

<com.squareup.ui.PlasticLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > ...normal layout here </com.squareup.ui.PlasticLinearLayout>

Friday, October 7, 2011

slide-57
SLIDE 57

Takeaways

  • Subtle gradients FTW
  • Test with bright, primary colors
  • Invalidate drawables when bounds change

Friday, October 7, 2011

slide-58
SLIDE 58

Recommended Tools

xScope DigitalColor Meter

Friday, October 7, 2011

slide-59
SLIDE 59

Custom Attributes

<declare-styleable name="EditablePhoto"> <attr name="caption" format="string"/> <attr name="captionSize" format="dimension"/> <attr name="placeholder" format="reference"/> </declare-styleable>

res/values/attrs.xml

Friday, October 7, 2011

slide-60
SLIDE 60

Attribute Namespace

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:square="http://schemas.android.com/apk/res/com.squareup" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal|top" >

Your Application Package

Friday, October 7, 2011

slide-61
SLIDE 61

Referencing Attributes

<com.squareup.EditablePhoto android:layout_width="@dimen/merchant_photo" android:layout_height="@dimen/merchant_photo" square:caption="@string/edit" square:captionSize="@dimen/merchant_caption" square:placeholder="@drawable/merchant_placeholder" />

Friday, October 7, 2011

slide-62
SLIDE 62

public EditablePhoto(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.EditablePhoto, 0, 0); placeholder = a.getDrawable( R.styleable.EditablePhoto_placeholder); caption = a.getString( R.styleable.EditablePhoto_caption); captionSize = a.getDimension( R.styleable.EditablePhoto_captionSize, getResources().getDimension( R.dimen.editable_photo_default_caption_size)); a.recycle(); ... }

Friday, October 7, 2011

slide-63
SLIDE 63

Small targets are hard to tap.

Friday, October 7, 2011

slide-64
SLIDE 64

Invisible TouchDelegate

Friday, October 7, 2011

slide-65
SLIDE 65

public static void expandTouchArea(final View bigView, final View smallView) { // Posting ensures the big view has a non-zero size. bigView.post(new Runnable() { @Override public void run() { // Touch delegates require local coordinates. Rect rect = new Rect(0, 0, bigView.getWidth(), bigView.getHeight()); bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); } }); }

TouchDelegate

Friday, October 7, 2011

slide-66
SLIDE 66

public static void expandTouchArea(final View bigView, final View smallView) { // Posting ensures the big view has a non-zero size. bigView.post(new Runnable() { @Override public void run() { // Touch delegates require local coordinates. Rect rect = new Rect(0, 0, bigView.getWidth(), bigView.getHeight()); bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); } }); }

TouchDelegate

Friday, October 7, 2011

slide-67
SLIDE 67

public static void expandTouchArea(final View bigView, final View smallView) { // Posting ensures the big view has a non-zero size. bigView.post(new Runnable() { @Override public void run() { // Touch delegates require local coordinates. Rect rect = new Rect(0, 0, bigView.getWidth(), bigView.getHeight()); bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); } }); }

TouchDelegate

Friday, October 7, 2011

slide-68
SLIDE 68

Fitts’s Law

  • Speed & Accuracy trade off
  • Make targets big and close

Friday, October 7, 2011

slide-69
SLIDE 69

Friday, October 7, 2011

slide-70
SLIDE 70

Round Corners

Friday, October 7, 2011

slide-71
SLIDE 71

FrameLayout RoundCornerViewport

Friday, October 7, 2011

slide-72
SLIDE 72

public class RoundCornerViewport extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { // Clip to a round rect shape. This will leave some // jagged pixels around the rounded corners. canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipPath(roundRectPath); // Draw the child view, but only the part inside the // clip path shows. super.dispatchDraw(canvas); canvas.restore(); // Cover up the jagged pixels with this border. canvas.drawRoundRect(boundsRect, cornerRadius, cornerRadius, borderLinePaint); } }

Friday, October 7, 2011

slide-73
SLIDE 73

public class RoundCornerViewport extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { // Clip to a round rect shape. This will leave some // jagged pixels around the rounded corners. canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipPath(roundRectPath); // Draw the child view, but only the part inside the // clip path shows. super.dispatchDraw(canvas); canvas.restore(); // Cover up the jagged pixels with this border. canvas.drawRoundRect(boundsRect, cornerRadius, cornerRadius, borderLinePaint); } }

Friday, October 7, 2011

slide-74
SLIDE 74

public class RoundCornerViewport extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { // Clip to a round rect shape. This will leave some // jagged pixels around the rounded corners. canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipPath(roundRectPath); // Draw the child view, but only the part inside the // clip path shows. super.dispatchDraw(canvas); canvas.restore(); // Cover up the jagged pixels with this border. canvas.drawRoundRect(boundsRect, cornerRadius, cornerRadius, borderLinePaint); } }

Friday, October 7, 2011

slide-75
SLIDE 75

public class RoundCornerViewport extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { // Clip to a round rect shape. This will leave some // jagged pixels around the rounded corners. canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipPath(roundRectPath); // Draw the child view, but only the part inside the // clip path shows. super.dispatchDraw(canvas); canvas.restore(); // Cover up the jagged pixels with this border. canvas.drawRoundRect(boundsRect, cornerRadius, cornerRadius, borderLinePaint); } }

Friday, October 7, 2011

slide-76
SLIDE 76

Jagged Corner.

Friday, October 7, 2011

slide-77
SLIDE 77

public class RoundCornerViewport extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { // Clip to a round rect shape. This will leave some // jagged pixels around the rounded corners. canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipPath(roundRectPath); // Draw the child view, but only the part inside the // clip path shows. super.dispatchDraw(canvas); canvas.restore(); // Cover up the jagged pixels with this border. canvas.drawRoundRect(boundsRect, cornerRadius, cornerRadius, borderLinePaint); } }

Thick Line

Friday, October 7, 2011

slide-78
SLIDE 78

android:imeOptions="actionDone"

Friday, October 7, 2011

slide-79
SLIDE 79

passwordField.setOnEditorActionListener( new TextView.OnEditorActionListener() { @Override public boolean onEditorAction( TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { doneClicked(passwordField); return true; } return false; } });

Friday, October 7, 2011

slide-80
SLIDE 80

passwordField.setOnEditorActionListener( new TextView.OnEditorActionListener() { @Override public boolean onEditorAction( TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { doneClicked(passwordField); return true; } return false; } });

Friday, October 7, 2011

slide-81
SLIDE 81

android:imeOptions=”actionNext” android:inputType=”phone” android:inputType=”textPersonName|textCapWords” etc...

More to Explore

Friday, October 7, 2011

slide-82
SLIDE 82

Thinking of using ViewFlipper?

Friday, October 7, 2011

slide-83
SLIDE 83

Friday, October 7, 2011

slide-84
SLIDE 84

Bug 6191

Fatal bug prior to Honeycomb: http://code.google.com/p/android/issues/detail?id=6191

Friday, October 7, 2011

slide-85
SLIDE 85

SafeViewFlipper

@Override protected void onDetachedFromWindow() { try { super.onDetachedFromWindow(); } catch (IllegalArgumentException e) { stopFlipping(); } }

http://pastie.org/1086467

Friday, October 7, 2011

slide-86
SLIDE 86

Friday, October 7, 2011

slide-87
SLIDE 87

getChildDrawingOrder(...) drawChild(...) canvas.clipRect(...) canvas.translate(...) canvas.rotate(...)

Friday, October 7, 2011

slide-88
SLIDE 88

Holograms

Start with three images:

Friday, October 7, 2011

slide-89
SLIDE 89

Hologram Interface

public interface Hologram { /** * Adjusts the hologram display. * * @param value ranges from -1..1. */ void update(float value); }

Friday, October 7, 2011

slide-90
SLIDE 90

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-91
SLIDE 91

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-92
SLIDE 92

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-93
SLIDE 93

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-94
SLIDE 94

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-95
SLIDE 95

public class HologramView extends View implements Hologram { private final Bitmap baseImage; private final Bitmap redOverlay; private final Bitmap blueOverlay; private final Paint overlayPaint = new Paint(); private float value; ... @Override public void draw(Canvas canvas) { canvas.drawBitmap(baseImage, 0, 0, null); Bitmap overlay = (value >= 0) ? redOverlay : blueOverlay; int overlayAlpha = Math.abs((int) 255 * value);

  • verlayPaint.setAlpha(overlayAlpha);

canvas.drawBitmap(overlay, 0, 0, overlayPaint); } @Override public void update(float value) { this.value = value; invalidate(); } }

Friday, October 7, 2011

slide-96
SLIDE 96

Accelerometer Listener

@Override public void onSensorChanged(SensorEvent sensorEvent) { final float ax = sensorEvent.values[0]; final float ay = sensorEvent.values[1]; final float az = sensorEvent.values[2]; // Sum typically ranges from approximately -16...16 float sum = ax + ay + az; // Dividing by 4 looks nice. Smaller denominators make the // hologram shift more quickly. float value = (float) Math.sin(sum / 4); delegate.update(value); }

Friday, October 7, 2011

slide-97
SLIDE 97
  • Averages the accelerometer readings
  • Contains an array, length = 8
  • Smooths the otherwise jittery signal

Boxcar Filter

Friday, October 7, 2011

slide-98
SLIDE 98

Demo

Friday, October 7, 2011

slide-99
SLIDE 99

Questions

eric@squareup.com

Friday, October 7, 2011