droidcon2013 android experience lahoda

85

Upload: droidcon-berlin

Post on 09-May-2015

357 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Droidcon2013 android experience lahoda
Page 2: Droidcon2013 android experience lahoda

IMPROVING ANDROID EXPERIENCE FOR BOTH USERS AND DEVELOPERS

droidcon Berlin 2013, Pavel Lahoda, Actiwerks Ltd.

Page 3: Droidcon2013 android experience lahoda

LET’S HAVE A LITTLE WARMUP

Page 4: Droidcon2013 android experience lahoda

ANDROID.UTIL.LOG

Page 5: Droidcon2013 android experience lahoda

HOW MANY TIMES YOU’VE TYPED THIS ?

Page 6: Droidcon2013 android experience lahoda

prn.log("Index=" + i);

HOW ABOUT THIS ?

Page 7: Droidcon2013 android experience lahoda

public static String cc(int depth) { if(skipCallStackCode == true) { return NA; // short-circuit for production } StackTraceElement[] ste = getStackTrace(null); int depthCount = 0; boolean shallowFlag = true; for(StackTraceElement element : ste) { if(prn.class.getName().equals(element.getClassName()) == true) { // always ignore elements that are above this class in the stack shallowFlag = false; } else { if(shallowFlag == false) { if(depthCount >= depth) { String name = element.getFileName(); if(name != null) { if(name.endsWith(".java")) { name = name.substring(0, name.length()-5); } } else { name ="[?]"; } return name; } else { depthCount++; } } } } return NA_BUG; }

HOW DOES IT WORK ?

Page 8: Droidcon2013 android experience lahoda

GITHUB LINK

Page 9: Droidcon2013 android experience lahoda

WHERE IS THE UX ?

Page 10: Droidcon2013 android experience lahoda

HAVE TIME TO WORK ON AWESOME STUFF !

Page 11: Droidcon2013 android experience lahoda

IMPORTANCE OF HAVING YOUR VIEW FLEXIBLE

Page 12: Droidcon2013 android experience lahoda

ANDROID AND WEB COMMON STUFFUNLIMITED AMOUNT OF DISPLAY SIZES

Page 13: Droidcon2013 android experience lahoda

WEB TRENDS: RESPONSIVE DESIGN

Page 14: Droidcon2013 android experience lahoda

ANDROID TRENDS: LOTS OF WORK

Page 15: Droidcon2013 android experience lahoda

CURRENT ANDROID LAYOUTS ARE NOT FLEXIBLE ENOUGH

Page 16: Droidcon2013 android experience lahoda

ALTERNATIVE:USE PURE JAVA VIEWGROUP

Page 17: Droidcon2013 android experience lahoda

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec); tinyGap = widthSpecSize/100; myComponent.measure(View.MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY));

// more component’s measuring goes there setMeasuredDimension(widthSpecSize, newHeight);}

@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {

myComponent.layout(x, y, x+myComponent.getMeasuredWidth(), y+titleLabel.getMeasuredHeight());// more component’s layout goes there

}

Page 18: Droidcon2013 android experience lahoda

ONMEASURE() - PLACE FOR YOUR LOGIC

Page 19: Droidcon2013 android experience lahoda

NO NEED TO REBIND COMPONENTS OR CALL SLOW LAYOUT INFLATE CODE

Page 20: Droidcon2013 android experience lahoda

WORKS GREAT FOR ORIENTATION CHANGES

Page 21: Droidcon2013 android experience lahoda

BBC NEWS FOR TABLETS EXAMPLE

Page 22: Droidcon2013 android experience lahoda

INSPIRATION:WEB RESPONSIVE LAYOUT

Page 23: Droidcon2013 android experience lahoda

DEAL WITH MANY DIFFERENT SCREEN SIZES

Page 24: Droidcon2013 android experience lahoda

STANDOUT - FLOATING WINDOWS

Page 25: Droidcon2013 android experience lahoda

ACTION BAR

Page 26: Droidcon2013 android experience lahoda

ONE OF WORST EXAMPLES OF API DESIGN

Page 27: Droidcon2013 android experience lahoda

ACTIONBAR IS NOT A DESCENDANT OF A VIEW

Page 28: Droidcon2013 android experience lahoda

BLOG.PERPETUMDESIGN.COM/2011/08/STRANGE-CASE-OF-DR-ACTION-AND-

