Ch 5: Building User Interfaces Flashcards
Building User Interfaces:
Important Topics
- Density-Independent UI Design
- Using Views and Layouts
- Optimizing Layouts
- Working with Lists and Grids
- Using Recycler View and Adapters
- Data Binding
- Extending, grouping, creating and using Views
Major Design Topics
that influence Material Design
User Interface (UI) design
User Experience (UX)
Human Computer Interaction (HCI)
*These are not covered in depth in this book
Density-Independent Design:
Basics
- The number of pixels available varies wildly depending on hardware
- This can be abstracted away by thinking in terms of Density-Independent Pixels (dp)
- these represent physical sizes
- UI elements with the same dp size will appear the same size on a screen regardless of the pixel density of the screen
- For font sizes, we use Scalable Pixels(sp)
- Shares same base density independence as dp
- also scaled independently based on user’s preferred text size
- Android 5.0(API 21) and up, supports Vector Drawables - scalable to support any display density
- Making designs density independent allows you to focus on optimizing and adapting designs for different screens
Density-Independent Design:
Fundamental Features
in Android that support it
- Density-Independent Pixels (dp)
- Scalable Pixels (sp)
- Support for device-independent Vector Drawables
Android User Interface:
Basic Components
-
Views
- Also referred to as “controls” or “widgets”
- Pretty much all visual components in Android
- Can draw their own customized UI
- Can handle user interactions
- Base ‘View’ class
-
View Groups
- Base ‘ViewGroup’ class
- An extension of View that supports adding child Views
- Responsible for sizing and positioning child Views
- View Groups that focus primarily on laying out child Views are called “layouts”
Android User Interface:
Assigning User Interface to an Activity
- To set the UI of an Activity, use setContentView()
- Pass in the View Instance or layout resource to display
- Typically done in the onCreate() handler
- Example:
- setContentView(R.layout.main);
Layouts:
Most Commonly Used Layouts
FrameLayout
LinearLayout
RelativeLayout
ConstraintLayout
Layouts:
FrameLayout
Summary
- Simplest of the Layout Managers
- Pins each child View within its frame
- Default position is the top-left corner
- Can use the “layout_gravity” attribute on a child View to alter its location
- Adding multiple children stacks each new child on top of the one before, with each new View potentially obscuring the previous ones
Layouts:
LinearLayout
Summary
- Aligns child Views in either a vertical or horizontal line - column, or row
- LinearLayout supports a “layout_weight” attribute for each child View that can control the relative size of each child View within the available space
Layouts:
RelativeLayout
Summary
- One of the most flexible of the native layouts
- But, potentially expensive to render
- Lets you define the positions of each child View relative to the others, and to the layout’s boundaries
Layouts:
ConstraintLayout
Summary
- Newest( and recommended) layout
- Designed to support large and complex layouts without the need to nest layouts
- Similar to the Relative Layout, but provides greater flexibility and is more efficient to lay out.
- Constraint Layout positions its children through a series of constraints
- requiring child Views to be positioned according to a boundary, other child Views, or to custom guidelines
- Has its own Visual Layout Editor, used to position each control and define the constraints rather than relying on manually editing XML.
- Available through the Constraint Layout package of the Android Support Library, making it backward compatible
Layouts:
How layouts are sized
- Each layout can scale to fill a screen, or whatever container it is in
- This is done by avoiding the use of absolute positions or predetermined pixel values
- This makes them well suited for designing UIs that work on a variety of devices
- Need to set the attributes:
- android:layout_width
- android:layout_height
- Dynamic values are:
- “match_parent”
- “wrap_content”
Defining Layouts:
XML Layout Basics
- Using XML external resources is preferred
- Must have a single root element, such as <linearlayout></linearlayout>
- The layout node has several attributes assigned
- The attributes modify the way in which all child nodes will be positioned
- There are many predefined constants for the attributes that can be used
- The root node can have an arbitrary number of child nodes, including other layouts
Layouts:
Constants:
match_parent
Used with width and height generally.
Expands the View to match the available space within the parent View, Fragment or Activity
Layouts:
Constants:
wrap_content
Generally used with width and height.
Sets the size of a View to the minimum required to contain the contents it displays,
such as the height required to display a wrapped text string.
Optimizing Layouts:
General Tips
-
Avoid redundant layouts
- Such as nesting Layout nodes
- Tip: for a set of child nodes defined in another file, use the <merge></merge> tag
-
Avoid using excessive Views
- Takes additional time and resources
- Tip: In a complex layout, use a ViewStub to stop some child views from being inflated until they are needed
-
Use the Lint tool to analyze your layouts
- It can detect optimization issues
Optimizing Layouts:
<merge></merge> tag
- Used when one layout file will be added to another
- Instead of using one of the Layouts for a root node, the file uses the <merge></merge> tag as the root node
- When this sublayout is added to another, the <merge></merge> tag is removed and its Child Views are added directly to the new parent
- The parent uses the <include></include> tag as it would with any other include
Optimizing Layouts:
<include></include> tag
- Used to insert the contents of one layout file into another
- The root node of the included file is added as a Child View (unless <merge></merge> tag is used)
- Need to assign an id to the new child view
- Use:
- <include></include>
Optimizing Layouts:
ViewStub
- Useful for reducing the number of Views inflated at a time
- Views in the stub not created until they are required
- Works like a lazy include-
- a stub represents a subset of child Views within the parent layout
- Only inflated when stub is inflated
- Only inflated explicitly via the “inflate” method or when it is made visible
Android Widget Toolbox:
Most Common Controls/Views
(12)
- TextView
- EditText
- ImageView
- VideoView
- Toolbar
- ProgressBar
- RecyclerView
- ViewPager
- Button
- ImageButton
- CheckBox
- RadioButton
Android Widget Toolbox:
Common Controls:
TextView:
Basic Function
A standard, read-only text label.
Supports multiline display, string formatting and automatic word-wrapping.
Android Widget Toolbox:
Common Controls:
EditText:
Basic Function
An editable text entry box.
Accepts multi-line entry, word-wrapping, and hint text.
Android Widget Toolbox:
Common Controls:
ImageView:
Basic Function
A View that shows a single image.
Android Widget Toolbox:
Common Controls:
Toolbar:
Basic Function
A View that shows a title and common actions.
Often used as the main app bar at the top of an Activity.
Android Widget Toolbox:
Common Controls:
ProgressBar:
Basic Function
A View that shows either an indeterminate progress indicator( a spinning circle),
or a horizontal progress bar.
Android Widget Toolbox:
Common Controls:
RecyclerView:
Basic Function
A View Group that manages displaying a large number of Views in a scrolling container.
Supports a number of layout managers that allow you to lay out Views as vertical and horizontal lists, or a grid.
Android Widget Toolbox:
Common Controls:
Button:
Basic Function
A standard, interactive push button.
Android Widget Toolbox:
Common Controls:
ImageButton:
Basic Function
A push button,
for which you can specify a customized background image.
Android Widget Toolbox:
Common Controls:
CheckBox
Basic Function
A two-state button represented by a checked or unchecked box.
Android Widget Toolbox:
Common Controls:
RadioButton:
Basic Function
A two-state, grouped button.
A group of these presents the user with a number of possible options, of which only one can be enabled at a time.
Android Widget Toolbox:
Common Controls:
VideoView:
Basic Function
Handles all state management and display Surface configuration for playing videos more simply from within your Activity.
Android Widget Toolbox:
Common Controls:
ViewPager:
Basic Function
Implements a horizontally scrolling set of Views.
The View Pager allows users to swipe or drag left or right to switch between different Views.
Recycler View:
Important Components
- RecyclerView itself
- Layout Manager
- Controls how items are displayed
- Adapter
- Creates and inflates individual Views
- Creates View Holders to bind to View elements
- View Holders
- Managed by the Adapter
- Basically “slots” for Views
- Views
- Display individual data items
Recycler View:
3 Important Layout Managers
- LinearLayoutManager
- GridLayoutManager
- StaggeredGridLayoutManager
Recycler View:
Layout Managers:
Overview
- Layout Managers control how each item in a Recycler View is displayed.
- There are a number of Layout Managers available.
- Responsible for determining WHEN a view can be safely recycled
- Can be assigned either in XML or programmatically
Recycler View:
Layout Managers:
LinearLayoutManager
Brief Summary
Lays out items in a single vertical or horizontal list
Recycler View:
Layout Managers:
GridLayoutManager
Brief Summary
Similar to Linear Layout Manager, but displays a grid.
When laid out vertically:
each row can include multiple items, where each is the same height.
For horizontal orientation:
each item in a given column must be the same width.
Recycler View:
Layout Managers:
StaggeredGridLayoutManager
Brief Summary
Similar to the Grid Layout Manager,
but creates a “staggered” grid.
Each grid cell can have a different height or width,
with cells staggered to eliminate gaps.
Recycler View:
Adapter:
Two Major Roles
- Initial creation of the Views to display, including inflating the appropriate layout
- Creation of the View Holders you’ll use to “bind” the View elements to the underlying data source
Recycler View:
Adapter:
Overview
- The adapter handles the data binding
- Creates Views to display
- Creates View Holders to bind data to
- It manages View Holders
- The binding phase should be very lightweight
Recycler View:
View Holder
Summary
A View Holder stores the View to be displayed.
- It also allows the Adapter to store additional metadata and View references to simplify data binding.
- Ex: finding references to any child Views within an item layout
- Does not itself assign values from data to Views
- Role is to make the elements available so that the Adapter can bind data to them
Data Binding:
Purpose of the Data Binding library
Makes it possible to write declarative layouts that minimize the glue code needed to bind View elements to underlying data sources.
Does this by generating the code for you at compile time.
How to enable Data Binding
Data Binding is an optional library, it must be enabled in the application module’s build.gradle file:
android {
databinding.enabled = true …}
*note: It is included in the Android Support library dependency (I think), so nothing has to be added to the dependencies node.
Data Binding:
How to apply Data Binding
- Once Data Binding is enabled….
- Wrap the elements of a layout file in a new <layout> </layout>element
- This will cause a Binding class to be generated for the layout
- It includes each child element as a property that can be accessed directly
- The Binding class name is based on the layout file name
- In code, an instance of the Binding class can be obtained using DataBindingUtil
- Can now update Views through the Binding instance
Data Binding:
Create an instance of the
Binding class
Note: This is done INSTEAD of using the Activity’s “setContentView” method to display the layout
- For full Activities/Layouts:
MyActivityBinding binding =
DataBindingUtil.setContentView(
this, R.layout.my_activity);
- For Fragment Views or RecyclerView Items,
- use the Binding class’s inflate method
MyActivityBinding binding =
MyActivityBinding.inflate(
inflator, viewGroup, false);
Data Binding:
Three ways to create a Binding class instance
- Inflate a view:
- DataBindingUtil.setContentView()
- MyBinding.inflate()
- Or create from an existing View using
- DataBindingUtil.bind(view)
- Make sure to cast to the right Binding class
Data Binding:
Variables :
Basics
- Allows you to add variables that can be used within the layout but set programmatically at runtime
- Add a <data></data> element within the layout
- Declare variables within this <data> element using the tag:
</data><ul>
<li><strong><variable> <strong>name</strong>="[name]" <strong>type</strong>="[some type]" <strong>/></strong></variable></strong></li>
</ul></data> - A set[Name] method will be added to the Binding class
- Variables can be accessed within the layout file using the syntax:
- @{name.classvariable}
Data Binding:
Variables:
Syntax for accessing some property of
a variable in layout file
@{myVariable.property}
Data Binding:
Variables:
Dealing with null values
- Pretty much any Java language syntax can be used within the referencing syntax
- Use the null-coalescing operator: ??
- to provide a default value when no value has been set
- Ex:
- android:text=’@{user.email ??“No email” }’
Data Binding:
Variables:
When are variable values bound to the views?
- By default:
- bindings are applied after the next frame redraw
- This can cause a visible flicker on some views, such as Recycler View
- Can make it immediate:
- Call executePendingBindings() on the binding instance
Creating New Views:
Three Basic Approaches
Modify/Extend an Existing View
Create a Composite Control from several components
Create an entirely new Control/View
Creating New Views:
Modifying/Extending an Existing View:
Basics
- Approach used when an existing View already supplies most of the basic functionality required
- To modifiy behavior:
- Override existing Event Handlers
- Still call the superclass’s handlers to keep existing functionality
- To modify appearance:
- Override the onDraw() method
Creating New Views:
Creating a Composite Control:
Basics
Combine several Views
to create atomic, reusable controls that leverage the functionality of several interconnected Views.
Creating New Views:
Creating an entirely new Control:
Basics
Done when you need a completely different interface that can’t be obtained by changing or combining existing controls.
Need to implement sizing, and drawing of the control, as well as adding handlers to react to events.
Creating New Views:
Modifying an Existing View:
Constructor variations that should be overridden
-
Basic Constructor
- Used when creating View in code
- Only takes Context parameter
-
Inflating
- Used when inflating View from XML
- Parameters:
- Context
- AttributeSet
-
Inflating with Style
- Used when inflating View from XML when it has a style attribute
- Parameters:
- Context
- AttributeSet
- StyleAttribute (integer)
Creating New Views:
Modifying an Existing View:
Basic Steps
- Create new class extending the existing View
- Override constructors
- Override Event Handlers to modify behavior
- Override onDraw() method to modify appearance
- Define Custom Attributes
Creating New Views:
Modifying an Existing View:
Defining custom attributes
- Can declare attributes for an application in the resource file:
- res/values/attrs.xml
- These attributes are global, so must have unique names
- Add an attribute using the <declare-styleable></declare-styleable> tag, specifying an associated view for the name, then add <attr></attr> tags to declare each attribute
Creating New Views:
Creating Compound Controls:
Basic Steps
- Extend a ViewGroup, usually a Layout
- Add child views, preferrably through an XML layout
- Override the constructor to inflate the new XML layout, or to instantiate the child controls
- Also within the constructor:
- “Hook up” the controls as necessary by overriding the event handlers associated with each component
Creating New Views:
Creating Custom Views:
Important Steps
- Creating a Visual Interface
- Sizing the Control
- Drawing the Control
- Implementing Behavior:
- Handling User Interaction Events
- Supporting Accessibility
Creating New Views:
Creating Custom Views:
Base Classes:
Two Base classes
View
SurfaceView
Creating New Views:
Creating Custom Views:
Base Classes:
View class
Provides a Canvas object with a series of draw() methods and Paint classes. Use them to create a visual interface with bitmaps and raster graphics.
Can override user events, including screen touches or key presses to provide interactivity.
Offers a powerful, lightweight solution when the View does not need to be graphics heavy.
Creating New Views:
Creating Custom Views:
Base Classes:
SurfaceView class
Better option for graphics heavy controls that are frequently updated(such as live video), or that display complex graphical information(such as games and 3D visualizations).
Provides a Surface object that supports drawing from a background thread, and optionally using OpenGL to implement graphics
Creating New Views:
Creating Custom Views:
Visual Interface:
Default visual interface
The base View class presents an empty 100x100 pixel square.
Creating New Views:
Creating Custom Views:
Visual Interface:
Methods that need to be overridden
-
onMeasure(int wMeasureSpec, int hMeasureSpec)
- Called when the control’s parent is laying out it’s child controls
- Parameters specify the space that is available
- Pass the desired width and height into the setMeasuredDimension(height, width) method
-
onDraw(Canvas canvas)
- Use a variety of Paint objects to “draw” onto the Canvas object
Creating New Views:
Creating Custom Views:
Visual Interface:
onMeasure():
Using the boundary parameters
widthMeasureSpec
heightMeasureSpec
- Both are passed in as integers for efficiency reasons
- These are not direct measurements
- Used to look up the MODE and SIZE of each
- MeasureSpec.getMode(mSpec);
- MeasureSpec.getSize(mSpec);
- the mode determines what size means:
- AT_MOST : maximum space available, this view can choose its own size
- EXACTLY: exact size the control will occupy
Creating New Views:
Creating Custom Views:
Visual Interface:
Drawing the control:
Basics
- override the onDraw() method
- Android Canvas uses the “painter’s algorithm” meaning new stuff is painted “over” old stuff
- There are a series of tools in the drawing APIs to help draw simple shapes, text and Drawables on the Canvas
- There are also a large variety of fills and pens in the Paint class
Creating New Views:
Creating Custom Views:
Handling User Interaction Events:
Common UI events to handle
-
onKeyDown
- Called when any device key is pressed
- Includes D-pad, keyboard, hang-up, call, back and camera buttons
-
onKeyUp
- Called when a user releases a pressed key
-
onTouchEvent
- Called when the touch screen is pressed or released, or when it detects movement
Creating New Views:
Creating Custom Views:
Supporting Accessibility:
Overview
- Use the Accessibility APIs to provide alternate interaction methods for users with visual, physical, or ag-related disabilities that make it difficult to interact fully with a touch screen
Creating New Views:
Creating Custom Views:
Supporting Accessibility:
Checklist
- Ensure View is accessible and navigable using D-pad events
- Use Content Description attribute within layout definition to describe input widgets
- Implement the AccessibilityEventSource interface
- Broadcast AccessibilityEvents using the sendAccessibilityEvent method
- Note: the View class already implements this interface, so you only need to make adjustments necessary for your View’s behavior