前言
在以前經(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了。
效果圖

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

每一個(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ò)哈哈~