Professional Documents
Culture Documents
Android
1. Custom Views
1.1. Default views
The Android framework provides several default views. The base class a view is the View. Views
are responsible for measuring, layouting and drawing themselves and their child elements (in case
of a ViewGroup). Views are also responsible for saving their UI state and handling touch events.
Developers can also create custom views and use them in their application.
It is possible to create custom views by:
View are typically created to provide a user interface experience with is not possible with the
default views. Using custom view allows the developer allow to do certain performance
optimization, i.e., in case of a custom layout the development can optimize the layout manager for
his use case.
measuring pass - implemented in the`measure(int, int)` method. This happens as a topdown traversal of the view hierarchy. Every view stores its measurements.
layout pass - implemented in the layout(int, int, int, int) method. This is also a top-down
traversal of the view hierarchy. During this phase each layout manager is responsible for
positioning all of its children. It uses the sizes computed in the measure pass.
Layout managers can run the measure pass several times. For example, LinearLayoutsupports the
weight attribute which distributes the remaining empty space among views
and RelativeLayout measures child views several times to solve constraints given in the layout file.
A view or activity can
the requestLayout() method.
trigger
the
measure
and
layout
pass
with
call
to
After the measure and layout calculation, the views draw themselves. This operation can be
triggered with the invalidate() method from the View class.
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<de.vogella.android.ownview.MyDrawView
android:id="@+id/myDrawView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
2. Compound Views
Compound views (also known as Compound Components) are pre-configured ViewGroups based
on existing views with some predefined view interaction.
Compound views also allow you to add custom API to update and query the state of the compound
view.
For such a control you define a layout file and assign it to your compound view. In the
implementation of your compound view you predefine the view interaction. You would define a
layout file and extend the corresponding ViewGroup class. In this class you inflate the layout file
and implement the View connection logic
3.2. Measurement
The layout manager calls the onMeasure() method of the view. The view receives the layout
parameter from the layout manager. A layout manager is responsible to determine the size of all its
children.
The view must call the setMeasuredDimenstion(int, int) method with the result.
4. Life cycle
4.1. Life cycle events related to the window
A view is displayed if it is attached to a layout hierarchy which is attached to a window. A view has
several life cycle hooks.
The onAttachedToWindow() is called once the window is available.
The onDetachedFromWindow() is used when the view is removed from its parent (and if the parent
is attached to a window). This happens for example if the activity is recycled (e.g. via
the finished() method call) or if the view is recycled.
The onDetachedFromWindow() method can be used to stop animations and to clean up resources
used by the view.
All views must know how to measure and layout themselves. The requestLayout()method call tells
the view to measure and layout itself. As this operation may influence the layout of other views it
calls also requestLayout() of its parent.
This recursive call is the reason why you should not nestle layout to deeply. The measure and
layout operation might be expensive if a lot of hierarchies are re-calculated.
The onMeasure() method determines the size for the view and its children. It must set the
dimension via the setMeasuredDimension() method in this method call before returning.
The onLayout() positions the views based on the result of the onMeasure() method call. This call
happens typically once, while onMeasure() can happen more than once.
To use these attributes in your layout file you have to declare them in the XML header. In the
following listing this is done via the xmlns:custom part of the code. These attributes are also
assigned to the view.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<!-- define new name space for your attributes -->
xmlns:custom="http://schemas.android.com/apk/res/com.vogella.android.view.compoundview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<!-- Assume that this is your new component. It uses your new attributes -->
<com.vogella.android.view.compoundview.ColorOptionsView
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
custom:titleText="Background color"
custom:valueColor="@android:color/holo_green_light"
/>
</LinearLayout>
The following example shows how you components can access these attributes.
6
package com.vogella.android.view.compoundview;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ColorOptionsView extends View {
private View mValue;
private ImageView mImage;
public ColorOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Options, 0, 0);
String titleText = a.getString(R.styleable.Options_titleText);
int valueColor = a.getColor(R.styleable.Options_valueColor,
android.R.color.holo_blue_light);
a.recycle();
// more stuff
}
}
Value
Testing
Table width
Application Name
Project Name
com.vogella.android.customview.compoundview
Package name
com.vogella.android.customview.compoundview
Latest
Template
Empty Activity
Activity
MainActivity
Layout
activity_main
android:showDividers="middle"
android:divider="?android:attr/listDivider"
tools:context=".MainActivity" >
<com.vogella.android.view.compoundview.ColorOptionsView
android:id="@+id/view1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:background="?android:selectableItemBackground"
android:onClick="onClicked"
custom:titleText="Background color"
custom:valueColor="@android:color/holo_green_light"
/>
<com.vogella.android.view.compoundview.ColorOptionsView
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:background="?android:selectableItemBackground"
android:onClick="onClicked"
custom:titleText="Foreground color"
custom:valueColor="@android:color/holo_orange_dark"
/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_centerVertical="true"
android:visibility="gone"
/>
</merge>
mValue = getChildAt(1);
mValue.setBackgroundColor(valueColor);
mImage = (ImageView) getChildAt(2);
}
public ColorOptionsView(Context context) {
this(context, null);
}
public void setValueColor(int color) {
mValue.setBackgroundColor(color);
}
public void setImageVisible(boolean visible) {
mImage.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
7. Canvas API
7.1. Introduction into the canvas API
The Canvas API allows to create complex graphical effects. You paint on a Bitmapsurface.
The Canvas class provides the drawing methods to draw on a bitmap and thePaint class specifies
how you draw on the bitmap.
The Canvas object contains the bitmap on which you draw. It also provides methods for drawing
operations, e.g. drawARGB() for drawing a color, drawBitmap() to draw aBitmap, drawText() to
draw a text, drawRoundRect() to draw a rectangle with rounded corners and much more.
7.4. Shader
A shader allows to define for a Paint object the content which should be drawn. For example you
can use a BitmapShader to define that a bitmap should be used to draw. This allows you for
example to draw an image with rounded corners. Simply define aBitmapShader for
your Paint object and use the drawRoundRect() method to draw a rectancle with rounded corners.
Other Shaders provided
by
the
Android
are LinearGradient,RadialGradient and SweepGradient for drawing color gradients.
platform
To use a Shaders assign it to your Paint object via the setShader() method.
If the area which is filled is larger than the Shaders you can define via the Shader tile mode how
the rest should be filled. The Shader.TileMode.CLAMP constant defines that the edge corners
should be used to fill the extra space, the Shader.TileMode.MIRRORconstant defines that the image
is mirrored and Shader.TileMode.REPEAT defines that the image will be repeated.
13
Android searches based on the ID of the view in the layout for the view and pass a Bundle to the
view which the view can use to restore its state.
You should save and restore the user interface state as the user left it, e.g. the scroll position or the
active selection.
14