Android自訂控制項之建立可複用的群組控制項_Android

來源:互聯網
上載者:User

前面已學習了一種自訂控制項的實現,是Andriod 自訂控制項之音頻條,還沒學習的同學可以學習下,學習了的同學也要去溫習下,一定要自己完全的掌握了,再繼續學習,貪多嚼不爛可不是好的學習方法,我們爭取學習了一種技術就會一種技術,而且不光看了就算了,最好的方法就是看完我自己再練習下,再擴充下,在原來的基礎上在添加一些東西,比如,增加一些功能實現等等。

今天我們打算學習下另外一種自訂控制項,就是建立可重複使用的群組控制項,那麼問題來了:

什麼是可重複使用?
就是在應用中,可以在多個地方共同使用一套代碼。這樣不僅能減少我們的工作量,而且還能保持應用風格的一致,這種應用最多最直接的體現就是統一風格樣式的標題列。

那什麼又是群組控制項呢?
群組控制項,顧名思義就是多個控制群組合在一起,相互協作共同完成某些特定的功能。

下面我們就針對app應用中風格統一的標題列來開始我們的學習。

首先,既然是一組組合的控制項,那就必須有一個可以來包含這些控制項的容器,我們所接觸的可以存放控制項的容器很多,比如LinearLayout、RelativeLayout等等多種Layout,今天我們就選擇RelativeLayout來做我們的容器。和以前一樣,我們先定義一個CompositeViews類來繼承RelativeLayout類,並重寫它的構造方法,代碼如下:

public class CompositeViews extends RelativeLayout{ public CompositeViews(Context context) {  this(context,null); } public CompositeViews(Context context, AttributeSet attrs) {  this(context, attrs,0); } public CompositeViews(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr); } }

接下來,我們再定義三個TextView控制項,分別是mLefeText,mRightText,textTitle用來顯示“返回”,“搜尋”以及“標題”並且使用LayoutParams規定它們在容器裡面的對齊。請看代碼:

public class CompositeViews extends RelativeLayout{ private TextView mLefeText; private TextView mRightText; private TextView textTitle; private LayoutParams leftLayoutParams; private LayoutParams ridhtLayoutParams; private LayoutParams titleLayoutParams; public CompositeViews(Context context) {  this(context,null); } public CompositeViews(Context context, AttributeSet attrs) {  this(context, attrs,0); } public CompositeViews(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr);  initView(context); }

initView(context)方法中是用來初始化三個群組控制項的,請看:

 private void initView(Context context) {  mLefeText = new TextView(context);  mRightText = new TextView(context);  textTitle = new TextView(context);  /*   * 左按鈕位置   */  leftLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  leftLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);  mLefeText.setText("返回");  mLefeText.setTextSize(22);  /*   * 右按鈕位置   */  ridhtLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  ridhtLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);  mRightText.setText("搜尋");  mRightText.setTextSize(22);  /*   * 中間標題位置   */  titleLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  titleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);  textTitle.setText("這是一個標題");  textTitle.setTextSize(22); }

ok,以上的代碼已經實現了群組控制項的顯示和對齊,我們把定義的View添加到布局檔案中並在Activity載入吧

activity_main.xml檔案

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:background="#999999" android:layout_height="wrap_content" android:orientation="vertical"> <com.sanhuimusic.mycustomview.view.CompositeViews  android:id="@+id/topBar"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  /></LinearLayout>

MainActivity:

public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main); }}

我們先來運行看下結果

ok,已顯示出來了,但是相信大家也看出來了,這上面的代碼中,各個控制項中的屬性是都是我們固定寫死的,既然我們是建立可服用的控制項,固定寫死的東西肯定是不可取的,那麼我們怎麼可以靈活地擷取控制項的屬性,以至於能達到複用呢?

這就必須要接觸另外一種技術了,就是自訂屬性。用我們自訂的屬於可以在每次使用我們定義的控制項時為其分配屬性即可。下面我們來學習下自訂屬性。

自訂屬性其實也是相當的簡單,首先,我們現在資源檔res下values目錄下建立一個attrs.xml檔案(eclipse內建,as自建),建立的attrs.xml是一個包含如下代碼的檔案:

<?xml version="1.0" encoding="utf-8"?><resources></resources>

在resources中有各種屬性供我們使用,同學們可以自己看下。根據我們現在的需求,我們選擇使用declare-styleable來聲明我們的屬性集,然後為其定義特有的name屬性,這個name是供我們在使用自訂屬性時,通過它可以尋找到裡面的所有屬性。請看如下代碼:

<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="CompositeViews">  <attr name="titleText" format="string"/>  <attr name="titleTextSize" format="dimension"/>  <attr name="titleColor" format="color"/>  <attr name="titleBackground" format="color|reference"/>  <attr name="leftTextColor" format="color"/>  <attr name="leftBackground" format="color|reference"/>  <attr name="leftText" format="string"/>  <attr name="leftTextSize" format="dimension"/>  <attr name="rightTextColor" format="color"/>  <attr name="rightBackground" format="color|reference"/>  <attr name="rightText" format="string"/>  <attr name="rightTextSize" format="dimension"/> </declare-styleable></resources>

單獨拿一行屬性來解析下它所代表的含義:如

好了,自訂屬性我們已學習完畢,那麼該怎麼使用我們自己定義的屬性呢?其實也很簡單,在我們的activity_main.xml檔案中直接使用我們定義的屬性就可以了,但是在使用是之前必須在指定引用第三方控制項的命名空間,在跟布局檔案中添加如下一行代碼:

xmlns:custom="http://schemas.android.com/apk/res-auto"

