カスタムview入門

4916 ワード

コントロールをカスタマイズするには、次のステップに分けられます.
1、カスタム属性の宣言と取得
(1)解析に必要なカスタム属性
(2)レスポンス/values/atrs.xmlで声明を定義します.
<resources>

    <declare-styleable name="HookView">
        <attr name="loadingText" format="string" />
        <attr name="completeText" format="string" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

</resources>
(3)ラyout xmlファイルで使用する
名前を定義してから3つの属性を定義し、ユーザー定義コントロールの参照に追加します.
    xmlns:app="http://schemas.android.com/apk/res-auto"
アプリ:loadingText=stringを使って設定する属性
(4)viewの構造方法で取得する
カスタムコントロールでTypedArayを利用して設定した属性を取得します.
if (attrs != null) {
            //       
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HookView);
            if (ta.hasValue(R.styleable.HookView_loadingText))
                loadingText = ta.getString(R.styleable.HookView_loadingText);
            if (ta.hasValue(R.styleable.HookView_completeText))
                completeText = ta.getString(R.styleable.HookView_completeText);
            textSize = ta.getDimension(R.styleable.HookView_textSize, 20);
            ta.recycle();
        }
ここで使うとrecycle()を覚えています.これはカスタムViewのためにActivityのCreateごとにCreateが作成されます.そのため、システムが頻繁にarrayを作成する必要があります.メモリと性能に対してはかなりの出費です.プールモードを使わないと、毎回GCに回収され、OutOfMemoryが発生する可能性があります.プログラム起動時には、プールにインスタンスを要求し、使用後にrecycle()方法を呼び出してそのインスタンスを解放し、他のモジュールに多重化してもいいです.recycle()を使用してください.
2、onMewureを測定する(どれぐらいのスペースを占めるか)
通常Viewは画面上に表示されますが、まずmeasreを経由してからlayoutに行きます.onMeassure(int widthSpec,int height Spec)を呼び出すときは、MeasreSpecの使用に関わります.
Meass reSpecは、3つのモードがあります.それぞれ「UNSPECIFIED」、「EXACT LY」、「ATuMOST」です.
私達がwidthまたはheightを設定すると、fill_になります.parentの場合、コンテナがレイアウト時にサブビューのmeasreメソッドを呼び出して入るモードはEXACT LYで、サブビューが残りの容器の空間を占めるため、サイズは決まっています.
設定がwrap_である場合contentの時、容器が入っているのはAT_です.MOSTは、サブビューの大きさが最大でどれぐらいかを表します.このようにviewはこの上限によって自分のサイズを設定します.サブビューのサイズが正確な値に設定されている場合、コンテナがEXACT LYに入りますが、Meass reSpecのUNSPECIFFIEDモードは、通常、スライドコントロールにおけるサブコントロールViewに対するオンメザス方式のデフォルト動作は、モードがUNSPIFIEDの場合、mMinWidth(通常は0)または背景drawableの最小サイズに設定されます.
イメージとしては、オンメスアメソッドは、親要素がコントロールを置くところに呼び出します.親コントロールが呼び出して、サブコントロールに質問します.「どこを使いたいですか?」次に二つのパラメータが入ってきます.widthMeass respecとheightMeass respec.コントロールが得る空間を指定して、そしてこの空間について説明するメタデータを指定します.結果を返すより良い方法は、Viewの高さと幅をsetMeasredDimention方法に伝えることです.
次に経典のViewの中でonMeasreが実現することを見ます.
@Override
    
   
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
   
int measuredHeight = measureHeight(heightMeasureSpec);
    
   
int measuredWidth = measureWidth(widthMeasureSpec);
    
   
setMeasuredDimension(measuredHeight, measuredWidth);
    
   
}
    
   
private int measureHeight(int measureSpec) {
    
   
int specMode = MeasureSpec.getMode(measureSpec);
    
int specSize = MeasureSpec.getSize(measureSpec);
    
   
// Default size if no limits are specified.
    
   
int result = 500;
    
if (specMode == MeasureSpec.AT_MOST){
    
   
// Calculate the ideal size of your
    
// control within this maximum size.
    
// If your control fills the available
    
// space return the outer bound.
    
   
result = specSize;
    
} 
else if (specMode == MeasureSpec.EXACTLY){
    
   
// If your control can fit within these bounds return that value.
    
result = specSize;
    
}
    
   
return result;
    
}
    
   
private int measureWidth(int measureSpec) {
    
int specMode = MeasureSpec.getMode(measureSpec);
    
int specSize = MeasureSpec.getSize(measureSpec);
    
   
// Default size if no limits are specified.
    
int result = 500;
    
if (specMode == MeasureSpec.AT_MOST){
    
// Calculate the ideal size of your control
    
// within this maximum size.
    
// If your control fills the available space
    
// return the outer bound.
    
result = specSize;
    
} 
   
else if (specMode == MeasureSpec.EXACTLY){
    
// If your control can fit within these bounds return that value.
    
   
result = specSize;
    
}
    
   
return result;
    
}
Meassure Spec類についてはここでもっと話してください.
これは32ビットのint値を表し、高い2桁はspecMode(測定モード)を表し、低い30桁はspecsize(ある測定モードでの規格の大きさ)を表します.
これに関する一般的な3つの関数:
static int getMode(int meass reSpec):提供された測定値(フォーマット)から抽出するモード(上記3つのモードの一つ)
static int getSize(int meass reSpec):提供された測定値に基づいてサイズ値を抽出します.
static int make Meass reSpec(int size,int mode):提供されたサイズ値とパターンに基づいて測定値(フォーマット)を作成します.
3、レイアウトonLayout(どこに置くか)
4、onDrawを描く(何を描くか)
通常はcanvas、PathのAPIを上手に把握する必要があります.属性アニメーションのインタラクションもあるかもしれません.
5、ontouchEvent
ユーザーインタラクティブ、イベントのキャプチャー処理が必要です.
6、onIntercept TouchEvent(view group)
view groupでイベントをブロックするには、イベントの配布メカニズムを把握する必要があります.
入门は主にこのいくつかの内容です.一つ一つのことを深く理解する必要があります.カスタマイズされたviewのソースコードを见るとき、よくこのいくつかのブロックを通して分析します.