SlideShare a Scribd company logo
Responsive mobile
design in practice
     Kirill Grouchnikov
    Android, Google Inc.
this talk is about

minimizing the pain of developing
    for multiple form factors
device variety


          Experia Pro 3.7”                  Flyer 7”                     Sony Tablet S 9.4”

Archos 2.8”              Galaxy Note 5.2”              Galaxy Tab 8.9”                    Toshiba Excite 13”
device orientation




1024*600    600*1024
adapting to the context
maps




“show more” of the infinite canvas
settings




combine two (or more) screens
    in a multi-pane layout
youtube (view)




  promote two tabs
  into the side panel
play store (details)




rearrange content in two columns
responsive mobile design
same content,
  same hierarchy

adapting to context
http://developer.android.com/design/patterns/multi-pane-layouts.html
same content,
   same hierarchy

adapting to context
minimizing the pain of developing
    for multiple form factors
same content, same hierarchy
differently stacked “blocks”
summary




screenshots




byline

+1



description
summary
screenshots
description
reviews
more by
developer links
cross-sell
flag content




rate & review
auto-update (apps)
trailer (movies)
song list (albums)
same blocks
rearranged in two columns
Responsive mobile design in practice
same building block on the same screen
     on different form factors
same building block
in different screens
Responsive mobile design in practice
res/layout/youtube_trailer_section.xml
<com.my.package.YoutubeTrailerSection>
    <ImageView
        android:id=”@+id/thumbnail”
        android:background=”black” />
    <ImageView
        android:id=”@+id/play_icon”
        android:src=”@drawable/ic_video_play” />
    <TextView
        android:id=”@+id/duration”
        android:textColor=”#CCCCCC”
        android:background=”#4C000000”
        android:textSize=”@dimen/content_primary” />
</com.my.package.YoutubeTrailerSection>
public class YoutubeTrailerSection
    extends TheMostSuitableBaseLayout

@Override onFinishInflate()
bind(YoutubeTrailerData)

@Override onMeasure() - if needed
@Override onLayout() - if needed
<com.my.package.YoutubeTrailerSection>
    <ImageView
        android:id=”@+id/thumbnail”
        android:background=”black” />
    <ImageView
        android:id=”@+id/play_icon” // ID not necessary if not used in code
        android:src=”@drawable/ic_video_play” />
    <TextView
        android:id=”@+id/duration”
        android:textColor=”#CCCCCC”
        android:background=”#4C000000”
        android:textSize=”@dimen/content_primary” />
</com.my.package.YoutubeTrailerSection>



private ImageView mThumbnail;
private TextView mDuration;

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    mThumbnail = (ImageView) findViewById(R.id.thumbnail);
    mDuration = (TextView) findViewById(R.id.duration);
}
private ImageView mThumbnail;
private TextView mDuration;

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    mThumbnail = (ImageView) findViewById(R.id.thumbnail);
    mDuration = (TextView) findViewById(R.id.duration);
}



public void bind(YoutubeTrailerData data) {
    mDuration.setText(data.getFormattedLength());
    String thumbnailUrl = data.getThumbnailUrl();
    ImageUtils.load(mThumbnail, thumbnailUrl); // cache / network app code
    setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            Intent youtubeIntent = IntentUtils.createYoutubeIntent(
                   data.getVideoUrl());
            getContext().startActivity(youtubeIntent);
        }
    });
}
why so much trouble with a
      custom class?
encapsulation
<include
    layout=”@layout/youtube_trailer_section” />

YoutubeTrailerSection trailer =
    (YoutubeTrailerSection) findViewById
         (R.id.youtube_trailer_section);
trailer.bind(model.getYoutubeTrailerData());
each block is binding a subset of the data
  no matter what the context is
<include
    android:id=”@+id/summary_section”
    layout=”@layout/details_summary” />
<include
    android:id=”@+id/screenshots_section”
    layout=”@layout/details_screenshots” />
<include
    android:id=”@+id/byline_section”
    layout=”@layout/details_byline” />
