Creating Custom Views
Kewang
2
A custom view should be...
3
A custom view should be...
ConformityXMLifyAccessibilityCompatibility
4
Let's implement
5
public class PieChart extends View { public PieChart(Context context, AttributeSet attrs) { super(context, attrs);
init(context, attrs); }
public PieChart(Context context) { super(context);
init(context, null); }
private void init(Context context, AttributeSet attrs) { }}
Constructors
6
<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>
/res/values/attrs.xml
7
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.example.customview" >
<com.example.customview.PieChart custom:labelPosition="left" custom:showText="true" />
</LinearLayout>
/res/layout/main.xml
8
private void init(Context context, AttributeSet 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(); }} The author's initialization
9
private void init(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.PieChart);
mShowText = a.getBoolean(R.styleable.PieChart_showText, false); mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
a.recycle(); }} My initialization
10
onDraw()
11
What to draw? Canvas
How to draw? Paint
12
before onDraw(), should onMeasure()
13
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int minw = getPaddingLeft() + getPaddingRight()+ getSuggestedMinimumWidth(); int w = resolveSize(minw, widthMeasureSpec); int h = resolveSize(MeasureSpec.getSize(w), heightMeasureSpec);
setMeasuredDimension(w, h);}
MUST setMeasuredDimension
14
float start = 0.f;for (int i = 0; i < series.size(); i++) { float sweep = (float) (series.get(i) / sum * 360.f);
paint.setColor(Color.rgb(0xff, 0xff, 0xff));
canvas.drawArc(oval, start, sweep, true, paint);
start += sweep;} onDraw()
15
then invalidate()
16
Interactive
17
View
boolean onTouchEvent()
ACTION_DOWNAll TouchEvent: return true;onClick(): return false;
18
ViewGroup
boolean onInterceptTouchEvent()
ACTION_DOWNhandle self: return true;pass to child: return false;
19
onClick(), onLongClick()onDown(), onFling()onLongPress,() onScroll()onShowPress(), onSingleTapUp()
Derive from onTouchEvent()
20
Optimizing
21
Do Less, Less Frequently
onDraw()invalidate()requestLayout()
22
onDraw()
eliminate allocations
23
invalidate()
invalidate(Rect)invalidate(int, int, int, int)
24
requestLayout()
if has complex UI custom ViewGroup
25
References
Creating a View ClassCustom DrawingMaking the View InteractiveOptimizing the View
26