SlideShare a Scribd company logo
1 of 65
Download to read offline
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
same building block on the same screen
     on different form factors
same building block
in different screens
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
<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

Similar to Responsive mobile design in practice

Making it fit - DroidCon Paris 18 june 2013
Making it fit - DroidCon Paris 18 june 2013Making it fit - DroidCon Paris 18 june 2013
Making it fit - DroidCon Paris 18 june 2013
Paris Android User Group
 
Custom UI Components at Android Only 2011
Custom UI Components at Android Only 2011Custom UI Components at Android Only 2011
Custom UI Components at Android Only 2011
Johan Nilsson
 

Similar to Responsive mobile design in practice (20)

07_UIAndroid.pdf
07_UIAndroid.pdf07_UIAndroid.pdf
07_UIAndroid.pdf
 
Compose In Practice
Compose In PracticeCompose In Practice
Compose In Practice
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Different types of sticker apps
Different types of sticker appsDifferent types of sticker apps
Different types of sticker apps
 
Making it fit - DroidCon Paris 18 june 2013
Making it fit - DroidCon Paris 18 june 2013Making it fit - DroidCon Paris 18 june 2013
Making it fit - DroidCon Paris 18 june 2013
 
Android xml-based layouts-chapter5
Android xml-based layouts-chapter5Android xml-based layouts-chapter5
Android xml-based layouts-chapter5
 
Custom UI Components at Android Only 2011
Custom UI Components at Android Only 2011Custom UI Components at Android Only 2011
Custom UI Components at Android Only 2011
 
Android App Development - 04 Views and layouts
Android App Development - 04 Views and layoutsAndroid App Development - 04 Views and layouts
Android App Development - 04 Views and layouts
 
"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин"Android Data Binding в массы" Михаил Анохин
"Android Data Binding в массы" Михаил Анохин
 
How to use data binding in android
How to use data binding in androidHow to use data binding in android
How to use data binding in android
 
Beginning Native Android Apps
Beginning Native Android AppsBeginning Native Android Apps
Beginning Native Android Apps
 
MVVM & Data Binding Library
MVVM & Data Binding Library MVVM & Data Binding Library
MVVM & Data Binding Library
 
Modern android development
Modern android developmentModern android development
Modern android development
 
Android Tutorials : Basic widgets
Android Tutorials : Basic widgetsAndroid Tutorials : Basic widgets
Android Tutorials : Basic widgets
 
08ui.pptx
08ui.pptx08ui.pptx
08ui.pptx
 
Android Application Fundamentals.
Android Application Fundamentals.Android Application Fundamentals.
Android Application Fundamentals.
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015
 
Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"Михаил Анохин "Data binding 2.0"
Михаил Анохин "Data binding 2.0"
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
Android apps development
Android apps developmentAndroid apps development
Android apps development
 

More from Kirill Grouchnikov (7)

Designing for the mobile form factor
Designing for the mobile form factorDesigning for the mobile form factor
Designing for the mobile form factor
 
Substance Java One 2007 Community Corner
Substance Java One 2007  Community  CornerSubstance Java One 2007  Community  Corner
Substance Java One 2007 Community Corner
 
Flamingo Ribbon component
Flamingo Ribbon componentFlamingo Ribbon component
Flamingo Ribbon component
 
Party of One
Party of OneParty of One
Party of One
 
Advanced Effects Oscon 2007
Advanced Effects   Oscon 2007Advanced Effects   Oscon 2007
Advanced Effects Oscon 2007
 
High DPI for desktop applications
High DPI for desktop applicationsHigh DPI for desktop applications
High DPI for desktop applications
 
On The Shoulders Of Giants
On The Shoulders Of GiantsOn The Shoulders Of Giants
On The Shoulders Of Giants
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 

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)
  • 19.
  • 20. same building block on the same screen on different form factors
  • 21. same building block in different screens
  • 22.
  • 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());
  • 56.
  • 57.
  • 58.
  • 59.
  • 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