在我們平時的Android開發中,有時候原生的控件無法滿足我們的需求,或者經常用到幾個控件組合在一起來使用.這個時候,我們就可以根據自己的需求創建自定義的控件了,一般通過繼承View或其子類來實現.
實現一個自定義控件一般需要下面三個步驟:
1. 設計控件中需要的屬性 (xml)
2. 實現自定義的View (java)
3. 引用自定義的View (xml)
下面我們通過實例來實現一個完整的自定義組合控件--TopBar,左右兩邊各一個Button,中間是一個TextView.
先看下最終效果:
下面通過代碼來完成自定義控件的完整過程.
.設計控件中需要的屬性
我們可以先把要實現的自定義控件畫一個草圖,來分析需要設計哪些屬性.我們需要在values資源文件夾下創建一個定義控件的xml文件.
atts.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 使用declare-styleable標簽定義控件,name為控件名 使用attr標簽定義控件的屬性,name為屬性名,format為屬性的類型 -->
<declare-styleable name="topBar">
<attr name="tbTitle" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" />
<attr name="leftText" format="string" />
<attr name="leftBackground" format="reference|color" />
<attr name="leftTextColor" format="color" />
<attr name="rightText" format="string" />
<attr name="rightBackground" format="reference|color" />
<attr name="rightTextColor" format="color" />
</declare-styleable>
</resources>
.實現自定義的View
TopBar.java
package scratchcard.cbt.com.learnuserdefinedview; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.RelativeLayout; import android.widget.TextView; /** * Created by caobotao on 15/12/9. */
public class TopBar extends RelativeLayout{ /** * 聲明控件 */
private Button leftBtn;//左按鈕
private TextView textView;//中間文本框
private Button rightBtn;//右按鈕
/** * 聲明三個控件的屬性 */
//聲明左按鈕的屬性
private String leftText;//按鈕文本
private Drawable leftBackground;//按鈕背景
private int leftTextColor;//按鈕文本顏色 //聲明中間文本框的屬性
private String tbTitle;//文本框文本
private float titleTextSize;//文本框字體大小
private int titleTextColor;//文本框字體顏色 //聲明右按鈕的屬性
private String rightText;//按鈕文本
private Drawable rightBackground;//按鈕背景
private int rightTextColor;//按鈕文本顏色
/** * 聲明三個控件的布局屬性 */
private LayoutParams leftBtnLayoutParams; private LayoutParams textViewLayoutParams; private LayoutParams rightBtnLayoutParams; //聲明左右按鈕點擊監聽
private TopBarBtnsOnClickListener listener; //創建一個監聽左右按鈕點擊的接口
public interface TopBarBtnsOnClickListener{ public void leftBtnOnClick();//左按鈕被點擊的事件
public void rightBtnOnClick();//右按鈕被點擊的事件
} //向外提供一個設置監聽的方法
public void setOnTopBarBtnsClick(TopBarBtnsOnClickListener listener){ this.listener = listener; } //重寫構造方法
public TopBar(Context context, AttributeSet attrs) { super(context, attrs); /** * 用TypedArray可以獲取用戶在xml中聲明的此控件的所有屬性,以鍵值對存儲, * K:資源文件(例 R.styleable.topBar_leftText) * V:屬性值 */ TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.topBar); //為左按鈕的屬性賦值
leftText = ta.getString(R.styleable.topBar_leftText); leftBackground = ta.getDrawable(R.styleable.topBar_leftBackground); leftTextColor = ta.getInt(R.styleable.topBar_leftTextColor,0); //為中間的文本框的屬性賦值
tbTitle = ta.getString(R.styleable.topBar_tbTitle); titleTextSize = ta.getDimension(R.styleable.topBar_titleTextSize,0); titleTextColor = ta.getInt(R.styleable.topBar_titleTextColor,0); //為右按鈕的屬性賦值
rightText = ta.getString(R.styleable.topBar_rightText); rightBackground = ta.getDrawable(R.styleable.topBar_rightBackground); rightTextColor = ta.getInt(R.styleable.topBar_rightTextColor,0); //使用完TypedArray之后需要調用其recycle()方法,以便重用
ta.recycle(); //實例化三個控件
leftBtn = new Button(context); textView = new TextView(context); rightBtn = new Button(context); //設置左按鈕的屬性
leftBtn.setText(leftText); leftBtn.setBackground(leftBackground); leftBtn.setTextColor(leftTextColor); //設置文本框的屬性
textView.setText(tbTitle); textView.setTextSize(titleTextSize); textView.setTextColor(titleTextColor); textView.setGravity(Gravity.CENTER); //設置右按鈕的屬性
rightBtn.setText(rightText); rightBtn.setBackground(rightBackground); rightBtn.setTextColor(rightTextColor); //設置此自定義控件的背景顏色
setBackgroundColor(0xFFF59563); //實例化左按鈕的布局屬性
leftBtnLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); //設置左按鈕靠左顯示
leftBtnLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE); //將左按鈕添加到本自定義控件中
addView(leftBtn,leftBtnLayoutParams); //同上
rightBtnLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); rightBtnLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE); addView(rightBtn,rightBtnLayoutParams); //同上
textViewLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); textViewLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE); addView(textView,textViewLayoutParams); //回調左按鈕的監聽事件
leftBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.leftBtnOnClick(); } }); //回調右按鈕的監聽事件
rightBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.rightBtnOnClick(); } }); } //當然,我們還可以添加其他控制此控件的方法,如設置左按鈕是否可見等等,大家可根據自己的需求進行擴展
public void setLeftBtnVisible(boolean isVisible){ leftBtn.setVisibility(isVisible ? VISIBLE : INVISIBLE); } }
.引用自定義的View
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 使用自定義的控件的屬性需要先添加命名空間 xmlns:cbt="http://schemas.android.com/apk/res-auto" 其中"cbt"可以任意指定,但是不能與系統的命名空間相同 在Android Studio中如上用res-auto, 在Eclipse需要在res后指定完整包名,如: xmlns:cbt="http://schemas.android.com/apk/res/scratchcard.cbt.com.learnuserdefinedview.TopBar" -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cbt="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="scratchcard.cbt.com.learnuserdefinedview.MainActivity">
<!-- 添加自定義控件及屬性 -->
<scratchcard.cbt.com.learnuserdefinedview.TopBar android:id="@+id/topbar" android:layout_width="wrap_content" android:layout_height="40dp" cbt:leftText = "BACK" cbt:leftBackground = "@android:color/holo_blue_bright" cbt:leftTextColor = "#FFFFFF" cbt:tbTitle = "自定義標題" cbt:titleTextSize = "10sp" cbt:titleTextColor = "#000000" cbt:rightText = "MORE" cbt:rightBackground = "@android:color/holo_blue_bright" cbt:rightTextColor = "#FFFFFF"/>
</LinearLayout>
MainActivity.java
package scratchcard.cbt.com.learnuserdefinedview; import android.app.Activity; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.ViewTreeObserver; import android.widget.Button; import android.widget.Toast; import scratchcard.cbt.com.learnuserdefinedview.TopBar.TopBarBtnsOnClickListener; public class MainActivity extends Activity { //創建自定義控件
private TopBar topBar; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化自定義控件
topBar = (TopBar) findViewById(R.id.topbar);
//為自定義控件添加按鈕的監聽事件
topBar.setOnTopBarBtnsClick(new TopBarBtnsOnClickListener() { @Override public void leftBtnOnClick() { Toast.makeText(MainActivity.this,"LEFT",Toast.LENGTH_SHORT).show(); } @Override public void rightBtnOnClick() { Toast.makeText(MainActivity.this,"RIGHT",Toast.LENGTH_SHORT).show(); } }); } }
運行項目后點擊左邊按鈕: 點擊右邊按鈕:
至此,整個自定義控件就已經完成了.雖然效果有些寒磣,但是麻雀雖小,五臟俱全.主要是通過這個實例使大家掌握自定義組合控件的過程與方法.學會了創建自定義控件的方法之后可以舉一反三完成自己的漂亮的作品.
完整源碼 : 點擊下載
作者:
caobotao
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位 置給出原文連接,否則保留追究法律責任的權利。
作者:
caobotao
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。