session #7 rich and responsive layouts
TRANSCRIPT
Britt Barak18.12.2016
Wifi: Techiteasy
Rich & Responsive Layouts #7
First,
Britt BarakBritt Barak
Figure 8
Android AcademyWomen Techmakers
Jonathan Yarkoni
Android Developer & Advocate Ironsource
Android Academy Staff
Yonatan LevinGoogle Developer
Expert & Android @ Gett
Britt BarakAndroid Lead
Figure8
Yossi SegevAndroid Developer
Crave
Community Mentors
Eti Negev
Largest Android Community
Android Academy - TLV
TLV - Android Academy
~ 2000 members Join Us:
What Do We Do?
●Android Fundamentals - NOW
● Android UI / UX - 29/1 !
● Community Hackathon - 9/3 !!!
●Android Performance
●Mentors Program●Active community
What’s For Today?●Views
●Styles and themes
●Custom view
●Qualifiers
●Fragments
UI vs. UX
What’s the UX?
What’s the UI?
What’s the UX?
What’s the UI?
What’s the UI?
Hiush Royi!
...and you are….?
President Obama...is this for me?!?!
So when is my birthday ?!?!?!??
And where are my balloons?
What’s the UX?
Capturing users
●Judgement will be served 30 seconds~○Visuals will decide
○functionality means less
●You need to:○Captivate
○Impress
○Retain
The Players
UI designerUX designerProduct managerDeveloper
Material design
When Using Standards
- Better UX- Better UI- Easier Development
- Shorter implementation
- Less bugs
When Using Standards
- Better UX- Better UI- Easier Development
- Shorter implementation
- Less bugs
- And better harmony- designer --- developer --- user
Designer - red lines
This is just the beginning
- Android UI/UX course (29/1)- Performance course
So Let’s Start!
●Views
●Styles and themes
●Custom view
●Qualifiers
●Fragments
What’s For Today?
Viewz - recap
Rectangle widgetA View:
●Knows to draw itself●Used for user interaction
●Has (at least) hight and width (match_parent / wrap_content/fixed)
●May has an id (@+id/ means to create an id if it doesn’t exist)
View Group (Layout)
A special kind of view.Knows to position other views on the screen.
Which Views Do We Have Here?
Let’s see a bit under the
hood...
How does it work?
Measure Layout Draw!
Step 1: Measure
Goal: obtain view size
REF: http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)
Step 1: Measure
Goal: obtain view size, including its descendants size
REF: http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)
Step 1: Measure
Goal: obtain view size, including its descendants size, agreed by its parent.
REF: http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)
Communicate Dimensions● ViewGroup.LayoutParams ●View.MeasureSpec
ViewGroup.LayoutParams
How big the View wants to be For each dimension, it can specify one of:
an exact number
MATCH_PARENT
WRAP_CONTENT
MeasureSpec
Parent requirement for childEXACTLY: exact size
AT MOST: maximum size
UNSPECIFIED: as child wants
How does it work?
Measure Layout Draw!
Step 2: Layout
Goal : set position for view and all its children
●onLayout() is called
REF: http://developer.android.com/reference/android/view/View.html#onLayout(boolean, int, int, int, int)
- View draws itself with size and position from previous steps.
- onDraw(Canvas) is called
Step 3: Draw
REF: http://developer.android.com/reference/android/view/View.html#onDraw(android.graphics.Canvas) Guide: http://developer.android.com/training/custom-views/custom-drawing.html
Remember:
●Inflating is not cheap●Lots of children are not cheap
○Usually : prefer flat vs. deep
View types
●Use the right tool for the right task● Viewgroups - root view
○ FrameLayout
○RelativeLayout
○LinearLayout
Widgets
ButtonImageviewTextViewEditTextCheck box
....and also
Time pickerDate pickerAnalog clockCalendar view
main_activity.xml
Some Confusing View Attributes
Weight
Weight
●specifying a size in relation to other objects●Set layout_height or layout_width to 0dp
To be calculated according to layout_weight.
Weight example<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@color/green" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@color/purple" />
</LinearLayout>
Weight example<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4" android:background="@color/green" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@color/purple" />
</LinearLayout>
Weight example<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/green" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@color/purple" />
</LinearLayout>
Gravity
Gravity
●gravity: gravity of the content of the view it’s used on.
●layout_gravity: sets the gravity of the view in it’s parent.
gravity
vs.
layout_gravity
Padding Vs Margin
Padding vs. margin
●Padding would squeeze the image.●Margin won’t let you place stuff which touches.
State List
State List Resource
●Sets a color / drawable per the view’s state.●Defined in .xml file
https://developer.android.com/guide/topics/resources/color-list-resource.html
res/color/button_text.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#ffff0000"/> <!-- pressed --> <item android:state_focused="true" android:color="#ff0000ff"/> <!-- focused --> <item android:color="#ff000000"/> <!-- default --></selector>
res/color/button_text.xml
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/click" android:textColor="@color/button_text" />
Questions ?
●Views
●Styles and themes
●Custom view
●Qualifiers
●Fragments
What’s For Today?
Styles
●a collection of properties of a View or window
consider
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#00FF00" android:typeface="monospace" android:text="@string/hello" />
In styles.xml
<resources> <style name="CodeFont"
parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style></resources>
Becomes:
<TextView style="@style/CodeFont" android:text="@string/hello" />
Inheritance
<style name="GreenText" parent="@android:style/TextAppearance"> <item name="android:textColor">#00FF00</item> </style>
<style name="CodeFont.Red"> <item name="android:textColor">#FF0000</item> </style>
Question- Which text color is that:
Which text color is that?
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" />
The answer is in the manifest!
AndroidManifest.xml<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
android:theme="@style/AppTheme"> <activity android:name=".MainActivity">
<!-- .... -->
</application>
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBa
r"> <!-- Customize your theme here. -->
</style>
<style name="Theme.AppCompat" parent="Base.Theme.AppCompat"/><style name="Theme.AppCompat.CompactMenu" parent="Base.Theme.AppCompat.CompactMenu"/><style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light"/><style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar"/><style name="Theme.AppCompat.DayNight.Dialog" parent="Theme.AppCompat.Light.Dialog"/><style name="Theme.AppCompat.DayNight.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog.Alert"/><style name="Theme.AppCompat.DayNight.Dialog.MinWidth" parent="Theme.AppCompat.Light.Dialog.MinWidth"/><style name="Theme.AppCompat.DayNight.DialogWhenLarge" parent="Theme.AppCompat.Light.DialogWhenLarge"/><style name="Theme.AppCompat.DayNight.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar"/><style name="Theme.AppCompat.Dialog" parent="Base.Theme.AppCompat.Dialog"/><style name="Theme.AppCompat.Dialog.Alert" parent="Base.Theme.AppCompat.Dialog.Alert"/><style name="Theme.AppCompat.Dialog.MinWidth" parent="Base.Theme.AppCompat.Dialog.MinWidth"/><style name="Theme.AppCompat.DialogWhenLarge" parent="Base.Theme.AppCompat.DialogWhenLarge"></style><style name="Theme.AppCompat.Light" parent="Base.Theme.AppCompat.Light"/><style name="Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light.DarkActionBar"/><style name="Theme.AppCompat.Light.Dialog" parent="Base.Theme.AppCompat.Light.Dialog"/><style name="Theme.AppCompat.Light.Dialog.Alert" parent="Base.Theme.AppCompat.Light.Dialog.Alert"/><style name="Theme.AppCompat.Light.Dialog.MinWidth" parent="Base.Theme.AppCompat.Light.Dialog.MinWidth"/><style name="Theme.AppCompat.Light.DialogWhenLarge" parent="Base.Theme.AppCompat.Light.DialogWhenLarge"></style><style name="Theme.AppCompat.Light.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item></style><style name="Theme.AppCompat.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item></style><style name="ThemeOverlay.AppCompat" parent="Base.ThemeOverlay.AppCompat"/><style name="ThemeOverlay.AppCompat.ActionBar" parent="Base.ThemeOverlay.AppCompat.ActionBar"/><style name="ThemeOverlay.AppCompat.Dark" parent="Base.ThemeOverlay.AppCompat.Dark"/><style name="ThemeOverlay.AppCompat.Dark.ActionBar" parent="Base.ThemeOverlay.AppCompat.Dark.ActionBar"/><style name="ThemeOverlay.AppCompat.Dialog" parent="Base.ThemeOverlay.AppCompat.Dialog"/><style name="ThemeOverlay.AppCompat.Dialog.Alert" parent="Base.ThemeOverlay.AppCompat.Dialog.Alert"/><style name="ThemeOverlay.AppCompat.Light" parent="Base.ThemeOverlay.AppCompat.Light"/><style name="Widget.AppCompat.ActionBar" parent="Base.Widget.AppCompat.ActionBar"></style><style name="Widget.AppCompat.ActionBar.Solid" parent="Base.Widget.AppCompat.ActionBar.Solid"></style>
Themes
●Styles ties to context : ○For an application or activity
○Since v-22.1, also to a view
●Basically: many configurations
Material Themes
●@android:style/Theme.AppCompat (dark version)@android:style/Theme.AppCompat.Light (light
version)@android:style/
Theme.AppCompat.Light.DarkActionBar
android:theme="@style/AppTheme"
What’s in a Theme?●Default color values●Default widget styles●Text Appearance Styles●Window Configuration●Drawables
Important Colors
● colorPrimary● colorPrimaryDark● colorAccent
Important Text Colors
● textColorPrimary● textColorPrimaryInverse● textColorSecondary● textColorSecondaryInverse
More important Colors
● colorControlNormal ○ (defaults to textColorSecondary)
● colorControlActivated ○ (defaults to colorAccent)
● colorControlHighlight
Example<activity android:theme="@style/AppTheme">
<style name="AppTheme" parent="android:Theme.AppCompat.Light">
<item name="android:colorAccent">@color/pink</item>
<item name="android:editTextStyle">@style/MyEditTextStyle</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@color/custom_theme_color</item>
</style>
<color name="custom_theme_color">#b0b0ff</color>
Questions ?
Re-using Layouts
Consider This Layout : titlebar.xml<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/titlebar_bg" >
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo" /></FrameLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg">
<include layout="@layout/titlebar"/>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" />
...
</LinearLayout>
What do we have?<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"...
<FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/titlebar_bg" >
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo" /></FrameLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" />
...
</LinearLayout>
Use merge <merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo" />
</merge>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg">
<include layout="@layout/titlebar"/>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" />
...
</LinearLayout>
Now:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">...
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/gafricalogo" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" />
...
</LinearLayout>
Remember:
Questions ?
●Views
●Styles and themes
●Custom view
●Qualifiers
●Fragments
What’s For Today?
Custom views - why?
●Encapsulating a specific functionality or attributes●Performance
https://developer.android.com/training/custom-views/create-view.html#subclassview
Custom views - How?
● Subclass a View or custom widget.●Define custom attributes.●Apply custom attributes.●Add properties and events.
Subclass a View
class PieChart extends View {
public PieChart(Context context, AttributeSet attrs) { super(context, attrs); }
}
Use Custom Attributes<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.example.customviews">
</LinearLayout>
Define Custom Attributes
res/values/attrs.xml
<resources> <declare-styleable name="PieChart"> <attr name="showText" format="boolean" /> <attr name="labelPosition" format="enum"> <enum name="left" value="0"/> <enum name="right" value="1"/> </attr> </declare-styleable></resources>
Attributes Format Types
●Resources Types:○Fraction
○Float
○Boolean
○Color
○String
○Dimension
○Integer
●Special Types:○Flag
○Enum
○Reference
Use Custom Attributes<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.myapp">
<com.example.customviews.charting.PieChart app:showText="true" app:labelPosition="left" />
</LinearLayout>
Apply Custom Attributespublic PieChart(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs,R.styleable.PieChart, 0, 0);
try { mShowText = a.getBoolean(R.styleable.PieChart_showText, false); mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0); } finally { a.recycle(); }}
Questions ?
Add Properties and Events
Attributes can only be read when the view is initialized.public boolean isShowText() { return mShowText;}
public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout();}
Notify a Change
Measure Layout Draw!
Which step should we re-do?
Notifying a Change
View View
Which step should we re-do?
Re - Draw:
●invalidate()- change in view appearance → re-draw.
Notifying a Change
View View
Which step should we re-do?
Notifying a Change
View1 View2 View1 View2
Which step should we re-do?
Notifying a Change
View1 View2 View1 View2View2View1
Which step should we re-do?
re-measure → re-layout→ re-draw
●requestLayout()
Notifying a Change
View1 View2 View1 View2View2View1
Design For Accessibility
Label your input fields using android:contentDescription
Call sendAccessibilityEvent() when appropriate.Support alternate controllers, such as D-pad and
trackball
More here: https://developer.android.com/guide/topics/ui/accessibility/custom-views.html
Questions ?
●Views
●Styles and themes
●Custom view
●Responsive design
●Fragments
What’s For Today?
87.6%
Resource Qualifiers
●w#dp●h#dp●land●port●sw#dp
Resource Qualifiers
●Screen size●Pixel density●Screen orientation●Platform version●Locale●UI Mode - car / TV / watch…
https://developer.android.com/guide/topics/resources/providing-resources.html
Resources Types
●Layouts●Dimensions●Menus●Styles●Booleans/Strings/Integers
examples
What happens on runtime change?
Remember Activity Lifecycle?
On Configuration ChangeActivity is recreated
In order to switch resources!
Remember-
This is the SAME app!
Code base, functionality, etc..
This Is The Same App
●Functionality is the same●Include layouts●Use Fragments
Let’s see another example:
How can this work?
ActivityonCreate
()
Illustration :)Activity
onCreate()
onDestroy()
PauseSave state
Inflate Set data
Restore state
onResume()
Play Clean
resources
onPause()
onResume()
Inflate Set data
Play
Could be a handful…….Separate to smaller
components!videoPrese
nter
ActivityonCreate
()
Illustration :)Activity
onCreate()
onDestroy()
PauseSave state
Inflate Set data
Restore state
onResume() onPause()
onResume()
Inflate Set data
init()
onResume()
onPause() clean()
init()
onResume()
●Views
●Styles and themes
●Custom view
●Responsive design
●Fragments
What’s For Today?
Fragments-(Flash back to lesson #4)
What Are They?
Fragments - What Are They?
“A Fragment represents a behavior or a portion of user interfacein an Activity.”
https://developer.android.com/guide/components/fragments.html
Fragments
●Component with UI and a lifecycle●Tied to activity lifecycle
How would it look like?
videoFragment
Illustration :)Activity
onCreate()
onDestroy()
Commit Fragment
VideoFragmentonCreateVi
ew()onDestro
y()PauseSave state
InflateSet data
onResume() onPause()
clean()Play
We use fragments to modularize the activity
View is lower abstraction than Fragment
Fragments know Views. Views don’t know Fragments.
Any Questions?
Thank You !