Android Develpers官網提供的範例:
Sample Code URL:
http://developer.android.com/shareables/training/CustomView.zip
自定義一個View的方法:
步驟一:
開一Java檔extends
(1)最原生的View
(2)ViewGroup
--------Layout類--------
(3)LinearLayout
(4)FrameLayout
--------元件類--------
(5)Button
...
步驟二:
在res\values\attrs.xml定義屬性
<resources>
<declare-styleable name="PieChart"> <!--需與Java檔的ClassName相同 -->
<attr name="autoCenterPointerInSlice" format="boolean"/>
<attr name="highlightStrength" format="float"/>
<attr name="labelColor" format="color"/>
<attr name="labelHeight" format="dimension"/>
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
<attr name="labelWidth" format="dimension"/>
<attr name="labelY" format="dimension"/>
<attr name="pieRotation" format="integer"/>
<attr name="pointerRadius" format="dimension"/>
<attr name="showText" format="boolean"/>
</declare-styleable>
</resources>
還有這些屬性可以使用:
<!-- Identifier for the child that represents the panel's handle. -->
<attr name="handle" format="reference" />
<!-- Defines opened handle (drawable/color). -->
<attr name="openedHandle" format="reference|color" />
<attr name="transitionTextColorDown" format="color" />
<attr name="weight" format="fraction" />
步驟三:
提供2種建構子:
//Create View object from your JAVA code.
public PieChart(Context context) {
super(context);
init();
}
//Call by the layout engine.
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
//Get the Attribute from XML layout.
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0
);
try {
// Retrieve the values from the TypedArray and store into
// fields of this class.
//
// The R.styleable.PieChart_* constants represent the index for
// each custom attribute in the R.styleable.PieChart array.
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextY = a.getDimension(R.styleable.PieChart_labelY, 0.0f);
mTextWidth = a.getDimension(R.styleable.PieChart_labelWidth, 0.0f);
mTextHeight = a.getDimension(R.styleable.PieChart_labelHeight, 0.0f);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
mTextColor = a.getColor(R.styleable.PieChart_labelColor, 0xff000000);
mHighlightStrength = a.getFloat(R.styleable.PieChart_highlightStrength, 1.0f);
mPieRotation = a.getInt(R.styleable.PieChart_pieRotation, 0);
mPointerRadius = a.getDimension(R.styleable.PieChart_pointerRadius, 2.0f);
mAutoCenterInSlice = a.getBoolean(R.styleable.PieChart_autoCenterPointerInSlice, false);
} finally {
// release the TypedArray so that it can be reused.
a.recycle();
}
init();
}
步驟四:
系統在開始onDraw()前,會多次呼叫onMeasure()去跟Layout問現在要畫的範圍是多大
//
// Measurement functions. This example uses a simple heuristic: it assumes that
// the pie chart should be at least as wide as its label.
//
@Override
protected int getSuggestedMinimumWidth() {
return (int) mTextWidth * 2;
}
@Override
protected int getSuggestedMinimumHeight() {
return (int) mTextWidth;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Try for a width based on our minimum
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
// Whatever the width ends up being, ask for a height that would let the pie
// get as big as it can
int minh = (w - (int) mTextWidth) + getPaddingBottom() + getPaddingTop();
int h = Math.min(MeasureSpec.getSize(heightMeasureSpec), minh);
setMeasuredDimension(w, h);
}
相關方法:
heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (parent.getHeight() * mWeight), MeasureSpec.EXACTLY);
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
int specMode = MeasureSpec.getMode(measureSpec);
if (specMode == MeasureSpec.EXACTLY) ....
一開始系統傳進來的引數measureSpec是從main.xml裡抓過來的
在MeasureSpec.getMode()裡會抓到的尺寸模式,有以下3種
步驟五:
幾次的onMeasure()呼叫完後,(如果是繼承自View)就跑去呼叫onDraw()開始繪圖了。
若是繼承自其他者,請參考以下:
Here's a summary of some of the other standard methods that the framework calls on views:
總結來說︰
1.在res/values/新增一個自訂的attrs.xml2.在main.xml裡使用他們3.繼承View,並在(1)建構式 裡宣告初始值(2)在onMeasure()裡交待清楚這個自創的View應該有多大(3)在onDraw()裡開始繪圖
Creating a View Class
http://developer.android.com/training/custom-views/create-view.htmlSample Code URL:
http://developer.android.com/shareables/training/CustomView.zip
自定義一個View的方法:
步驟一:
開一Java檔extends
(1)最原生的View
(2)ViewGroup
--------Layout類--------
(3)LinearLayout
(4)FrameLayout
--------元件類--------
(5)Button
...
步驟二:
在res\values\attrs.xml定義屬性
<resources>
<declare-styleable name="PieChart"> <!--需與Java檔的ClassName相同 -->
<attr name="autoCenterPointerInSlice" format="boolean"/>
<attr name="highlightStrength" format="float"/>
<attr name="labelColor" format="color"/>
<attr name="labelHeight" format="dimension"/>
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
<attr name="labelWidth" format="dimension"/>
<attr name="labelY" format="dimension"/>
<attr name="pieRotation" format="integer"/>
<attr name="pointerRadius" format="dimension"/>
<attr name="showText" format="boolean"/>
</declare-styleable>
</resources>
還有這些屬性可以使用:
<!-- Identifier for the child that represents the panel's handle. -->
<attr name="handle" format="reference" />
<!-- Defines opened handle (drawable/color). -->
<attr name="openedHandle" format="reference|color" />
<attr name="transitionTextColorDown" format="color" />
<attr name="weight" format="fraction" />
步驟三:
提供2種建構子:
//Create View object from your JAVA code.
public PieChart(Context context) {
super(context);
init();
}
//Call by the layout engine.
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
//Get the Attribute from XML layout.
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0
);
try {
// Retrieve the values from the TypedArray and store into
// fields of this class.
//
// The R.styleable.PieChart_* constants represent the index for
// each custom attribute in the R.styleable.PieChart array.
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextY = a.getDimension(R.styleable.PieChart_labelY, 0.0f);
mTextWidth = a.getDimension(R.styleable.PieChart_labelWidth, 0.0f);
mTextHeight = a.getDimension(R.styleable.PieChart_labelHeight, 0.0f);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
mTextColor = a.getColor(R.styleable.PieChart_labelColor, 0xff000000);
mHighlightStrength = a.getFloat(R.styleable.PieChart_highlightStrength, 1.0f);
mPieRotation = a.getInt(R.styleable.PieChart_pieRotation, 0);
mPointerRadius = a.getDimension(R.styleable.PieChart_pointerRadius, 2.0f);
mAutoCenterInSlice = a.getBoolean(R.styleable.PieChart_autoCenterPointerInSlice, false);
} finally {
// release the TypedArray so that it can be reused.
a.recycle();
}
init();
}
步驟四:
系統在開始onDraw()前,會多次呼叫onMeasure()去跟Layout問現在要畫的範圍是多大
//
// Measurement functions. This example uses a simple heuristic: it assumes that
// the pie chart should be at least as wide as its label.
//
@Override
protected int getSuggestedMinimumWidth() {
return (int) mTextWidth * 2;
}
@Override
protected int getSuggestedMinimumHeight() {
return (int) mTextWidth;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Try for a width based on our minimum
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
// Whatever the width ends up being, ask for a height that would let the pie
// get as big as it can
int minh = (w - (int) mTextWidth) + getPaddingBottom() + getPaddingTop();
int h = Math.min(MeasureSpec.getSize(heightMeasureSpec), minh);
setMeasuredDimension(w, h);
}
相關方法:
heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (parent.getHeight() * mWeight), MeasureSpec.EXACTLY);
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
int specMode = MeasureSpec.getMode(measureSpec);
if (specMode == MeasureSpec.EXACTLY) ....
一開始系統傳進來的引數measureSpec是從main.xml裡抓過來的
在MeasureSpec.getMode()裡會抓到的尺寸模式,有以下3種
Mode
|
Value
|
備註
|
main.xml裡相對應的設定
|
AT_MOST
|
-2147483648
|
子視圖可自行調整尺寸大小
|
android:layout_width或height 設為"wrap_content"時
|
EXACTLY
|
1073741824
|
父Layout已經很明確的定義該子視圖的大小
|
android:layout_width或height有自訂大小或為"fill_parent"時
|
UNSPECIFIED
|
0
|
父Layout未指定大小,子視圖可自行調整。
|
步驟五:
幾次的onMeasure()呼叫完後,(如果是繼承自View)就跑去呼叫onDraw()開始繪圖了。
若是繼承自其他者,請參考以下:
Here's a summary of some of the other standard methods that the framework calls on views:
Category | Methods | Description |
---|---|---|
Creation | Constructors | There is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. The second form should parse and apply any attributes defined in the layout file. |
| Called after a view and all of its children has been inflated from XML. | |
Layout |
| Called to determine the size requirements for this view and all of its children. |
| Called when this view should assign a size and position to all of its children. | |
| Called when the size of this view has changed. | |
Drawing |
| Called when the view should render its content. |
Event processing |
| Called when a new key event occurs. |
| Called when a key up event occurs. | |
| Called when a trackball motion event occurs. | |
| Called when a touch screen motion event occurs. | |
Focus |
| Called when the view gains or loses focus. |
| Called when the window containing the view gains or loses focus. | |
Attaching |
| Called when the view is attached to a window. |
| Called when the view is detached from its window. | |
| Called when the visibility of the window containing the view has changed. |
總結來說︰
1.在res/values/新增一個自訂的attrs.xml2.在main.xml裡使用他們3.繼承View,並在(1)建構式 裡宣告初始值(2)在onMeasure()裡交待清楚這個自創的View應該有多大(3)在onDraw()裡開始繪圖
留言
張貼留言