開發:用自定義控件來實現常用的標題欄

1需求

1)       大量界面都需要某個佈局時,我們可能會使用include去引用某個佈局文件,但缺點就是,include無法處理具體的響應事件。

2)       舉個栗子,現在你想做一個標題欄,帶Button(觸發finish方法)、還有textView(顯示標題),用include的話,你得在每一個界面都來對Button設置點擊監聽,然後在onClick()裏寫finish();然後再對textView.setText();

3)       以上是每個新手的淚。現在我們用自定義控件來擦掉眼角的翔

2自定義控件步驟

2.1準備好控件的佈局

預覽圖:
文件名:view_title_with_back
<?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()方法;
按鈕很簡單,可是問題來了,我們的text怎麼辦呢?
首先可以肯定的是,我們同樣可以在這裏把textView給find出來,問題就是我們不知道具體的界面的text是什麼。我們也不能接受走回include的老路——在每個Activity界面裏再去設置,假如我們可以用普通的textView那樣擁有text屬性就好了,那我們可以直接配置!
下面就介紹自定義屬性~~

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是命名空間,你喜歡叫啥都行;
後面的這麼寫就行了,我之前是直接定義到自定義控件這個類的包的位置的,不過as更推薦上面這麼寫,那更簡單
<com.lie.customviewdemo.view.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        lie:textTitle="測試標題1"/>

搞定~~~~~~~~

後話:可能還有人說,即便這樣還是接受不了,那可以考慮在baseActivity裏添加帶返回和可以設置標題的東西,不過暫時我還不打算研究這塊,等弄會了再搬上來吧



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章