<include
    android:id=”@+id/plusone_section”
    layout=”@layout/details_plusone” />
<include
    android:id=”@+id/description_section”
    layout=”@layout/details_text” />
...
ScreenshotsSection screenshots =
                         (ScreenshotsSection) findViewById
                              (R.id.screenshots_section);
                     screenshots.bind(model.getScreenshotsData());




                     TextSection description =
                         (TextSection) findViewById
                              (R.id.description_section);
                     description.bind(model.getDescriptionData());




* I can swear that some PMs seem to think that it’s really that simple
the main flow looks up a section
and passes the relevant data subset
and each section handles its own
 data binding, events and layout
             tweaks
<include
    layout=”@layout/screenshots_section” />

ScreenshotsSection trailer =
    (ScreenshotsSection) findViewById
         (R.id.screenshots_section);
trailer.bind(model.getScreenshotsData());
no knowledge of context,
internal IDs or event handling
each block is a separate reusable layout
include                include

          include
include                include


include   include
include   include   include
          include
include   include   include
it’s like combining Lego blocks*




  * except for the part where you’re stuck maintaining the code base
all I see is <include>s

* he was kind of a douche, fell in love with the wrong girl and after
that steak it really went downhill for him. YMMV.
the code doesn’t have to be
  aware what is the context
<include
    layout=”@layout/screenshots_section” />

ScreenshotsSection trailer =
    (ScreenshotsSection) findViewById
         (R.id.screenshots_section);
trailer.bind(model.getScreenshotsData());
welcome to the real world
font size, column count,
location of rating bar in cells
font size
res/values/font-dimens.xml
   <dimen name="content_primary_size">16sp</dimen>

res/values-sw800dp/font-dimens.xml
   <dimen name="content_primary_size">18sp</dimen>

res/values/styles.xml
   <style name="DetailsPage_Header">
       ...
       <item name=”android:textSize”>@dimen/content_primary_size</item>
   </style>

res/layout/pack_header.xml
   <TextView
      android:id=”+id/header”
      style=”@style/DetailsPage_Header”
      ...
column count
res/values/ints.xml
   <integer name="moreby_items_per_row">2</integer>

res/values-sw800dp/ints.xml
   <integer name="moreby_items_per_row">1</integer>

public class MoreBySection
   private int mColumnCount;

   public MoreBySection(Context ctx) {
       ...
       mColumnCount = ctx.getResources().getInteger(
           R.integer.moreby_items_per_row);
   }
cell layouts
res/layout/item_cell.xml
res/layout-sw800dp/item_cell.xml

public class PackAdapter

   @Override
   public View getView(int pos, View convertView, ViewGroup parent) {
       if (convertView == null) {
           convertView = mLayoutInflater.inflate(
               R.layout.item_cell, parent, false);
       }

       CellViewHolder holder = (CellViewHolder) convertView.getTag();
       ...
       return convertView;
   }
the code doesn’t have to be
  aware what is the context*



  * if you managed to confine the differences to resource files
not exactly the same blocks
context awareness “leaking”
      into the code
res/values/bools.xml
   <bool name="use_two_column_layout">false</bool>

res/values-sw800dp/bools.xml
   <bool name="use_two_column_layout">true</bool>
public class BylineSection

private boolean mIsTwoColumnMode;

public BylineSection(Context ctx) {
    ...
    mIsTwoColumnMode = ctx.getResources().getBoolean(
        R.bool.use_two_column_layout);
}

public void bind() {
    if (mIsTwoColumnMode) {
        // add update date, download size and download count
    } else {
        // add rating count, update date, download size
        // and download count
    }
}
reuse blocks
  on the same screen
on different form factors
<include
    layout=”@layout/screenshots_section” />

ScreenshotsSection trailer =
    (ScreenshotsSection) findViewById
         (R.id.screenshots_section);
trailer.bind(model.getScreenshotsData());
reuse blocks
in different screens
Responsive mobile design in practice
Responsive mobile design in practice
Responsive mobile design in practice
Responsive mobile design in practice
<include
    layout=”@layout/youtube_trailer_section” />

