在Android中,複合控件是非常常見的,下面以建立一個标題欄為例,講解建立自定義複合控件的過程。
以下圖為例:我們要建立一個标題欄,這個标題欄是由左邊的Button、右邊的Button以及中間的TextView複合而成的,而我們希望能夠直接在這個自定義标題欄設定裡面的Button和TextView的屬性資訊。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyROBlL5kzMwMTMwkTMxETMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
具體實作過程如下:
1、首先在res資源目錄的values目錄建立一個attrs.xml的屬性定義檔案,并在該檔案中定義相應的屬性。代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TopBar">
<attr name="titleText" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" />
<attr name="leftText" format="string" />
<attr name="leftTextSize" format="dimension" />
<attr name="leftTextColor" format="color" />
<attr name="leftBackground" format="reference|color" />
<attr name="rightText" format="string" />
<attr name="rightTextSize" format="dimension" />
<attr name="rightTextColor" format="color" />
<attr name="rightBackground" format="reference|color" />
</declare-styleable>
</resources>
這裡定義了标題文字的内容、大小、顔色,左邊按鈕的文字内容、大小、顔色以及按鈕的背景,右邊按鈕的文字内容、大小、顔色以及按鈕的背景,值得一提的是,這裡的背景屬性既可以是顔色屬性,也可以是引用屬性,如引用一張圖檔,故這裡使用了“|”來分隔不同的屬性——“reference|color”。
2、自定義的ComplexView代碼如下:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ComplexView extends LinearLayout {
private String titleText;//标題文字
private float titleTextSize;//标題文字大小
private int titleTextColor;//标題文字顔色
private String leftText;//左邊按鈕文字
private float leftTextSize;//左邊按鈕文字大小
private int leftTextColor;//左邊按鈕文字顔色
private Drawable leftBackground;//左邊按鈕背景
private String rightText;//右邊按鈕文字
private float rightTextSize;//右邊按鈕文字大小
private int rightTextColor;//右邊按鈕文字顔色
private Drawable rightBackground;//右邊按鈕背景
private Button leftBtn;
private TextView titleTv;
private Button rightBtn;
public ComplexView(Context context) {
super(context);
}
public ComplexView(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(context.obtainStyledAttributes(attrs, R.styleable.TopBar));
View view = LayoutInflater.from(context).inflate(R.layout.complex_view, this);
leftBtn = (Button) view.findViewById(R.id.left_btn);
rightBtn = (Button) view.findViewById(R.id.right_btn);
titleTv = (TextView) view.findViewById(R.id.title_tv);
//設定标題屬性
titleTv.setText(titleText);
titleTv.setTextSize(titleTextSize);
titleTv.setTextColor(titleTextColor);
//設定左邊按鈕屬性
leftBtn.setText(leftText);
leftBtn.setTextSize(leftTextSize);
leftBtn.setTextColor(leftTextColor);
leftBtn.setBackgroundDrawable(leftBackground);
//設定右邊按鈕屬性
rightBtn.setText(rightText);
rightBtn.setTextSize(rightTextSize);
rightBtn.setTextColor(rightTextColor);
rightBtn.setBackgroundDrawable(rightBackground);
//左右按鈕點選事件
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
onTopBarClickListener.leftClick();
}
});
rightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
onTopBarClickListener.rightClick();
}
});
}
//擷取自定義屬性集
private void parseAttributes(TypedArray ta) {
titleText = ta.getString(R.styleable.TopBar_titleText);
titleTextSize = ta.getDimension(R.styleable.TopBar_titleTextSize, 25);
titleTextColor = ta.getColor(R.styleable.TopBar_titleTextColor, 0);
leftText = ta.getString(R.styleable.TopBar_leftText);
leftTextSize = ta.getDimension(R.styleable.TopBar_leftTextSize, 16);
leftTextColor = ta.getColor(R.styleable.TopBar_leftTextColor, 0);
leftBackground = ta.getDrawable(R.styleable.TopBar_leftBackground);
rightText = ta.getString(R.styleable.TopBar_rightText);
rightTextSize = ta.getDimension(R.styleable.TopBar_rightTextSize, 16);
rightTextColor = ta.getColor(R.styleable.TopBar_rightTextColor, 0);
rightBackground = ta.getDrawable(R.styleable.TopBar_rightBackground);
ta.recycle();
}
//為左右按鈕設定點選事件,使用接口回調方法
public interface onTopBarClickListener {
void leftClick();
void rightClick();
}
onTopBarClickListener onTopBarClickListener = null;
public void setOnTopBarClickListener(onTopBarClickListener onTopBarClickListener) {
this.onTopBarClickListener = onTopBarClickListener;
}
}
其中complex_view布局檔案如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/left_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp" />
<TextView
android:id="@+id/title_tv"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center" />
<Button
android:id="@+id/right_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp" />
</LinearLayout>
3、在activity_main中引入ComplexView,為了引用自定義控件的屬性,需要在activity_main布局檔案中加入下面一句:
xmlns:app="http://schemas.android.com/apk/res-auto"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.exam.myapplication.ComplexView
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#008577"
app:leftBackground="@drawable/btn_shape"
app:leftText="傳回"
app:leftTextColor="#ffffff"
app:leftTextSize="8sp"
app:rightBackground="@drawable/btn_shape"
app:rightText="更多"
app:rightTextColor="#ffffff"
app:rightTextSize="8sp"
app:titleText="标題"
app:titleTextColor="#ffffff"
app:titleTextSize="10sp" />
</LinearLayout>
上面的btn_shape其實是按鈕的背景,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="3dp"/>
<solid android:color="#00574B"/>
</shape>
4、我在自定義的ComplexView中還為左右按鈕增加了點選事件,這裡使用了接口回調方法,可以在MainActivity中實作具體的邏輯。代碼如下:
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
ComplexView topBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
topBar = (ComplexView) findViewById(R.id.top_bar);
topBar.setOnTopBarClickListener(new ComplexView.onTopBarClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this, "傳回", Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this, "更多", Toast.LENGTH_SHORT).show();
}
});
}
}
建立自定義複合控件的整個流程到此介紹完畢。