custom是我們第三方命名空間的名字,可以任意命名,我們在使用自訂屬性時必須以它開頭。請看代碼:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:background="#999999" android:layout_height="wrap_content" android:orientation="vertical"> <com.sanhuimusic.mycustomview.view.CompositeViews  android:id="@+id/topBar"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  custom:titleText="@string/titleText"  custom:titleColor="#000000"  custom:titleTextSize="@dimen/titleTextSize"  custom:titleBackground="#999999"  custom:leftText="@string/leftText"  custom:leftTextColor="#FFFFFF"  custom:leftBackground="#666666"  custom:leftTextSize="@dimen/leftTextSize"  custom:rightText="@string/rightText"  custom:rightTextColor="#FFFFFF"  custom:rightBackground="#666666"  custom:rightTextSize="@dimen/rightTextSize"  /> </LinearLayout>

我們是使用custom加上我們自訂屬性裡面< attr name="titleText" format="string"/>裡的name值來動態設定屬性值的,如:custom:titleText="@string/titleText"。

ok,在我們xml檔案中已設定好屬性值,那麼該怎麼顯示出來呢?這個是需要通過一個類型組TypedArray來擷取的,它裡麵包含各種從AttributeSet屬性集中擷取屬性的方法,所以我們修改上面的構造方法和initView(context)方法,如下所示:

 private void initView(Context context, AttributeSet attrs) {  mLefeText = new TextView(context);  mRightText = new TextView(context);  textTitle = new TextView(context);  /**   * 擷取自訂屬性   */  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CompositeViews);  String titleText = typedArray.getString(R.styleable.CompositeViews_titleText);  float titleTextSize = typedArray.getDimension(R.styleable.CompositeViews_titleTextSize, 16);  int titleColor = typedArray.getColor(R.styleable.CompositeViews_titleColor,0);  Drawable titleBackground = typedArray.getDrawable(R.styleable.CompositeViews_titleBackground);  String leftText = typedArray.getString(R.styleable.CompositeViews_leftText);  int leftTextColor = typedArray.getColor(R.styleable.CompositeViews_leftTextColor, 0);  float leftTextSize = typedArray.getDimension(R.styleable.CompositeViews_leftTextSize, 16);  Drawable leftBackground = typedArray.getDrawable(R.styleable.CompositeViews_leftBackground);  String rightText = typedArray.getString(R.styleable.CompositeViews_rightText);  int rightTextColor = typedArray.getColor(R.styleable.CompositeViews_rightTextColor, 0);  float rightTextSize = typedArray.getDimension(R.styleable.CompositeViews_rightTextSize, 16);  Drawable rightBackground = typedArray.getDrawable(R.styleable.CompositeViews_rightBackground);  typedArray.recycle();  /*   * 左按鈕位置   */  leftLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  leftLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);  mLefeText.setText(leftText);  mLefeText.setTextColor(leftTextColor);  mLefeText.setTextSize(leftTextSize);  mLefeText.setBackground(leftBackground);  addView(this.mLefeText,leftLayoutParams);   /*   * 右按鈕位置   */  ridhtLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  ridhtLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);  mRightText.setText(rightText);  mRightText.setTextColor(rightTextColor);  mRightText.setTextSize(rightTextSize);  mRightText.setBackground(rightBackground);  addView(mRightText,ridhtLayoutParams);  /*   * 中間標題位置   */  titleLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  titleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);  textTitle.setText(titleText);  textTitle.setTextSize(titleTextSize);  textTitle.setTextColor(titleColor);  textTitle.setBackground(titleBackground);  addView(textTitle,titleLayoutParams); }

代碼解釋:首先通過上下文context擷取到屬性存放到TypedArray 中,然後通過TypedArray 裡封裝好的各種方法擷取對應的屬性值,然後再分別為我們的控制項設定屬性。這樣就完成了,自訂屬性的使用,並且複用度高,每當需要使用標題列是都只需要在xml中添加我們定義的View控制項,為其配置屬性即可使用,節約了開發時間,提高了效率,並且還保持的app風格的一致。

好,到這裡感覺已經講完了整個過程吧,其實還有一個重要的實現還沒有講。我們的控制項已經可以呈現出來了,但是怎麼完成裡面控制項的作用呢?

這裡比較常見的做法是利用回調機制來實現功能的開發,首先我們先定義一個介面,建立兩個方法,用於左右控制項的點擊事件。

 public interface TopBarClickListener{   void leftClickListener();   void rightClickListener(); }

然後在構造方法中為左右控制項添加點擊事件,但不實現功能,等待調用者自己實現:

private void setListener() {  mLefeText.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    mTopBarClickListener.leftClickListener();   }  });  mRightText.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    mTopBarClickListener.rightClickListener();   }  }); }

再者,把定義好的介面暴露給調用者:

 public void setOnTopBarClickListener(TopBarClickListener topBarClickListener){  mTopBarClickListener = topBarClickListener; }

最後,誰調用,誰實現。這就完成了不同介面複用控制項實現不同的功能的便利。在這裡我們只在MainActivity中列印Toast就可以了。

public class MainActivity extends AppCompatActivity { private CompositeViews topBar; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  topBar = (CompositeViews) findViewById(R.id.topBar);  topBar.setOnTopBarClickListener(new CompositeViews.TopBarClickListener(){   @Override   public void leftClickListener() {    ToastUtil.makeText(MainActivity.this,"您點擊了返回鍵",Toast.LENGTH_SHORT).show();   }   @Override   public void rightClickListener() {    ToastUtil.makeText(MainActivity.this,"您點擊了搜尋鍵",Toast.LENGTH_SHORT).show();   }  }); }}

OK,看看結果吧

好,已經可以實現我們的需求了,是不是學會很多呢。

今天主要講了android自訂View中另一種的實現,並且還學習了自訂屬性,同學們下去好好消化下,並自己動手現實一兩個例子吧,好了,今天就講到這裡,謝謝大家。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.