MR-BAR.HTML

Page 29: Droidcon2013 android experience lahoda

ACTIONBARSHERLOCK

Page 30: Droidcon2013 android experience lahoda

ACTION BAR PLUS

Page 31: Droidcon2013 android experience lahoda

PROBLEM ?

Page 32: Droidcon2013 android experience lahoda

AB OCCUPIES ~10% OF SCREEN SPACE

Page 33: Droidcon2013 android experience lahoda

FUNCTIONALITY OFTEN REDUCED TO BRANDING

Page 34: Droidcon2013 android experience lahoda

FLY-OUT MENU: A FACEBOOK SOLUTION

Page 35: Droidcon2013 android experience lahoda

NOT CONSISTENT WITH THE REST OF ACTIONBAR FUNCTIONALITY

Page 36: Droidcon2013 android experience lahoda

ACTIONBAR PARTS

Page 37: Droidcon2013 android experience lahoda

ACTIONBAR BEHAVIOR

Touch here showsa menu with options

Touch here moves up in hierarchy

Touch here performs action

Touch here show a menu with options

Any extension should stay consistent with this

Page 38: Droidcon2013 android experience lahoda

DON’T CONFUSE YOUR USERS

Page 39: Droidcon2013 android experience lahoda

OWN APPS’D USE SOME UX FACELIFT

Page 40: Droidcon2013 android experience lahoda

STILL WANT MORE FROM THE ACTIONBAR AREA ?

Page 41: Droidcon2013 android experience lahoda

ACTION BAR PLUSCUSTOM ACTIONBAR IMPLEMENTATION

Page 42: Droidcon2013 android experience lahoda

EMBRACE EXTRA DIMENSION

Page 43: Droidcon2013 android experience lahoda

TWO TYPES OF NAVIGATION

Page 44: Droidcon2013 android experience lahoda

MAKE SURE THERE IS DEAD AREA TO SEPARATE FROM NOTIFICATION BAR

GESTURE

Page 45: Droidcon2013 android experience lahoda

USE MIDDLE AS BONUS CONTENT

Page 46: Droidcon2013 android experience lahoda

SUCH AS STUFF OUTSIDE THE APP

Page 47: Droidcon2013 android experience lahoda

2D JUST ON OVERFLOWACTIONS ARE EITHER TOUCH

OR SWIPE DOWN

Page 48: Droidcon2013 android experience lahoda

ACCESS TO HELP ON ACTIONS

Page 49: Droidcon2013 android experience lahoda

EMBRACE MULTITOUCH

Page 50: Droidcon2013 android experience lahoda

EASY SPLIT VIEW FEATURE

Page 51: Droidcon2013 android experience lahoda

BROADCAST THE AVAILABLE SCREEN

actiwerks.intent.splitviewDESCRIPTION OF THE INTENT APPEARS SOON ON THE OPENINTENTS.ORG

Page 52: Droidcon2013 android experience lahoda

BROADCAST DETAILS

private Intent splitIntent;

splitIntent = new Intent();splitIntent.setAction("actiwerks.intent.splitview");

splitIntent.removeExtra("APP_SPLIT_SIZE");splitIntent.putExtra("APP_SPLIT_SIZE", windowVerticalOffset);getContext().sendBroadcast(splitIntent);

Page 53: Droidcon2013 android experience lahoda

RECEIVE THE BROADCAST

<receiver android:name="AppSplitViewReceiver" ><intent-filter>

<action android:name="actiwerks.intent.splitview" /></intent-filter>

</receiver>