YoutubeTrailerSection trailer =
    (YoutubeTrailerSection) findViewById
         (R.id.youtube_trailer_section);
trailer.bind(model.getYoutubeTrailerData());
“my apps” screen
combine and share blocks
this talk was about

minimizing the pain of developing
    for multiple form factors
building blocks

•identify
• encapsulate
• reuse



 * almost made it through with no bullet points
Q&A

• slideshare.net/kirillcool
• pushing-pixels.org
• +Kirill Grouchnikov
• kirillcool@yahoo.com

More Related Content

PDF
Responsive mobile design
PPT
Android
PPT
Android 2
PDF
Константин Чернухо_Popups, alerts and windows
PDF
Dominando o Data Binding no Android
PDF
Dominando o Data Binding no Android
PDF
Programmers guide
PDF
Android development for iOS developers
Responsive mobile design
Android
Android 2
Константин Чернухо_Popups, alerts and windows
Dominando o Data Binding no Android
Dominando o Data Binding no Android
Programmers guide
Android development for iOS developers

Similar to Responsive mobile design in practice (20)

PDF
07_UIAndroid.pdf
PPTX
Compose In Practice
PDF
Building Modern Apps using Android Architecture Components
PDF
Different types of sticker apps
PPTX
Making it fit - DroidCon Paris 18 june 2013
DOCX
Android xml-based layouts-chapter5
PDF
Custom UI Components at Android Only 2011
ODP
Android App Development - 04 Views and layouts
PDF
"Android Data Binding в массы" Михаил Анохин
PDF
How to use data binding in android
PPT
Beginning Native Android Apps
PDF
MVVM & Data Binding Library
PPTX
Modern android development
PPTX
Android Tutorials : Basic widgets
PPTX
08ui.pptx
PPTX
Android Application Fundamentals.
PDF
Android por onde começar? Mini Curso Erbase 2015
PDF
Михаил Анохин "Data binding 2.0"
DOC
Android Application DevlopmentManual-1.doc
KEY
Design Patterns for Tablets and Smartphones
07_UIAndroid.pdf
Compose In Practice
Building Modern Apps using Android Architecture Components
Different types of sticker apps
Making it fit - DroidCon Paris 18 june 2013
Android xml-based layouts-chapter5
Custom UI Components at Android Only 2011
Android App Development - 04 Views and layouts
"Android Data Binding в массы" Михаил Анохин
How to use data binding in android
Beginning Native Android Apps
MVVM & Data Binding Library
Modern android development
Android Tutorials : Basic widgets
08ui.pptx
Android Application Fundamentals.
Android por onde começar? Mini Curso Erbase 2015
Михаил Анохин "Data binding 2.0"
Android Application DevlopmentManual-1.doc
Design Patterns for Tablets and Smartphones
Ad

More from Kirill Grouchnikov (7)

PPT
Designing for the mobile form factor
PDF
Substance Java One 2007 Community Corner
PDF
Flamingo Ribbon component
PDF
Party of One
PDF
Advanced Effects Oscon 2007
PDF
High DPI for desktop applications
PDF
On The Shoulders Of Giants
Designing for the mobile form factor
Substance Java One 2007 Community Corner
Flamingo Ribbon component
Party of One
Advanced Effects Oscon 2007
High DPI for desktop applications
On The Shoulders Of Giants
Ad

Recently uploaded (20)

PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
NewMind AI Monthly Chronicles - July 2025
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Approach and Philosophy of On baking technology
PDF
Encapsulation theory and applications.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Electronic commerce courselecture one. Pdf
20250228 LYD VKU AI Blended-Learning.pptx
Big Data Technologies - Introduction.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
“AI and Expert System Decision Support & Business Intelligence Systems”
Building Integrated photovoltaic BIPV_UPV.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
NewMind AI Monthly Chronicles - July 2025
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
The AUB Centre for AI in Media Proposal.docx
Approach and Philosophy of On baking technology
Encapsulation theory and applications.pdf
Unlocking AI with Model Context Protocol (MCP)
Diabetes mellitus diagnosis method based random forest with bat algorithm
Understanding_Digital_Forensics_Presentation.pptx
Electronic commerce courselecture one. Pdf

