自定義控件(組合控件和自定義屬性)

前言

在以前經(jīng)常聽(tīng)到別人說(shuō),安卓里面自定義view灰常的重要。然后自己也沒(méi)有去真正的去學(xué)習(xí)。自定義view其實(shí)是個(gè)非常高深的學(xué)問(wèn),如果深入研究下去的話。我看過(guò)愛(ài)哥(csdn)的ui博客(愛(ài)哥的csdn),真心佩服,感嘆他的代碼,數(shù)學(xué),美術(shù)功底。然后,也沒(méi)認(rèn)真看下去,因?yàn)閷?shí)在是太深?yuàn)W了。自定義view大概可以分成

  • 繼承view
  • 組合view
  • 自己畫(huà)的view(用paint和canvas)
  • 自定義viewgroup(widget)
    最近又跟同學(xué)聊起來(lái)了,于是就準(zhǔn)備自己實(shí)現(xiàn)一個(gè)imagebutton來(lái)練練手。(最簡(jiǎn)單的了)以及后面一個(gè)把imageview與textview結(jié)合使用的案例。

ImageButton

要實(shí)現(xiàn)ImageButton最容易想到的不就是把button和imageview合在一起么。嗯,人容易就想到這是一個(gè)組合自定義view??墒侨绾伟岩粋€(gè)image放到button上呢,自然就是用一個(gè)FrameLayout把button和imageview包裹起來(lái),然后將這個(gè)layout當(dāng)作一個(gè)weidgt。把一個(gè)layout當(dāng)成一個(gè)控件我開(kāi)始不太理解。后來(lái)了解到一些東西。

補(bǔ)充知識(shí)點(diǎn)(安卓的頂層視圖)

在android里面,你的app界面的活動(dòng)的視圖并非是最頂級(jí)的視圖。大家應(yīng)該都知道viewtree。在安卓里面,最頂級(jí)的視圖是一個(gè)叫DecorView的東西。它包括你的狀態(tài)欄,標(biāo)題欄,以及你的活動(dòng)界面。而且這個(gè)活動(dòng)界面,安卓會(huì)自動(dòng)幫你提前弄進(jìn)去一個(gè)FrameLayout??梢赃@么理解吧,在安卓這個(gè)上帝的面前,你的activity就是放在他的framelayout的一個(gè)個(gè)view。上一張圖~


DecorView->LinearLayout(狀態(tài)欄和activity)->FrameLayout(activity)->你自己的acitivty視圖。

好啦,回歸正題。我上代碼了。

myimagebutton_layout.xml

<FrameLayout    
  xmlns:android="http://schemas.android.com/apk/res/android"        
  android:layout_width="match_parent"             
  android:layout_height="match_parent">   
  <Button       
    android:layout_width="match_parent"        
    android:layout_height="match_parent"        
    android:id="@+id/button_imagebutton"        />    
  <ImageView 
    android:layout_width="match_parent"        
    android:layout_height="match_parent"        
    android:id="@+id/imageview_button"        />
</FrameLayout>

用一個(gè)framelayout把兩個(gè)控件裝起來(lái),然后組合。組合了之后我們就去自定義我們這個(gè)控件的屬性。button不用變對(duì)吧,用原生的就好了,就是需要有一個(gè)圖片的src這個(gè)屬性就好了。

在values目錄下的attrs.xml文件_

<?xml version="1.0" encoding="utf-8"?>
<resources>在
    <declare-styleable name="MyImageButton">
        <attr name="Imagesrc" format="reference"/>
    </declare-styleable>
</resources>

一般來(lái)說(shuō),declare-styleable標(biāo)簽的名字都是你的自定義控件的名字。attr就是你的自定義控件屬性。format是這個(gè)屬性的值的數(shù)據(jù)類(lèi)型。這里的reference表示引用。dimension表示的是dp或者sp的大小。還有一些可以自己去看看。定義好屬性,我們就開(kāi)始寫(xiě)控件了。

MyImageButton.java

/**
 * Created by Zane on 15/10/27.
 */
public class MyImageButton2 extends FrameLayout{

    ImageView mImageView;
    Button mButton;
    int resId;

    public MyImageButton2(Context context) {
        super(context);
    }

    public MyImageButton2(Context context, AttributeSet attrs) {
        super(context, attrs);
        //導(dǎo)入布局
        LayoutInflater.from(context).inflate(R.layout.myimagebutton_layout, this);

      mImageView=(ImageView)findViewById(R.id.imageview_button);
       
      mButton = (Button) findViewById(R.id.button_imagebutton);
        //獲得這個(gè)控件對(duì)應(yīng)的屬性。
      TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyImageButton);

        try{
          //獲得屬性值
            resId = a.getResourceId(R.styleable.MyImageButton_Imagesrc, 0);
        }finally {
          //回收這個(gè)對(duì)象
            a.recycle();
        }

        if(resId != 0){
            mImageView.setImageResource(resId);
        }
    }

    public void setImage(int resId){
        mImageView.setImageResource(resId);
    }

} 

一般來(lái)說(shuō),繼承view(就這么說(shuō)吧,反正都是都是繼承view的),實(shí)現(xiàn)兩三個(gè)構(gòu)造函數(shù)就可以了。在第二個(gè)里面有一個(gè)attr,這就是傳進(jìn)來(lái)的屬性。如果resId不為默認(rèn)值,就表示用戶在xml里面?zhèn)魅肓诉@個(gè)屬性值,你也必須要寫(xiě)一個(gè)set方法,讓用戶可以在java代碼中去改變屬性值。

test.myimagebutton.layout.xml_

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.think.testview.customview.MyImageButton2
        xmlns:pt = "http://schemas.android.com/apk/res/com.example.think.testview"
        android:layout_height="100dp"
        android:layout_width="match_parent"
        pt:Imagesrc = "@drawable/ic_launcher"
        />

</LinearLayout>

看到我們使用了自定義控件。如果用過(guò)github上面別人寫(xiě)的控件庫(kù)的同學(xué)應(yīng)該知道這種方法引入控件。xmlns:pt = "http://schemas.android.com/apk/res/com.example.think.testview 這個(gè)申明時(shí)必須的。pt是自己任意命名的,后面跟的是"http://schemas.android.com/apk/res/"加上你的包名。后面直接使用我們的自定義屬性久ok了。

效果圖

haha.png

結(jié)束語(yǔ)

說(shuō)來(lái)也巧,剛會(huì)這個(gè)就有一個(gè)機(jī)會(huì)可以讓我實(shí)戰(zhàn)一下了。其實(shí)也就比這個(gè)復(fù)雜一點(diǎn)點(diǎn),在做一個(gè)項(xiàng)目的時(shí)候,遇到這樣的效果需求。

hehe.png

每一個(gè)結(jié)果后面都有一個(gè)imageview。如果要寫(xiě)的話,也很簡(jiǎn)單對(duì)吧,就是一個(gè)imageview加一個(gè)text。可是你如果自己寫(xiě)一個(gè)控件出來(lái)呢,它本身就實(shí)現(xiàn)了imageview和textview的結(jié)合。那豈不是兩個(gè)控件變一個(gè)?并且這種形式用的太多了,各種地方都要用到,索性我就自己寫(xiě)了一個(gè)CombineImageViewTextView出來(lái)了。當(dāng)然這個(gè)自定義屬性就會(huì)多一點(diǎn)了,比如兩個(gè)東西之間的間隔,字體大小,顏色等等。好了這也是我第一次用markdown寫(xiě)博客,感覺(jué)還不錯(cuò)哈哈~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容