nicola corti - building ui consistent android apps - codemotion milan 2017
TRANSCRIPT
![Page 1: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/1.jpg)
Building UI Consistent Android AppsNicola Corti @cortinico
![Page 2: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/2.jpg)
![Page 3: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/3.jpg)
Yelp Mission
Connecting people with great local businesses.
![Page 5: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/5.jpg)
What is Consistency?
![Page 6: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/6.jpg)
“ Unified use of Design Elements, such as color, typography, spatial layout and behaviors.
![Page 7: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/7.jpg)
Functional
Internal ConsistencyVisual
![Page 8: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/8.jpg)
External Consistency - Across Product
![Page 9: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/9.jpg)
External Consistency - Across Platform
![Page 10: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/10.jpg)
Benefits• Learnability
• Reduce frustrations
• Save money/time 💰
Photo by davelawler/CC BY - NC
![Page 11: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/11.jpg)
How to tackle Consistency?
![Page 12: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/12.jpg)
⌘ R ⇧ + +
![Page 14: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/14.jpg)
![Page 15: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/15.jpg)
External Examples• Google Material Design
• Apple Design Guidelines
• Github Primer
http://styleguides.io/
![Page 16: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/16.jpg)
github.com/alexpate/awesome-design-systems
![Page 18: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/18.jpg)
Consistency @Yelp
![Page 19: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/19.jpg)
Mobile Apps
![Page 20: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/20.jpg)
![Page 21: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/21.jpg)
![Page 22: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/22.jpg)
yelp.com/styleguide
![Page 23: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/23.jpg)
![Page 24: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/24.jpg)
![Page 25: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/25.jpg)
The Android Styleguide Library
![Page 26: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/26.jpg)
Design Build Share
![Page 27: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/27.jpg)
Design
![Page 28: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/28.jpg)
Does it fit?• Can it be reused?
• Is it visible to the user?
• Development plan?
![Page 29: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/29.jpg)
User photo User name timestamp
friends, media
checkins
Elite badge
description
![Page 30: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/30.jpg)
Attributes
<resources></resources>
![Page 31: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/31.jpg)
Attributes
<resources> <declare-styleable name="UserPassport"> </declare-styleable></resources>
![Page 32: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/32.jpg)
Attributes
<resources> <declare-styleable name="UserPassport"> <!-- Determines user's name --> <attr name="userPassportName" format="string"/> </declare-styleable></resources>
![Page 33: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/33.jpg)
Attributes
<resources> <declare-styleable name="UserPassport"> <!-- Determines user's name --> <attr name="userPassportName" format="string"/> <!-- Determines user's description/role --> <attr name="userPassportDescription" format="string"/> </declare-styleable></resources>
![Page 34: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/34.jpg)
Attributes
<resources> <declare-styleable name="UserPassport"> <!-- Determines user's name --> <attr name="userPassportName" format="string"/> <!-- Determines user's description/role --> <attr name="userPassportDescription" format="string"/> </declare-styleable> <attr name="userPassportStyle" format="reference"/></resources>
![Page 35: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/35.jpg)
Theme
![Page 36: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/36.jpg)
Theme<resources> <!—- This theme is the parent of all themes of Yelp's android apps. —-> <style name="YelpStyleguideTheme"/> </resources>
![Page 37: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/37.jpg)
Theme<resources> <!—- This theme is the parent of all themes of Yelp's android apps. —-> <style name="YelpStyleguideTheme" parent=“Theme.AppCompat.Light.DarkActionBar"/></resources>
![Page 38: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/38.jpg)
Theme<resources> <!—- This theme is the parent of all themes of Yelp's android apps. —-> <style name="YelpStyleguideTheme" parent=“Theme.AppCompat.Light.DarkActionBar"> <item name="userPassportStyle">@style/UserPassport</item> </style></resources>
![Page 39: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/39.jpg)
Styles
![Page 40: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/40.jpg)
Styles
<style name=“UserPassport"/>
![Page 41: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/41.jpg)
Styles
<style name=“UserPassport"> <item name="userPassportName">Joe Smith</item></style>
![Page 42: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/42.jpg)
Styles
<style name=“UserPassport"> <item name="userPassportName">Joe Smith</item> <item name="userPassportDescription">Owner of Sample Business</item></style>
![Page 43: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/43.jpg)
UserPassport
![Page 44: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/44.jpg)
public class UserPassport extends RelativeLayout {
![Page 45: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/45.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription;
![Page 46: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/46.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; public void setName(String name) { mUserName.setText(name); }
![Page 47: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/47.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; public void setName(String name) { mUserName.setText(name); } public void setDescription(String description) { if (TextUtils.isEmpty(description)) { mDescription.setVisibility(GONE); } else { mDescription.setVisibility(VISIBLE); mDescription.setText(description); } }
![Page 48: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/48.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription;
![Page 49: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/49.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; public UserPassport(final Context context) { super(context); init(context, null, 0); } public UserPassport(final Context context, final AttributeSet attrs) { super(context, attrs); init(context, attrs, R.attr.userPassportStyle); } public UserPassport(final Context context, final AttributeSet attrs, final int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); }
![Page 50: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/50.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; public UserPassport(final Context context) { super(context); init(context, null, 0); } public UserPassport(final Context context, final AttributeSet attrs) { super(context, attrs); init(context, attrs, R.attr.userPassportStyle); } public UserPassport(final Context context, final AttributeSet attrs, final int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); }
![Page 51: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/51.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { }
![Page 52: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/52.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { LayoutInflater.from(context).inflate(R.layout.user_passport, this, true); }
![Page 53: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/53.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { LayoutInflater.from(context).inflate(R.layout.user_passport, this, true); mUserName = (TextView) findViewById(R.id.user_name); mDescription = (TextView) findViewById(R.id.description); }
![Page 54: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/54.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { LayoutInflater.from(context).inflate(R.layout.user_passport, this, true); mUserName = (TextView) findViewById(R.id.user_name); mDescription = (TextView) findViewById(R.id.description); final TypedArray styles = context.obtainStyledAttributes(attrs, R.styleable.UserPassport, defStyleAttr, 0); }
![Page 55: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/55.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { LayoutInflater.from(context).inflate(R.layout.user_passport, this, true); mUserName = (TextView) findViewById(R.id.user_name); mDescription = (TextView) findViewById(R.id.description); final TypedArray styles = context.obtainStyledAttributes(attrs, R.styleable.UserPassport, defStyleAttr, 0); setName(styles.getString(R.styleable.UserPassport_userPassportName)); setDescription(styles.getString( R.styleable.UserPassport_userPassportDescription)); }
![Page 56: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/56.jpg)
public class UserPassport extends RelativeLayout { private TextView mUserName; private TextView mDescription; private void init( final Context context, final AttributeSet attrs, final int defStyleAttr) { LayoutInflater.from(context).inflate(R.layout.user_passport, this, true); mUserName = (TextView) findViewById(R.id.user_name); mDescription = (TextView) findViewById(R.id.description); final TypedArray styles = context.obtainStyledAttributes(attrs, R.styleable.UserPassport, defStyleAttr, 0); setName(styles.getString(R.styleable.UserPassport_userPassportName)); setDescription(styles.getString( R.styleable.UserPassport_userPassportDescription)); styles.recycle(); }
![Page 57: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/57.jpg)
<style name="UserPassport"> <item name="userPassportName">Joe Smith</item> <item name="userPassportDescription">@null</item> <item name="userPassportTint">@color/orange_dark_interface</item> <item name="userPassportNameColor">@color/black_regular_interface</item> <item name="userPassportSize">Regular</item> <item name="userPassportShowName">true</item> <item name="userPassportShowIcons">true</item> <item name="userPassportEliteYear">-1</item> <item name="userPassportFriends">0</item> <item name="userPassportReviews">0</item> <item name="userPassportPhotos">0</item> <item name="userPassportCheckIns">0</item> <item name="userPassportShowCheckIn">false</item></style>
![Page 58: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/58.jpg)
<style name="UserPassport.White"> <item name="userPassportName">Joe Smith</item> <item name="userPassportDescription">@null</item> <item name="userPassportTint">@color/orange_dark_interface</item> <item name="userPassportNameColor">@color/black_regular_interface</item> <item name="userPassportSize">Regular</item> <item name="userPassportShowName">true</item> <item name="userPassportShowIcons">true</item> <item name="userPassportEliteYear">-1</item> <item name="userPassportFriends">0</item> <item name="userPassportReviews">0</item> <item name="userPassportPhotos">0</item> <item name="userPassportCheckIns">0</item> <item name="userPassportShowCheckIn">false</item></style>
![Page 59: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/59.jpg)
<style name="UserPassport.White"> <item name="userPassportName">Joe Smith</item> <item name="userPassportDescription">@null</item> <item name="userPassportTint">@color/white_interface</item> <item name="userPassportNameColor">@color/white_interface</item> <item name="userPassportSize">Regular</item> <item name="userPassportShowName">true</item> <item name="userPassportShowIcons">true</item> <item name="userPassportEliteYear">-1</item> <item name="userPassportFriends">0</item> <item name="userPassportReviews">0</item> <item name="userPassportPhotos">0</item> <item name="userPassportCheckIns">0</item> <item name="userPassportShowCheckIn">false</item></style>
![Page 60: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/60.jpg)
<style name="UserPassport.White"> <item name="userPassportTint">@color/white_interface</item> <item name="userPassportNameColor">@color/white_interface</item></style>
![Page 61: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/61.jpg)
Color Palette
![Page 62: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/62.jpg)
Illustrations
![Page 63: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/63.jpg)
Assetsdependencies { // Yelp asset libs compile 'com.yelp:yelpicons:135.0.0' compile ‘com.yelp:yelpdesign:4.0.4’
}
![Page 64: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/64.jpg)
Assetsdependencies { // Yelp asset libs compile 'com.yelp:yelpicons:135.0.0' compile ‘com.yelp:yelpdesign:4.0.4’
}
![Page 65: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/65.jpg)
Color
![Page 66: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/66.jpg)
Color<color name="black_extra_light_interface">#666666</color><color name="black_regular_interface">#333333</color><color name="blue_dark_interface">#0073bb</color><color name="blue_extra_light_interface">#d0ecfb</color><color name="blue_regular_interface">#0097ec</color><color name="gray_dark_interface">#999999</color><color name="gray_extra_light_interface">#f5f5f5</color><color name="gray_light_interface">#e6e6e6</color><color name="gray_regular_interface">#cccccc</color><color name="green_extra_light_interface">#daecd2</color><color name="green_regular_interface">#41a700</color><color name="mocha_extra_light_interface">#f8e3c7</color><color name="mocha_light_interface">#f1bd79</color><color name="orange_dark_interface">#f15c00</color><color name="orange_extra_light_interface">#ffebcf</color><color name="purple_extra_light_interface">#dad1e4</color><color name="red_dark_interface">#d32323</color><color name="red_extra_light_interface">#fcd6d3</color><color name="slate_extra_light_interface">#cddae2</color><color name="white_interface">#ffffff</color><color name="yellow_dark_interface">#fec011</color><color name="yellow_extra_light_interface">#fff7cc</color>
![Page 67: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/67.jpg)
Color<color name="black_extra_light_interface">#666666</color><color name="black_regular_interface">#333333</color><color name="blue_dark_interface">#0073bb</color><color name="blue_extra_light_interface">#d0ecfb</color><color name="blue_regular_interface">#0097ec</color><color name="gray_dark_interface">#999999</color><color name="gray_extra_light_interface">#f5f5f5</color><color name="gray_light_interface">#e6e6e6</color><color name="gray_regular_interface">#cccccc</color><color name="green_extra_light_interface">#daecd2</color><color name="green_regular_interface">#41a700</color><color name="mocha_extra_light_interface">#f8e3c7</color><color name="mocha_light_interface">#f1bd79</color><color name="orange_dark_interface">#f15c00</color><color name="orange_extra_light_interface">#ffebcf</color><color name="purple_extra_light_interface">#dad1e4</color><color name="red_dark_interface">#d32323</color><color name="red_extra_light_interface">#fcd6d3</color><color name="slate_extra_light_interface">#cddae2</color><color name="white_interface">#ffffff</color><color name="yellow_dark_interface">#fec011</color><color name="yellow_extra_light_interface">#fff7cc</color>
![Page 68: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/68.jpg)
Color<color name="black_extra_light_interface">#666666</color><color name="black_regular_interface">#333333</color><color name="blue_dark_interface">#0073bb</color><color name="blue_extra_light_interface">#d0ecfb</color><color name="blue_regular_interface">#0097ec</color><color name="gray_dark_interface">#999999</color><color name="gray_extra_light_interface">#f5f5f5</color><color name="gray_light_interface">#e6e6e6</color><color name="gray_regular_interface">#cccccc</color><color name="green_extra_light_interface">#daecd2</color><color name="green_regular_interface">#41a700</color><color name="mocha_extra_light_interface">#f8e3c7</color><color name="mocha_light_interface">#f1bd79</color><color name="orange_dark_interface">#f15c00</color><color name="orange_extra_light_interface">#ffebcf</color><color name="purple_extra_light_interface">#dad1e4</color><color name="red_dark_interface">#d32323</color><color name="red_extra_light_interface">#fcd6d3</color><color name="slate_extra_light_interface">#cddae2</color><color name="white_interface">#ffffff</color><color name="yellow_dark_interface">#fec011</color><color name="yellow_extra_light_interface">#fff7cc</color>
![Page 69: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/69.jpg)
Build
![Page 70: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/70.jpg)
Review Template
![Page 71: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/71.jpg)
VCS & CI• git submodule
• Run the Build for
• submodule
• consumer app
• business app
![Page 72: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/72.jpg)
Custom Lint Checks
![Page 73: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/73.jpg)
Custom Lint Checks
Button b = new Button(context); SwitchCompat switchCompat = new SwitchCompat(context); Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 74: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/74.jpg)
Custom Lint Checks
@SuppressLint("") Button b = new Button(context); @SuppressLint("") SwitchCompat switchCompat = new SwitchCompat(context); @SuppressLint("") Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 75: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/75.jpg)
Custom Lint Checks
@SuppressLint("NonStyleguideButtonInstance") Button b = new Button(context); @SuppressLint("") SwitchCompat switchCompat = new SwitchCompat(context); @SuppressLint("") Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 76: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/76.jpg)
Custom Lint Checks
@SuppressLint("NonStyleguideButtonInstance") Button b = new Button(context); @SuppressLint("NonStyleguideToggleInstance") SwitchCompat switchCompat = new SwitchCompat(context); @SuppressLint("") Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 77: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/77.jpg)
Custom Lint Checks
@SuppressLint("NonStyleguideButtonInstance") Button b = new Button(context); @SuppressLint("NonStyleguideToggleInstance") SwitchCompat switchCompat = new SwitchCompat(context); @SuppressLint("NonStyleguideSnackbarInstance") Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 78: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/78.jpg)
Custom Lint Checks
// Using stock Button because […] + Ticket number. @SuppressLint("NonStyleguideButtonInstance") Button b = new Button(context); @SuppressLint("NonStyleguideToggleInstance") SwitchCompat switchCompat = new SwitchCompat(context); @SuppressLint("NonStyleguideSnackbarInstance") Snackbar.make(getRootView(), “Test”, LENGTH_SHORT).show();
![Page 79: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/79.jpg)
Custom Lint Checks
![Page 80: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/80.jpg)
Custom Lint Checks
<Button android:layout_width="match_parent" android:layout_height="match_parent" /><Switch android:layout_width="match_parent" android:layout_height="match_parent" />
![Page 81: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/81.jpg)
Custom Lint Checks
<Button android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="NonStyleguideButtonTag" /><Switch android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="NonStyleguideToggleTag" />
![Page 82: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/82.jpg)
build.gradle
![Page 83: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/83.jpg)
build.gradle
android { lintOptions { }}
![Page 84: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/84.jpg)
build.gradle
android { lintOptions { abortOnError true warningsAsErrors true }}
![Page 85: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/85.jpg)
build.gradle
android { lintOptions { abortOnError true warningsAsErrors true lintConfig file("lint.xml") }}
![Page 86: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/86.jpg)
build.gradle
android { lintOptions { abortOnError true warningsAsErrors true lintConfig file("lint.xml") baseline file("lint-baseline.xml") }}
![Page 87: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/87.jpg)
Test your component• Your component ❤ Espresso?
• Do you handle state changes?
• contentDescription ?
![Page 88: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/88.jpg)
Share
![Page 89: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/89.jpg)
Documentation• Provide Javadoc
• Add Screenshots
• Document Attributes
• Document Styles
![Page 90: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/90.jpg)
Screenshots capture• v0.1: Manual Screenshots
• v0.2: Automated locally
• v0.3: Automated with CI 💫
![Page 91: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/91.jpg)
![Page 92: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/92.jpg)
![Page 93: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/93.jpg)
![Page 94: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/94.jpg)
StyleguideTestApp• Components Showcase
• For Designer 🎨
• For Developer 🔧
![Page 95: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/95.jpg)
Taking Screenshots with Espressopublic class ScreenshotViewActions {}
![Page 96: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/96.jpg)
Taking Screenshots with Espressopublic class ScreenshotViewActions { public static ViewAction screenshot(final String folderName, final String fileName) { return new ViewAction() { }; } }
![Page 97: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/97.jpg)
Taking Screenshots with Espressopublic class ScreenshotViewActions { public static ViewAction screenshot(final String folderName, final String fileName) { return new ViewAction() { // Other methods omitted. @Override public void perform(UiController uiController, View view) { ScreenshotsUtil.takeScreenshot(folderName, fileName, view); } }; } }
![Page 98: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/98.jpg)
Sample Espresso Test
![Page 99: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/99.jpg)
Sample Espresso Testpublic class StarsViewActivityTests {}
![Page 100: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/100.jpg)
Sample Espresso Testpublic class StarsViewActivityTests { @Test public void takeScreenshot() throws InterruptedException { onView(withId(R.id.stars_view_4)).perform(setStarsNumber(4)); } }
![Page 101: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/101.jpg)
Sample Espresso Testpublic class StarsViewActivityTests { @Test public void takeScreenshot() throws InterruptedException { onView(withId(R.id.stars_view_4)).perform(setStarsNumber(4)); onView(withId(R.id.stars_view_5)).perform(setStarsNumber(5), screenshot(FOLDER_NAME, "stars_with_text")); } }
![Page 102: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/102.jpg)
Sample Espresso Testpublic class StarsViewActivityTests { @Test public void takeScreenshot() throws InterruptedException { onView(withId(R.id.stars_view_4)).perform(setStarsNumber(4)); onView(withId(R.id.stars_view_5)).perform(setStarsNumber(5), screenshot(FOLDER_NAME, "stars_with_text")); ScreenshotUtil.fullScreenshot(FOLDER_NAME, "stars_fullscreen"); } }
![Page 104: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/104.jpg)
We are hiring!www.yelp.com/careers/
![Page 105: Nicola Corti - Building UI Consistent Android Apps - Codemotion Milan 2017](https://reader031.vdocument.in/reader031/viewer/2022022415/5a6479a17f8b9a36568b478b/html5/thumbnails/105.jpg)
Nicola Corti @cortinico
[email protected] bit.ly/uiconsistency
@YelpEngineering
github.com/yelp
yelp.com/careers
engineeringblog.yelp.com