Responsive mobile design in practice

  • 1. Responsive mobile design in practice Kirill Grouchnikov Android, Google Inc.
  • 2. this talk is about minimizing the pain of developing for multiple form factors
  • 3. device variety Experia Pro 3.7” Flyer 7” Sony Tablet S 9.4” Archos 2.8” Galaxy Note 5.2” Galaxy Tab 8.9” Toshiba Excite 13”
  • 5. adapting to the context
  • 6. maps “show more” of the infinite canvas
  • 7. settings combine two (or more) screens in a multi-pane layout
  • 8. youtube (view) promote two tabs into the side panel
  • 9. play store (details) rearrange content in two columns
  • 11. same content, same hierarchy adapting to context
  • 13. same content, same hierarchy adapting to context
  • 14. minimizing the pain of developing for multiple form factors
  • 15. same content, same hierarchy differently stacked “blocks”
  • 17. summary screenshots description reviews more by developer links cross-sell flag content rate & review auto-update (apps) trailer (movies) song list (albums)
  • 20. same building block on the same screen on different form factors
  • 21. same building block in different screens
  • 23. res/layout/youtube_trailer_section.xml <com.my.package.YoutubeTrailerSection> <ImageView android:id=”@+id/thumbnail” android:background=”black” /> <ImageView android:id=”@+id/play_icon” android:src=”@drawable/ic_video_play” /> <TextView android:id=”@+id/duration” android:textColor=”#CCCCCC” android:background=”#4C000000” android:textSize=”@dimen/content_primary” /> </com.my.package.YoutubeTrailerSection>
  • 24. public class YoutubeTrailerSection extends TheMostSuitableBaseLayout @Override onFinishInflate() bind(YoutubeTrailerData) @Override onMeasure() - if needed @Override onLayout() - if needed
  • 25. <com.my.package.YoutubeTrailerSection> <ImageView android:id=”@+id/thumbnail” android:background=”black” /> <ImageView android:id=”@+id/play_icon” // ID not necessary if not used in code android:src=”@drawable/ic_video_play” /> <TextView android:id=”@+id/duration” android:textColor=”#CCCCCC” android:background=”#4C000000” android:textSize=”@dimen/content_primary” /> </com.my.package.YoutubeTrailerSection> private ImageView mThumbnail; private TextView mDuration; @Override protected void onFinishInflate() { super.onFinishInflate(); mThumbnail = (ImageView) findViewById(R.id.thumbnail); mDuration = (TextView) findViewById(R.id.duration); }
  • 26. private ImageView mThumbnail; private TextView mDuration; @Override protected void onFinishInflate() { super.onFinishInflate(); mThumbnail = (ImageView) findViewById(R.id.thumbnail); mDuration = (TextView) findViewById(R.id.duration); } public void bind(YoutubeTrailerData data) { mDuration.setText(data.getFormattedLength()); String thumbnailUrl = data.getThumbnailUrl(); ImageUtils.load(mThumbnail, thumbnailUrl); // cache / network app code setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent youtubeIntent = IntentUtils.createYoutubeIntent( data.getVideoUrl()); getContext().startActivity(youtubeIntent); } }); }
  • 27. why so much trouble with a custom class?
  • 29. <include layout=”@layout/youtube_trailer_section” /> YoutubeTrailerSection trailer = (YoutubeTrailerSection) findViewById (R.id.youtube_trailer_section); trailer.bind(model.getYoutubeTrailerData());
  • 30. each block is binding a subset of the data no matter what the context is
  • 31. <include android:id=”@+id/summary_section” layout=”@layout/details_summary” /> <include android:id=”@+id/screenshots_section” layout=”@layout/details_screenshots” /> <include android:id=”@+id/byline_section” layout=”@layout/details_byline” /> <include android:id=”@+id/plusone_section” layout=”@layout/details_plusone” /> <include android:id=”@+id/description_section” layout=”@layout/details_text” /> ...
  • 32. ScreenshotsSection screenshots = (ScreenshotsSection) findViewById (R.id.screenshots_section); screenshots.bind(model.getScreenshotsData()); TextSection description = (TextSection) findViewById (R.id.description_section); description.bind(model.getDescriptionData()); * I can swear that some PMs seem to think that it’s really that simple
  • 33. the main flow looks up a section and passes the relevant data subset
  • 34. and each section handles its own data binding, events and layout tweaks
  • 35. <include layout=”@layout/screenshots_section” /> ScreenshotsSection trailer = (ScreenshotsSection) findViewById (R.id.screenshots_section); trailer.bind(model.getScreenshotsData());
  • 36. no knowledge of context, internal IDs or event handling
  • 37. each block is a separate reusable layout
  • 38. include include include include include include include include include include include include include include
  • 39. it’s like combining Lego blocks* * except for the part where you’re stuck maintaining the code base
  • 40. all I see is <include>s * he was kind of a douche, fell in love with the wrong girl and after that steak it really went downhill for him. YMMV.
  • 41. the code doesn’t have to be aware what is the context
  • 42. <include layout=”@layout/screenshots_section” /> ScreenshotsSection trailer = (ScreenshotsSection) findViewById (R.id.screenshots_section); trailer.bind(model.getScreenshotsData());
  • 43. welcome to the real world
  • 44. font size, column count, location of rating bar in cells
  • 45. font size res/values/font-dimens.xml <dimen name="content_primary_size">16sp</dimen> res/values-sw800dp/font-dimens.xml <dimen name="content_primary_size">18sp</dimen> res/values/styles.xml <style name="DetailsPage_Header"> ... <item name=”android:textSize”>@dimen/content_primary_size</item> </style> res/layout/pack_header.xml <TextView android:id=”+id/header” style=”@style/DetailsPage_Header” ...
  • 46. column count res/values/ints.xml <integer name="moreby_items_per_row">2</integer> res/values-sw800dp/ints.xml <integer name="moreby_items_per_row">1</integer> public class MoreBySection private int mColumnCount; public MoreBySection(Context ctx) { ... mColumnCount = ctx.getResources().getInteger( R.integer.moreby_items_per_row); }
  • 47. cell layouts res/layout/item_cell.xml res/layout-sw800dp/item_cell.xml public class PackAdapter @Override public View getView(int pos, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mLayoutInflater.inflate( R.layout.item_cell, parent, false); } CellViewHolder holder = (CellViewHolder) convertView.getTag(); ... return convertView; }
  • 48. the code doesn’t have to be aware what is the context* * if you managed to confine the differences to resource files
  • 49. not exactly the same blocks
  • 51. res/values/bools.xml <bool name="use_two_column_layout">false</bool> res/values-sw800dp/bools.xml <bool name="use_two_column_layout">true</bool>
  • 52. public class BylineSection private boolean mIsTwoColumnMode; public BylineSection(Context ctx) { ... mIsTwoColumnMode = ctx.getResources().getBoolean( R.bool.use_two_column_layout); } public void bind() { if (mIsTwoColumnMode) { // add update date, download size and download count } else { // add rating count, update date, download size // and download count } }
  • 53. reuse blocks on the same screen on different form factors
  • 54. <include layout=”@layout/screenshots_section” /> ScreenshotsSection trailer = (ScreenshotsSection) findViewById (R.id.screenshots_section); trailer.bind(model.getScreenshotsData());
  • 60. <include layout=”@layout/youtube_trailer_section” /> YoutubeTrailerSection trailer = (YoutubeTrailerSection) findViewById (R.id.youtube_trailer_section); trailer.bind(model.getYoutubeTrailerData());
  • 63. this talk was about minimizing the pain of developing for multiple form factors
  • 64. building blocks •identify • encapsulate • reuse * almost made it through with no bullet points
  • 65. Q&A • slideshare.net/kirillcool • pushing-pixels.org • +Kirill Grouchnikov • kirillcool@yahoo.com