public class AppSplitViewReceiver extends BroadcastReceiver {

@Override public void onReceive(Context context, Intent intent) { if(intent.getAction() != null && intent.getAction().equals("actiwerks.intent.splitview")) { int peekSize = intent.getIntExtra("APP_SPLIT_SIZE", -1); // Handle the intent in the app, resize the window/layout accordingly } }

}

Page 54: Droidcon2013 android experience lahoda

ACTIONBARPLUS IN THE GITHUB

Page 55: Droidcon2013 android experience lahoda

FUN WITH THE LIST VIEW

Page 56: Droidcon2013 android experience lahoda

PROBLEM ?

Page 57: Droidcon2013 android experience lahoda

ARRAYADAPTER API NOT DESIGNEDFOR GENERIC VIEWGROUP

Page 58: Droidcon2013 android experience lahoda

interface ViewAdapterBinder<T, V> {public void bindViewToData(V view, T data);

}

public class ArrayViewGroupAdapter<T, V extends ViewGroup> extends ArrayAdapter<T>

BIND DATA TO VIEW

Page 59: Droidcon2013 android experience lahoda

public View getView(int position, View convertView, ViewGroup parent){ // assign the view we are converting to a local variable V v = null; try { v = (V) convertView; } catch(ClassCastException ccex) {}

// safe to ignore, keep null to force new instance to be created

// first check to see if the view is null. if so, we have to inflate it. // to inflate it basically means to render, or show, the view. if (v == null) { v = getInstanceOfV(); } T data = getItem(position); if (data != null && binder != null) { binder.bindViewToData(v, data); } else { // signal error here prn.log("Can't bind data to view " + position); } // the view must be returned to our activity return v;

}

Page 60: Droidcon2013 android experience lahoda

private V getInstanceOfV() {

ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();

Class<V> type = (Class<V>) superClass.getActualTypeArguments()[1];

try { return type.getDeclaredConstructor(Context.class).newInstance(getContext());

} catch (Exception ex) {// Oops, no default constructorthrow new RuntimeException(ex);

}

}

Page 61: Droidcon2013 android experience lahoda

public class SampleArrayAdapter extends ArrayViewGroupAdapter<SampleData, SampleListItem> {

public SampleArrayAdapter(Context context) { super(context, new ArrayViewGroupAdapter.ViewAdapterBinder<SampleData, SampleListItem>() { @Override public void bindViewToData(SampleListItem view, SampleData data) { view.setTitle(data.getTitle()); view.setDetails(data.getDetails()); } }); }}

Page 62: Droidcon2013 android experience lahoda

A TYPE-SAFE, REFACTORING FRIENDLY SOLUTION

Page 63: Droidcon2013 android experience lahoda

ADVANTAGES FOR THE DEVELOPER AND THE USER

Page 64: Droidcon2013 android experience lahoda

INSTANT LISTS WITH INTROSPECTION

Page 65: Droidcon2013 android experience lahoda

OBJECTFORMS.COM

Page 66: Droidcon2013 android experience lahoda

FLEXIBLE LAYOUT ALLOWS RESIZING

Page 67: Droidcon2013 android experience lahoda

PINCH TO ZOOM GESTURE IN LISTS

Page 68: Droidcon2013 android experience lahoda

TIME AND DATE PICKER

Page 69: Droidcon2013 android experience lahoda

PROBLEM ?

Page 70: Droidcon2013 android experience lahoda

UNLIKE OTHER WIDGETS, TIME & DATE PICKER NEEDS DIALOG

(OR PLENTY OF SPACE)

Page 71: Droidcon2013 android experience lahoda

SOLUTION:SPLIT EDITING INTO SPECIALIZED

TIME & DATE KEYBOARD

Page 72: Droidcon2013 android experience lahoda

DIRECT MANIPULATION GESTURE

Page 73: Droidcon2013 android experience lahoda

“KEYBOARD” FOR DATE SELECTION

Page 74: Droidcon2013 android experience lahoda

NO TOUCH AT ALL

Page 75: Droidcon2013 android experience lahoda

KINETIC GESTURES

Page 76: Droidcon2013 android experience lahoda

SHAKE GESTURE

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{ if (motion == UIEventSubtypeMotionShake) { [self showAlert]; }} //When a gesture is detected (and ended) the showAlert method is called. -(IBAction)showAlert{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"ShakeGesture Demo" message:@"Shake detected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show];}

Page 77: Droidcon2013 android experience lahoda

AREA THAT IS NOT GETTING THE LOVE IT DESERVERS

Page 78: Droidcon2013 android experience lahoda

TIM BRAY : SENSPLORE

Page 80: Droidcon2013 android experience lahoda

SAMSUNG GESTURES

Page 81: Droidcon2013 android experience lahoda

HELP US SHAPE THE FUTURE

http://www.kineticgestures.org

Page 82: Droidcon2013 android experience lahoda

TAKEWAY

Page 83: Droidcon2013 android experience lahoda

Q & A

Page 84: Droidcon2013 android experience lahoda

THANK YOU