1需求
1) 大量界面都需要某個佈局時,我們可能會使用include去引用某個佈局文件,但缺點就是,include無法處理具體的響應事件。
2) 舉個栗子,現在你想做一個標題欄,帶Button(觸發finish方法)、還有textView(顯示標題),用include的話,你得在每一個界面都來對Button設置點擊監聽,然後在onClick()裏寫finish();然後再對textView.setText();
3) 以上是每個新手的淚。現在我們用自定義控件來擦掉眼角的翔
2自定義控件步驟
2.1準備好控件的佈局
<?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="50dp"
android:background="#4B5F6A"
android:gravity="center_vertical">
<ImageView
android:id="@+id/title_option_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:clickable="true"
android:contentDescription="@null"
android:paddingLeft="13dp"
android:paddingRight="13dp"
android:src="@drawable/back"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="@android:color/white"
android:textSize="20sp"/>
</RelativeLayout>
2.2創建控件類的構造
2.2.1意義
我們在配置文件裏直接寫控件名,系統會調用控件的構造,所以我們可以在構造裏搞點飛機:
1) 佈局:高端人士會在這裏各種draw,我就直接inflate上面的佈局了(╮(╯▽╰)╭)
2) 作用:你個控件定義來幹嘛的?這裏就可以寫了,比如本文,這個控件有個按鈕(點擊則關閉界面),和一個text(設置標題)
2.2.2返回按鈕
LayoutInflater.from(context).inflate(R.layout.view_title_with_back,//想要加載的佈局
this);//this是給加載好的佈局,再添加一個父佈局
//(聯想到adapter的inflate都寫null的,百度下即可知道區別,不過這裏寫null會怎樣我就懶得測試了)
ImageView iv_back = (ImageView) findViewById(R.id.title_option_back);
iv_back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
如上面代碼所示,我們這裏直接就把佈局inflate進來,並且在裏面找到返回按鈕,並實現監聽觸發finish()方法;2.3自定義屬性
1) 創建屬性配置文件
2) 創建屬性
<declare-styleable name="myTitleView">
<attr name="textTitle" format="string|reference" />
</declare-styleable>
name="textTitle"是你界面配置裏要用的屬性
format是格式,這裏是字符串和引用都可以(想了解更多可以百度自定義屬性的format)
3) 讓控件來使用屬性
這點好理解,比如textView裏的text屬性,你填了東西,但是textView這個類裏對這個text屬性的值取都不取,你填了也是無效的,所以同樣的,我們要在自定義控件的類裏,對我們這個自定義屬性進行取值並使用
其實自定義還有另外個方案,並不用在attrs.xml裏配置,不過相對來講不夠強大,但就是簡單點,本文就也有貼但註釋掉了;
現在可以完整的把這個自定義控件的代碼貼出來了:
package com.lie.customviewdemo.view;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.lie.customviewdemo.R;
/**
* Created by lie on 2015-11-19.
* 普通標題,具有以下功能:
* 1)具有點擊觸發finish的返回按鈕
* 2)可在配置文件裏直接設置標題文字
*/
public class TitleLayout extends RelativeLayout {
/**
* 以下代碼通過構造函數中引入的AttributeSet 去查找XML佈局的屬性名稱,然後找到它對應引用的資源ID去找值
* 介紹了兩種方式,一種需要在attrs.xml裏配置(自由度高),一種不需要
* @param context
* @param attrs
*/
public TitleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* 以下代碼需要在attrs.xml裏設置你自己的屬性,很靈活
*
*/
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.myTitleView);
String titleText = a.getString(R.styleable.myTitleView_textTitle);//這裏對應你自定義屬性的總名字
/**
* 以下的直接用,不用另外在attrs配置
*
*/
// int resouceId = attrs.getAttributeResourceValue(null,//第一個參數:命名空間名
// "textTitle",//第二個參數:xml文件裏設置的屬性名,用的時候務必屬性名要一致,前面不用加android:或者其他命名空間
// -1);//第三個參數:默認值
// String Text;
// if (resouceId > 0) {
// Text = context.getResources().getText(resouceId).toString();
// } else {
// Text = resouceId+"";
// }
LayoutInflater.from(context).inflate(R.layout.view_title_with_back,//想要加載的佈局
this);//this是給加載好的佈局,再添加一個父佈局(聯想到adapter的inflate都寫null的,百度下即可知道區別,不過這裏寫null會怎樣我就懶得測試了)
ImageView iv_back = (ImageView) findViewById(R.id.title_option_back);
iv_back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
TextView tv_title = (TextView) findViewById(R.id.tv_title);
tv_title.setText(titleText);
// tv_title.setText(Text);
}
}
完成上面的代碼,那麼這個控件就是一個:帶有點擊會finish的按鈕、可以顯示text的好標題了2.4使用自定義控件
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:lie="http://schemas.android.com/apk/res-auto"
lie是命名空間,你喜歡叫啥都行;<com.lie.customviewdemo.view.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
lie:textTitle="測試標題1"/>