概念
自定義組合View是指android給我們提供的View本身功能不夠用,但是可以把幾個(gè)View粘合起來形成一個(gè)獨(dú)立的類,對(duì)外部提供統(tǒng)一的職能,內(nèi)部View之間的邏輯實(shí)現(xiàn)可以隱藏,使之整體看起來就像是一個(gè)新的View。另外,還可以通過自定義屬性功能,使得我們的組合View直接在XML布局文件中方便的使用
實(shí)現(xiàn)
定義一個(gè)基類,之后的組合View都繼承自它
public abstract class BaseCustomView extends RelativeLayout {
/**
* 自定義view屬性命名空間
*/
private static final String NAMESPACE = "http://schemas.android.com/apk/res-auto";
//重載構(gòu)造函數(shù) 通過new構(gòu)建對(duì)象時(shí)會(huì)調(diào)用此處
//View.java中原文:Simple constructor to use when creating a view from code
public BaseCustomView(Context context) {
super(context);
initView();
}
//在XML中構(gòu)建時(shí)會(huì)調(diào)用此處,也是我們自定義屬性的構(gòu)造函數(shù),style默認(rèn)用app的主題
//View.java中原文:Constructor that is called when inflating a view from XML
//...This version uses a default style of 0, so the only attribute values
//applie are those in the Context's Theme and the given AttributeSet
public BaseCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, getStyleable());
initAttributes(a);
initView();
a.recycle();
}
public BaseCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
/**
* 初始化布局
*/
private void initView() {
View view = View.inflate(getContext(), getLayout(), this);
ButterKnife.bind(this, view);
initData(view);
}
//返回 R.styleable.xxx styleable是自定義的一組declare-styleable
protected abstract int[] getStyleable();
//根據(jù)獲取到的屬性數(shù)組在代碼中初始化屬性值
protected abstract void initAttributes(TypedArray a);
//獲取自定義組合View的布局 R.layout.xxx
protected abstract int getLayout();
//初始化一些默認(rèn)數(shù)據(jù)
protected abstract
- 一個(gè)簡單的例子
一般我們?cè)趹?yīng)用中會(huì)有很多類似的View,比如設(shè)置界面的View都可以抽取出來獨(dú)立成章,簡化代碼方便維護(hù)下邊是一個(gè)簡單的例子,實(shí)現(xiàn)了一個(gè)比較通用的設(shè)置條目,XML中沒有設(shè)置相關(guān)資源的時(shí)候就隱藏相應(yīng)內(nèi)部View,否之顯示出來。一個(gè)空的效果顯示如下:

示例
public class SettingItemView extends BaseCustomView {
private String mLeftString;
private String mEndString;
private Drawable mLeftImage;
private Drawable mEndImage;
private int mLeftColor;
public SettingItemView(Context context) {
super(context);
}
public SettingItemView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SettingItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected int[] getStyleable() {
return R.styleable.SettingItemView;
}
@Override
protected void initAttributes(TypedArray a) {
mLeftString = a.getString(R.styleable.SettingItemView_textLeft);
mEndString = a.getString(R.styleable.SettingItemView_textEnd);
mLeftImage = a.getDrawable(R.styleable.SettingItemView_imageLeft);
mEndImage = a.getDrawable(R.styleable.SettingItemView_imageEnd);
mLeftColor = a.getColor(R.styleable.SettingItemView_colorLeft, getResources().getColor(R
.color.text_color));
}
@Override
protected int getLayout() {
return R.layout.ui_setting_item;
}
@Override
protected void initData(View view) {
setLeftText(mLeftString);
setEndText(mEndString);
setLeftImage(mLeftImage);
setEndImage(mEndImage);
tv_left.setTextColor(mLeftColor);
}
public void setLeftImage(Drawable image) {
iv_left.setImageDrawable(image);
}
/**
* 當(dāng)沒有設(shè)置圖片資源時(shí)隱藏之
*
* @param image
*/
public void setEndImage(Drawable image) {
if (image != null) {
iv_end.setVisibility(VISIBLE);
iv_end.setImageDrawable(image);
}
}
public void setLeftText(String text) {
tv_left.setText(text);
}
/**
* 當(dāng)沒有設(shè)置文字時(shí)隱藏之
*
* @param text
*/
public void setEndText(String text) {
if (!TextUtils.isEmpty(text)) {
tv_end.setVisibility(VISIBLE);
tv_end.setText(text);
}
}
}
- 新建一個(gè)屬性文件attrs.xml
添加以下自定義屬性(一些通用的可以抽取出來供其它使用):
<!--common-->
<attr name="textLeft" format="string"/>
<attr name="textEnd" format="string"/>
<attr name="imageLeft" format="reference"/>
<attr name="imageEnd" format="reference"/>
<!--SettingItemView-->
<declare-styleable name="SettingItemView">
<attr name="textLeft"/>
<attr name="textEnd"/>
<attr name="imageLeft"/>
<attr name="imageEnd"/>
<attr name="colorLeft" format="color"/>
</declare-styleable>
關(guān)于styleable屬性類型可以搜索一下有很多資料,就不展開說了
布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/rl_root"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height">
<View
android:id="@+id/line"
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:background="#ffd2d2d2"
android:layout_alignParentBottom="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:orientation="horizontal"
android:layout_above="@id/line">
<ImageView
android:id="@+id/iv_left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:visibility="gone"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_weight="1"
android:visibility="gone"/>
<ImageView
android:id="@+id/iv_end"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:visibility="gone"/>
<TextView
android:id="@+id/tv_end"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
- 應(yīng)用
在布局中應(yīng)用剛才寫的組合View就像普通View一樣就好了,別忘了在跟布局中添加一行
xmlns:item="http://schemas.android.com/apk/res-auto"
這樣新屬性就可以以item的命名空間調(diào)用了
<所在包名.SettingItemView
android:id="@+id/siv_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
item:imageLeft="@drawable/xxx"
item:textLeft="test"/>
遷移自CSDN
2015年12月12日 11:02:33
http://blog.csdn.net/u013262051/article/details/50273451