Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to Achieve the Best Experience for Multi-Window

How to Achieve the Best Experience for Multi-Window

If you aren’t handling config changes in your app and you plan on targeting Android N, you may be in for a rude awakening. Unlike most features released Multi-Window happens to be opt out only. What this means for you and your users is a whole new way to experience your app. Let’s talk about how to manage upgrading your app and how multi-window affects your design and some possible strategies to make this the best experience for your users.

9904145db476b6658d75fff27b1929ed?s=128

Elliott Chenger

September 30, 2016
Tweet

Transcript

  1. HOW TO ACHIEVE THE BEST EXPERIENCE FOR MULTI-WINDOW ELLIOTT CHENGER

    @echenger
  2. • What is Multi-Window • How Multi-Window Affects Design •

    Upgrading to Multi-Window • Best Experience for Multi-Window HOW TO ACHIEVE THE BEST EXPERIENCE FOR MULTI-WINDOW 2
  3. WHAT IS MULTI-WINDOW?

  4. None
  5. None
  6. None
  7. THREE MODES

  8. SPLIT-SCREEN

  9. PICTURE-IN-PICTURE

  10. FREE-FORM

  11. HOW MULTI-WINDOW AFFECTS DESIGN

  12. LESS REAL-ESTATE

  13. None
  14. WIDGETS

  15. SIDE NAVIGATION

  16. APP BAR 56 DP 16 DP 48 DP 14 DP

  17. APP BAR 56 DP 16 DP 48 DP 14 DP

    Not a typo, material design has DP for app bar title
  18. FAB SIZE_AUTO 56 DP 40 DP

  19. z FAB 19 case SIZE_AUTO:
 // If we're set to

    auto, grab the size from resources and refresh
 final int width = ConfigurationHelper.getScreenWidthDp(res);
 final int height = ConfigurationHelper.getScreenHeightDp(res);
 return Math.max(width, height) < AUTO_MINI_LARGEST_SCREEN_WIDTH
 ? getSizeDimension(SIZE_MINI)
 : getSizeDimension(SIZE_NORMAL);
  20. z FAB 20 case SIZE_AUTO:
 // If we're set to

    auto, grab the size from resources and refresh
 final int width = ConfigurationHelper.getScreenWidthDp(res);
 final int height = ConfigurationHelper.getScreenHeightDp(res);
 return Math.max(width, height) < AUTO_MINI_LARGEST_SCREEN_WIDTH
 ? getSizeDimension(SIZE_MINI)
 : getSizeDimension(SIZE_NORMAL);
  21. z FAB 21 /**
 * The switch point for the

    largest screen edge where SIZE_AUTO switches from mini to normal.
 */
 private static final int AUTO_MINI_LARGEST_SCREEN_WIDTH = 470;
  22. LAYOUTS

  23. PORTRAIT VS LANDSCAPE

  24. PORTRAIT VS LANDSCAPE

  25. SMALLEST WIDTH

  26. SMALLEST WIDTH

  27. CUSTOM VIEWS

  28. CUSTOM VIEWS

  29. CUSTOM VIEWS

  30. z HOW MULTI-WINDOW AFFECTS YOUR DESIGN 30 - Less Real-estate

    - UX of Widgets affected - Orientation or Screen Specific Layouts May not work - Custom Views
  31. UPGRADING TO MULTI-WINDOW

  32. TARGETING API < 24

  33. YES YOUR APP MAY SUPPORT MULTI-WINDOW

  34. YES YOUR APP MAY SUPPORT MULTI-WINDOW SPLIT-SCREEN AND FREE-FORM

  35. 35 LEGACY SUPPORT API < 24 <activity android:name=".MainActivity">
 <intent-filter>
 <action

    android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
  36. YOU’RE NOT CRAZY THERE IS NOTHING SPECIAL ABOUT THAT

  37. 37 LEGACY SUPPORT API < 24 android:screenOrientation=["unspecified" | "behind" |

    "landscape" | "portrait" | "reverseLandscape" | "reversePortrait" | "sensorLandscape" | "sensorPortrait" | "userLandscape" | "userPortrait" | "sensor" | "fullSensor" | "nosensor" | "user" | "fullUser" | "locked"]
  38. TARGETING API >= 24

  39. WARNING! MULTI-WINDOW IS ENABLED BY DEFAULT

  40. IF YOU DON’T WANT MULTI-WINDOW ?

  41. APP WIDE OR ACTIVITY SPECIFIC

  42. 42 DISABLING OR ENABLING MULTI-WINDOW <application
 android:allowBackup="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:supportsRtl="true"


    android:resizeableActivity="true|false"
 android:theme="@style/AppTheme">

  43. 43 DISABLING OR ENABLING MULTI-WINDOW <application
 android:allowBackup="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:supportsRtl="true"


    android:resizeableActivity="true|false"
 android:theme="@style/AppTheme">

  44. 44 DISABLING OR ENABLING MULTI-WINDOW <activity
 android:name=".examples.ShareActivity"
 android:label="@string/title_activity_share"
 android:resizeableActivity="true|false" />

  45. 45 DISABLING OR ENABLING MULTI-WINDOW <activity
 android:name=".examples.ShareActivity"
 android:label="@string/title_activity_share"
 android:resizeableActivity="true|false" />

  46. FREEFORM

  47. 47 FREEFORM LAYOUT DEFAULTS android:defaultHeight=“some dp" android:defaultWidth=“some dp" android:gravity=“some view

    gravity" android:minHeight="some dp" android:minWidth="some dp"
  48. SPLIT-SCREEN

  49. 49 SPLIT-SCREEN LAYOUT DEFAULTS android:minHeight="some dp" android:minWidth="some dp"

  50. ACTIVITY/FRAGMENT

  51. DON’T UNREGISTER ONPAUSE

  52. None
  53. DON’T DO TOO MUCH ONRESUME

  54. NEW METHODS

  55. 55 ACTIVITY/FRAGMENT isInMultiWindowMode() isInPictureInPictureMode() onMultiWindowModeChanged() onPictureInPictureModeChanged() Fragment.onMultiWindowModeChanged()

  56. CONFIG CHANGES

  57. HANDLE CONFIG CHANGES

  58. 58 HANDLING CONFIG CHANGES <activity
 android:name=".examples.ConfigChangesHandledActivity"
 android:configChanges=“screenSize|smallestScreenSize| screenLayout|orientation"
 android:resizeableActivity="true" />

  59. 59 HANDLING CONFIG CHANGES <activity
 android:name=".examples.ConfigChangesHandledActivity"
 android:configChanges=“screenSize|smallestScreenSize| screenLayout|orientation"
 android:resizeableActivity="true" />

  60. 60 HANDLING CONFIG CHANGES @Override
 public void onConfigurationChanged(Configuration newConfig) {


    super.onConfigurationChanged(newConfig);
 }
  61. Pros • One layout • No marshaling of data saved

    before activity destroyed • No re-inflation HANDLE CONFIG CHANGES 61 Cons • Layout invalidation and redrawing • Re-architecture of screen to be responsive • Multiple configs change at once
  62. LET ANDROID HANDLE CONFIG CHANGES

  63. CARRY ON

  64. Pros • Resources Qualifiers are your best friends • Less

    upfront engineering effort ANDROID HANDLE CONFIG CHANGES 64 Cons • Possible unnecessary layout and redrawing • Activity Creation can be costly • Marshaling data unnecessary
  65. NOT ONE APPROACH THAT IS BETTER THAN THE OTHER

  66. ADJACENT ACTIVITIES

  67. None
  68. 68 ADJACENT ACTIVITIES intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);


  69. z UPGRADING TO MULTI-WINDOW 69 - Legacy Apps may work

    in multi-window - Enable/Disable when targeting API 24 - Updates to Activity and Fragments - How to handle Config Changes or Not - Adjacent Activities
  70. BEST EXPERIENCE FOR MULTI-WINDOW

  71. https://material.google.com/layout/responsive-ui.html

  72. ADOPT RESPONSIVE UI PATTERNS

  73. ANDROID HANDLES CONFIG CHANGES?

  74. LEAN ON RESOURCE QUALIFIERS

  75. 75 RESOURCE QUALIFIERS MyProject/ src/ MyActivity.java res/ drawable/ graphic.png layout/

    main.xml info.xml mipmap/ icon.png values/ strings.xml
  76. 76 RESOURCE QUALIFIERS MyProject/ src/ MyActivity.java res/ drawable/ graphic.png layout/

    main.xml info.xml mipmap/ icon.png values/ strings.xml
  77. 77 RESOURCE QUALIFIERS MyProject/ src/ MyActivity.java res/ drawable-<qualifier>/ graphic.png layout-<qualifier>/

    main.xml info.xml mipmap-<qualifier>/ icon.png values-<qualifier>/ strings.xml
  78. 78 RESOURCE QUALIFIERS layout/ layout-sw600dp/ layout-sw330dp-h230dp/ layout-sw330dp-h320dp/ layout-sw330dp-h400dp/

  79. None
  80. 411 336 336 336 659 418 324 231

  81. 411 336 336 336 659 418 324 231 SMALLEST WIDTH

    HEIGHT
  82. YOU HANDLE CONFIG CHANGES

  83. COORDINATOR LAYOUT

  84. 84 ACTIVITY/FRAGMENT @Override
 public boolean layoutDependsOn(CoordinatorLayout parent, View child, View

    dependency) {
 return dependency instanceof ImageView;
 }
  85. 85 ACTIVITY/FRAGMENT @Override
 public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View

    dependency) {
  86. 86 ACTIVITY/FRAGMENT Configuration configuration = parent.getContext().getResources().getConfiguration();
 int smallestWidth = configuration.smallestScreenWidthDp;


    int smallestWidthBucket = Breakpoint.getSmallestWidthBucket(smallestWidth);
 switch (smallestWidthBucket) {
 case Breakpoint.SW_200:
 break;
 case Breakpoint.SW_300:
 break;
 case Breakpoint.SW_400:
 default:
 }

  87. 87 ACTIVITY/FRAGMENT Configuration configuration = parent.getContext().getResources().getConfiguration();
 int smallestWidth = configuration.smallestScreenWidthDp;


    int smallestWidthBucket = Breakpoint.getSmallestWidthBucket(smallestWidth);
 switch (smallestWidthBucket) {
 case Breakpoint.SW_200:
 break;
 case Breakpoint.SW_300:
 break;
 case Breakpoint.SW_400:
 default:
 }

  88. 88 ACTIVITY/FRAGMENT Configuration configuration = parent.getContext().getResources().getConfiguration();
 int smallestWidth = configuration.smallestScreenWidthDp;


    int smallestWidthBucket = Breakpoint.getSmallestWidthBucket(smallestWidth);
 switch (smallestWidthBucket) {
 case Breakpoint.SW_200:
 break;
 case Breakpoint.SW_300:
 break;
 case Breakpoint.SW_400:
 default:
 }

  89. 89 ACTIVITY/FRAGMENT Configuration configuration = parent.getContext().getResources().getConfiguration();
 int smallestWidth = configuration.smallestScreenWidthDp;


    int smallestWidthBucket = Breakpoint.getSmallestWidthBucket(smallestWidth);
 switch (smallestWidthBucket) {
 case Breakpoint.SW_200:
 break;
 case Breakpoint.SW_300:
 break;
 case Breakpoint.SW_400:
 default:
 }

  90. 90 ACTIVITY/FRAGMENT Configuration configuration = parent.getContext().getResources().getConfiguration();
 int smallestWidth = configuration.smallestScreenWidthDp;


    int smallestWidthBucket = Breakpoint.getSmallestWidthBucket(smallestWidth);
 switch (smallestWidthBucket) {
 case Breakpoint.SW_200:
 break;
 case Breakpoint.SW_300:
 break;
 case Breakpoint.SW_400:
 default:
 }

  91. z BEST EXPERIENCE FOR MULTI-WINDOW 91 - Change your design

    process - Develop breakpoints - Responsive UI - Lean on resource qualifiers for break points - Explore new technologies like CoordinatorLayout
  92. • Test your app on N, with and without targeting

    N • Design Auditing • Fluid Layouts • Responsive UI • Future Proof • Lean on Resources Configurations and Qualifiers FINALLY 92
  93. Thanks! @ECHENGER