在android開發的過程中,有的時候面對多個Activity里面一些相同的布局,我們需要寫多次相同的代碼,同時這種方法給我們的項目維護也帶來了很大不便。那么有沒有一種可行的辦法能夠將Activity里面相同的布局拆分的很清楚呢?當然是有的,這個時候就輪到自定義控件閃亮登場了。
其實在android里面有多種方法去實現自定義控件,但是今天這篇博客里面只介紹使用xml的方式進行自定義控件的創建。請看下面的這種場景,不管在哪個頁面里面都有個標題,包括一條居中的文本信息和在左邊的返回按鈕。這個時候我們就可以將上面的標題拆分成一個控件,然后在該控件里面暴露出一個text屬性和一個按鈕的點擊事件。
首先讓我們先來創建一個前台的xml文件用於放置布局,代碼如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/test"
android:gravity="center_vertical">
<TextView
android:id="@+id/tvBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="<"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登錄"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
可以看到在上面的布局里面,我們只是放置了兩個TextView,一個表示返回,另一個則表示title。
看到這里聰明的你也許就能猜到了,會不會在自定義控件的時候,我們也同樣需要采用某種方法加載上面的布局文件,然后在加載的時候同時關聯自己定義好的屬性和事件到上面返回的TextView點擊事件和標題的TextView的text屬性呢?是的,請看比較重要的后台關聯代碼類定義:
public class TitleControl extends RelativeLayout {
}
可以發現TitleControl我們是直接從RelativeLayout繼承而來的,這樣的話TitleControl就屬於一種View控件了。接下來所要做的事情,就是定義屬性和事件了。現在假設我們需要定義一個MyText屬性,那么應該怎么做呢?請看如下代碼:
public class TitleControl extends RelativeLayout {
private TextView tvBack, tvTitle;
private String title;
public TitleControl(Context context) {
super(context);
}
public TitleControl(Context context, AttributeSet attrs) {
super(context, attrs);
View view = View.inflate(context, R.layout.activity_title, this);
tvTitle = (TextView) view.findViewById(R.id.tvTitle);
tvBack = (TextView) view.findViewById(R.id.tvBack);
tvBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.title);
title = a.getString(R.styleable.title_MyText);
a.recycle();
tvTitle.setText(title, TextView.BufferType.SPANNABLE);
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
}
在上面的代碼里面我們通過View的inflate方法加載前台頁面,然后通過findViewById方法就找到了前台需要關聯的控件了。但是我們自己定義的屬性放在哪里呢?一種比較容易維護的做法就是將屬性放置在xml文件里面。下面就讓我們來看看屬性的xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="title">
<attr name="MyText" format="string"/>
</declare-styleable>
</resources>
當我們定義好屬性xml之后,就可以通過下面的這段代碼,將我們自己定義的MyText屬性關聯到TextView的Text屬性上面了。這樣就相當於實現了自定義屬性。
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.title); title = a.getString(R.styleable.title_MyText); a.recycle(); tvTitle.setText(title, TextView.BufferType.SPANNABLE);
做到這里我們就差一個自定義事件了,那么我們怎樣去定義一個事件關聯到TextView的點擊上面呢?答案是通過回調方法的方式實現的,請看回調方法的定義:
private ITitleCallback iTitleCallback;
public interface ITitleCallback {
void OnBackClickLinear();
}
public void setTitleClickLinear(ITitleCallback iTitleCallback) {
this.iTitleCallback = iTitleCallback;
}
然后在TextView點擊的時候執行如下代碼就可以了:
tvBack = (TextView) view.findViewById(R.id.tvBack);
tvBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(iTitleCallback!=null){
iTitleCallback.OnBackClickLinear();
}
}
});
好了,今天就到這里吧!如有不對,歡迎拍磚。
