自定義View學(xué)習(xí)--定義View流程和注意事項(xiàng)

參考了Google官方培訓(xùn)課程鴻洋大神的博客,下面進(jìn)入正題


Googl官方建議

·遵守Android標(biāo)準(zhǔn)規(guī)則。
·提供自定義的風(fēng)格屬性值并能夠被Android XML Layout所識(shí)別
·發(fā)出可訪問(wèn)的事件。
·能夠兼容Android的不同平臺(tái)。

常用實(shí)現(xiàn)2種方式

·繼承View
·拓展現(xiàn)有控件(繼承系統(tǒng)提供的UI組件)

自定義View的流程

1.繼承View或者繼承View的一個(gè)實(shí)現(xiàn)類

  • 至少重寫父類的一個(gè)構(gòu)造方法
    它包含一個(gè)Contenx與一個(gè)AttributeSet對(duì)象作為參數(shù)。這個(gè)constructor允許layout editor創(chuàng)建并編輯你的view的實(shí)例。
    public RoundImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    getAttrs(context,attrs);
    }

2.定義自定義屬性

  • Gogle官方建議:
    ·為你的view在資源標(biāo)簽下定義自設(shè)的屬性
    ·在你的XML layout中指定屬性值
    ·在運(yùn)行時(shí)獲取屬性值
    ·把獲取的屬性值應(yīng)用到你的view上

  • 如何定義?
    在vuales文件夾下新建attrs.xml文件,定義自定義View需要的屬性,可以通過(guò)構(gòu)造方法的 atts參數(shù)獲取
    <resources>
    <declare-styleable name="RoundImageView">
    <attr name="XfermodeImageView_src" format="reference"/>
    <attr name="XfermodeImageView_type" format="integer"/>
    <attr name="XfermodeImageView_borderRadius" format="dimension"/>
    </declare-styleable>
    </resources>

  • 如何使用?
    在使用自定義的屬性時(shí)要聲明相應(yīng)的命名空間:

      <com.wenjie.drawview.RoundImageView
             xmlns:custom="http://schemas.android.com/apk/res-auto"      
             android:layout_width="match_parent"             
             android:layout_height="wrap_content"   
             custom:XfermodeImageView_src="@mipmap/test2" 
      />
    

請(qǐng)注意:如果你的view是一個(gè)inner class,你必須指定這個(gè)view的outer class.同樣的,如果PieChart有一個(gè)inner class叫做PieView。為了使用這個(gè)類中自設(shè)的屬性,你應(yīng)該使用com.example.customviews.charting.PieChart$PieView.

  • 如何獲取屬性并且應(yīng)用?

    對(duì)res目錄里的每一個(gè)<declare-styleable>資源,自動(dòng)生成的R.java文件定義了存放屬性ID的數(shù)組和常量,常量用來(lái)索引數(shù)組中每個(gè)屬性。因此我們可以使用TypedArray這個(gè)類來(lái)讀取屬性:(為了方便,下面的代碼比較簡(jiǎn)單)
    public CustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.getTheme().obtainStyledAttributes(
    attrs,
    R.styleable.CustomView,
    0, 0);
    try {
    mShowText =a.getBoolean(R.styleable.CustomView_showText, false);
    mTextPos = a.getInteger(R.styleable.CustomView_labelPosition, 0);
    } finally {
    a.recycle();
    }
    }

TypedArray對(duì)象是一個(gè)共享資源,必須被在使用后進(jìn)行回收。

  • 添加屬性和事件
    public boolean isShowText() {
    return mShowText;
    }

    public void setShowText(boolean showText) {
        mShowText = showText;
        invalidate();
        requestLayout();
    }
    

注意點(diǎn):在setShowText方法里面有調(diào)用invalidate()) and requestLayout()). 這兩個(gè)調(diào)用是確保穩(wěn)定運(yùn)行的關(guān)鍵。當(dāng)view的某些內(nèi)容發(fā)生變化的時(shí)候,需要調(diào)invalidate來(lái)通知系統(tǒng)對(duì)這個(gè)view進(jìn)行redraw,當(dāng)某些元素變化會(huì)引起組件大小變化時(shí),需要調(diào)用requestLayout方法。調(diào)用時(shí)若忘了這兩個(gè)方法,將會(huì)導(dǎo)致hard-to-find bugs。

  • 響應(yīng)事件的監(jiān)聽器
    如果需要額外的事件,可以通過(guò)接口回調(diào)的方式來(lái)設(shè)置事件監(jiān)聽,一般可以定義一個(gè)內(nèi)部接口.

3.需要warp_content屬性時(shí):在onMeasure()方法中判斷測(cè)量模式為AT_MOST時(shí),設(shè)定一個(gè)值。


4.實(shí)現(xiàn)onDraw()方法:在這里繪制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容