Android通用標(biāo)題欄組合控件

由于項目中經(jīng)常用到此種組合控件,就封裝了下,具體效果看下圖,老司機(jī)可以繞道哈!

Image.png
一、主要功能
  • 支持左右圖標(biāo)動態(tài)設(shè)置
  • 支持左右、中間文字動態(tài)修改
  • 支持字體大小、顏色修改
  • 支持左右圖標(biāo),左中右文字隱藏顯示
  • 支持左右圖標(biāo)和文案的點(diǎn)擊監(jiān)聽
二、基本使用方式
<com.example.android.customvView.CustomNavigatorBar
        android:id="@+id/customView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:leftImage="@drawable/leftarrow"
        app:rightImage="@drawable/rightarrow"
        app:leftImageVisiable="true"
        app:rightImageVisible="true"
        app:leftText="左邊"
        app:rightText="右邊"
        app:midText="標(biāo)題"
        app:midTextFontColor="#ffffff"
        app:leftTextColor="#ffffff"
        app:rightTextColor="@color/colorAccent"
        app:titleBarBackground="@color/colorPrimary"
        app:midTextFontSize="18px"
        app:leftTextVisibale="true"
        app:rightTextVisible="true"
        app:leftTextFontSize="16px"
        app:rightTextFontSize="16px"
        />

三、基本屬性介紹

屬性名 屬性說明 屬性值
titleBarBackground 標(biāo)題欄背景色 color,reference,默認(rèn)為white
leftImage 左邊圖片 reference
leftImageVisiable 左邊圖片是否可見 boolean,默認(rèn)為true,顯示控件
leftText 左邊文案 string,reference
leftTextVisibale 左邊文案是否可見 boolean,默認(rèn)為true,顯示控件
leftTextFontSize 左邊文案字體大小 dimension,reference,默認(rèn)為16sp
leftTextColor 左邊文案字體顏色 color,reference
midText 中間文案 string,reference
midTextVisiable 中間文案是否可見 boolean,默認(rèn)為true,顯示控件
midTextFontSize 中間文案字體大小 dimension,reference,默認(rèn)為18sp
midTextFontColor 中間文案字體顏色 color,reference
rightText 右邊文案 color,reference
rightTextVisible 右邊文案是否可見 boolean,默認(rèn)為true,顯示控件
rightTextFontSize 右邊文案字體大小 dimension,reference,默認(rèn)為16sp
rightTextColor 右邊文案字體顏色 color,reference
rightImage 右邊圖片 reference
rightImageVisible 右邊圖片是否可見 boolean,默認(rèn)為true,顯示控件

四、組合控件類

package com.example.android.customvView;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.android.R;

/**
 * Created by WangLu on 2016/12/6.
 * E-mail:wang_lu90125@163.com
 */

public class CustomNavigatorBar extends RelativeLayout implements View.OnClickListener {

    private ImageView leftImage;
    private TextView leftText;
    private TextView midText;
    private ImageView rightImage;
    private TextView rightText;
    private OnCustomClickListener customClickListener ;

    public CustomNavigatorBar(Context context) {
        this(context,null);
    }

    public CustomNavigatorBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CustomNavigatorBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        iniView(context);
        /**
         * 兩種初始化的不同,請看下面注釋講解
         */
        initOneType(context, attrs);//第一種初始化
//        initTwoType(context, attrs);//第二種初始化
    }

    private void iniView(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.custom_title_bar, this, true);
        leftImage = (ImageView) view.findViewById(R.id.left_image);
        leftText = (TextView) view.findViewById(R.id.left_text);
        midText = (TextView) view.findViewById(R.id.mid_text);
        rightText = (TextView) view.findViewById(R.id.right_text);
        rightImage = (ImageView) view.findViewById(R.id.right_image);

    }

    /**
     * 有興趣的請參考鴻洋大神的自定義講解
     *
     * 初始化屬性值:這種寫法,不管你在布局中有沒有使用該屬性,都會執(zhí)行g(shù)etXXX方法賦值
     *假設(shè)一個場景:
     *    private int attr_mode = 1;//默認(rèn)為1
     *   //然后你在寫getXXX方法的時候,是這么寫的:
     *   attr_mode = array.getInt(i, 0);
     *
     *   可能你的自定義屬性有個默認(rèn)的值,然后你在寫賦值的時候,一看是整形,就默默的第二個參數(shù)就給了個0,
     *   然而用戶根本沒有在布局文件里面設(shè)置這個屬性,你卻在運(yùn)行時將其變?yōu)榱?(而不是默認(rèn)值),而第二種就不存在這個問題。
     *   當(dāng)然這個場景可以由規(guī)范的書寫代碼的方式來避免,(把默認(rèn)值提取出來,都設(shè)置對就好了)。
     *
     * 場景二:
     *
     *   其實(shí)還有個場景,假設(shè)你是繼承自某個View,父類的View已經(jīng)對該成員變量進(jìn)行賦值了,然后你這邊需要根據(jù)用戶的設(shè)置情況,
     *   去更新這個值,第一種寫法,如果用戶根本沒有設(shè)置,你可能就將父類的賦值給覆蓋了。
     *
     * @param context
     * @param attrs
     */
    private void initTwoType(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomNavigatorBar);
        if (null != typedArray) {
            Drawable leftDrawable = typedArray.getDrawable(R.styleable.CustomNavigatorBar_leftImage);
            leftImage.setImageDrawable(leftDrawable);

            boolean leftImageVisible = typedArray.getBoolean(R.styleable.CustomNavigatorBar_leftImageVisiable, false);
            if (leftImageVisible) {
                leftImage.setVisibility(View.VISIBLE);
            } else {
                leftImage.setVisibility(View.GONE);
            }

            typedArray.recycle();
        }
    }

    /**注:如果switch報錯,請改為if-else
     * 初始化屬性值:這種寫法,只有在布局中設(shè)置了該屬性值后,才會調(diào)用getXXX()方法賦值
     * @param context
     * @param attrs
     */
    private void initOneType(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomNavigatorBar);
        int totalAttributes = typedArray.getIndexCount();
        for (int i = 0 ; i<totalAttributes ;i++) {
            int index = typedArray.getIndex(i);
            switch (index) {
                case R.styleable.CustomNavigatorBar_leftImage:
                    leftImage.setImageDrawable(typedArray.getDrawable(index));
                    break ;
                case R.styleable.CustomNavigatorBar_leftImageVisiable:
                    getVisible(typedArray,leftImage,index);
                    break ;
                case R.styleable.CustomNavigatorBar_leftText:
                    leftText.setText(typedArray.getString(index));
                    break ;
                case R.styleable.CustomNavigatorBar_leftTextFontSize:
                    leftText.setTextSize(typedArray.getDimensionPixelSize(index, (int) sp2px(context,16)));
                    break ;
                case R.styleable.CustomNavigatorBar_leftTextColor:
                    leftText.setTextColor(typedArray.getColor(index, Color.WHITE));
                    break ;
                case R.styleable.CustomNavigatorBar_leftTextVisibale:
                    getVisible(typedArray,leftText,index);
                    break ;
                case R.styleable.CustomNavigatorBar_midText:
                    midText.setText(typedArray.getString(index));
                    break ;
                case R.styleable.CustomNavigatorBar_midTextVisiable:
                    getVisible(typedArray,midText,index);
                    break ;
                case R.styleable.CustomNavigatorBar_midTextFontSize:
                    midText.setTextSize(typedArray.getDimensionPixelSize(index,(int) sp2px(context,18)));
                    break ;
                case R.styleable.CustomNavigatorBar_midTextFontColor:
                    midText.setTextColor(typedArray.getColor(index,Color.WHITE));
                case R.styleable.CustomNavigatorBar_rightImage:
                    rightImage.setImageDrawable(typedArray.getDrawable(index));
                    break ;
                case R.styleable.CustomNavigatorBar_rightImageVisible:
                    getVisible(typedArray,rightImage,index);
                    break ;
                case R.styleable.CustomNavigatorBar_rightText:
                    rightText.setText(typedArray.getString(index));
                    break ;
                case R.styleable.CustomNavigatorBar_rightTextFontSize:
                    rightText.setTextSize(typedArray.getDimensionPixelSize(index,(int) sp2px(context,16)));
                    break ;
                case R.styleable.CustomNavigatorBar_rightTextColor:
                    rightText.setTextColor(typedArray.getColor(index, Color.WHITE));
                    break ;
                case R.styleable.CustomNavigatorBar_rightTextVisible:
                    getVisible(typedArray,rightText,index);
                    break ;
                case R.styleable.CustomNavigatorBar_titleBarBackground:
                    int titleBarBackgroundColor = typedArray.getColor(index, Color.GREEN);
                    setBackgroundColor(titleBarBackgroundColor);
                    break ;
            }
        }
        typedArray.recycle();
    }

    /**
     * 用來隱藏顯示View,只有g(shù)one 和 visible兩種情況,因?yàn)閕nVisible感到在這里用不到,就沒有封裝
     * @param typedArray
     * @param view
     * @param index
     */
    private void getVisible(TypedArray typedArray ,View view,int index) {
        boolean visible = typedArray.getBoolean(index, false);
        if (visible) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    }

    private void setVisible(View view ,boolean visible) {
        if (visible) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    }

    /**
     * 兩種監(jiān)聽只能使用其中一種,不能同時使用
     *
     * ----------------------------第一種點(diǎn)擊監(jiān)聽開始處----------------------------------------
     * @param clickListener
     */
    public void setLeftImageOnClickListener(View.OnClickListener clickListener) {
        if (null != clickListener) {
            leftImage.setOnClickListener(clickListener);
        }
    }

    public void setLeftTextOnClickListener(View.OnClickListener clickListener) {
        if (null != clickListener) {
            leftText.setOnClickListener(clickListener);
        }
    }
    public void setRightImageOnClickListener(View.OnClickListener clickListener) {
        if (null != clickListener) {
            rightImage.setOnClickListener(clickListener);
        }
    }

    public void setRightTextOnClickListener(View.OnClickListener clickListener) {
        if (null != clickListener) {
            rightText.setOnClickListener(clickListener);
        }
    }

    /**
     * ----------------------------第二種點(diǎn)擊監(jiān)聽開始處----------------------------------------
     * @return
     */
    public void addViewClickListener(OnCustomClickListener listener) {
        leftText.setOnClickListener(this);
        leftImage.setOnClickListener(this);
        rightImage.setOnClickListener(this);
        rightText.setOnClickListener(this);
        this.customClickListener = listener ;
    }

    public interface OnCustomClickListener{
        void onClickListener(View rootView);
    }

    @Override
    public void onClick(View view) {
        customClickListener.onClickListener(view);
    }

    /**
     * ----------------------------第二種點(diǎn)擊監(jiān)聽結(jié)束處----------------------------------------
     * @return
     */

    public ImageView getLeftImageView(){
        return leftImage;
    }
    public ImageView getRightImage(){
        return rightImage;
    }

    public TextView getLeftText(){
        return leftText;
    }

    public TextView getRightText(){
        return rightText;
    }

    public TextView getMidText(){
        return midText;
    }

    /**
     * 設(shè)置textView的標(biāo)題內(nèi)容
     * @param textDescribe
     */
    public void setLeftText(String textDescribe) {
        if (null != textDescribe) {
            leftText.setText(textDescribe);
        }
    }
    public void setMidText(String textDescribe) {
        if (null != textDescribe) {
            midText.setText(textDescribe);
        }
    }

    public void setRightText(String textDescribe) {
        if (null != textDescribe) {
            rightText.setText(textDescribe);
        }
    }

    /**
     * 設(shè)置textView的字體顏色
     * @param textColor
     */
    public void setLeftTextColor(int textColor) {
        leftText.setTextColor(textColor);
    }
    public void setMidTextColor(int textColor) {
        midText.setText(textColor);
    }

    public void setRightTextColor(int textColor) {
        rightText.setText(textColor);
    }

    /**
     * 設(shè)置title欄背景色
     * @param color
     */
    public void setTitleBarBackground(int color) {
        setBackgroundColor(color);
    }

    /**
     * 左右控件的隱藏顯示
     * @param visible
     */
    public void setLeftImageVisible(boolean visible) {
        setVisible(leftImage, visible);
    }
    public void setLeftTextVisible(boolean visible) {
        setVisible(leftText, visible);
    }
    public void setRifhtImageVisible(boolean visible) {
        setVisible(rightImage, visible);
    }
    public void setRightTextVisible(boolean visible) {
        setVisible(rightText, visible);
    }


    private float sp2px(Context context, float defaultVal) {
        float applyDimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, defaultVal, context.getResources().getDisplayMetrics());
        return applyDimension ;
    }

    private float dp2px(Context context, float defaultVal) {
        float applyDimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, defaultVal, context.getResources().getDisplayMetrics());
        return applyDimension ;
    }

    private float dp2px(Context context, int defultVal) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (float) (defultVal*scale + 0.5);
    }

}

五、attrs.xml

<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <declare-styleable name = "CustomNavigatorBar">
        <attr name="titleBarBackground" format="reference|color" />
        <attr name="leftImage" format="reference" />
        <attr name="leftImageVisiable" format="boolean" />
        <attr name="leftText" format="string|reference" />
        <attr name="leftTextVisibale" format="boolean" />
        <attr name="leftTextFontSize" format="dimension|reference" />
        <attr name="leftTextColor" format="color|reference" />
        <attr name="midText" format="string|reference" />
        <attr name="midTextVisiable" format="boolean" />
        <attr name="midTextFontSize" format="dimension|reference" />
        <attr name="midTextFontColor" format="color|reference" />
        <attr name="rightText" format="string|reference" />
        <attr name="rightTextVisible" format="boolean" />
        <attr name="rightTextFontSize" format="dimension|reference" />
        <attr name="rightTextColor" format="color|reference" />
        <attr name="rightImage" format="reference" />
        <attr name="rightImageVisible" format="boolean" />
    </declare-styleable>
</resources>

六、組合控件布局(custom_title_bar.xml)

  為什么使用merge,因?yàn)榻M合控件已經(jīng)extends RelativeLayout,如果根布局還是用viewGroup的話,會使布局重復(fù)嵌套,影響View的繪制性能;
<?xml version = "1.0" encoding = "utf-8" ?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/left_image"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerVertical="true"
        android:minHeight="20dp"
        android:minWidth="20dp"
        android:layout_marginLeft="10dp"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/left_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@+id/left_image"
        android:gravity="center"
        android:minHeight="45dp"
        android:text="left" />

    <TextView
        android:id="@+id/mid_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:minHeight="45dp"
        android:text="mid"
        android:textSize="17sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:minHeight="45dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/right_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:layout_toLeftOf="@+id/right_image"
            android:gravity="center"
            android:minHeight="45dp"
            android:text="right" />

        <ImageView
            android:id="@+id/right_image"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:minHeight="20dp"
            android:minWidth="20dp"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>
</merge>

七、具體使用

CustomNavigatorBar customNavigatorBar = (CustomNavigatorBar) findViewById(R.id.customView);
        /**
         * 第一種監(jiān)聽的具體實(shí)現(xiàn)
         */
        customNavigatorBar.setLeftImageOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"left",Toast.LENGTH_SHORT).show();
            }
        });

        /**
         * 第二種監(jiān)聽的具體實(shí)現(xiàn)
         */
        customNavigatorBar.addViewClickListener(new CustomNavigatorBar.OnCustomClickListener() {
            @Override
            public void onClickListener(View rootView) {
                switch (rootView.getId()) {
                    case R.id.right_image:
                        Toast.makeText(MainActivity.this,"right_image is clicked",Toast.LENGTH_SHORT).show();
                        break ;
                    case R.id.left_image:
                        Toast.makeText(MainActivity.this,"left_image is clicked",Toast.LENGTH_SHORT).show();
                        break ;
                }
            }
        });

八、github倉庫

如有什么問題,敬請?zhí)岢觯指兄x!希望越來越好,謝謝!

如果喜歡,還請點(diǎn)擊start,喜歡支持一下了,謝謝O(∩_∩)O~。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,287評論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,241評論 4 61
  • 卜算子·走西 【21世紀(jì)】霍錦威 粵客走西南,久念宗海好。 高原斷陷水色碧,彩云弄波濤。 及笄已花信,齊留歲月刀。...
    霍錦威Focus閱讀 608評論 0 1
  • 說走技術(shù)的道路輕松, 問題就擺在那里, 解決它你就成長了, 可是,問題那么多 技術(shù)淘汰那么快! 你剛掌握好一點(diǎn), ...
    逍遙萍閱讀 143評論 0 0
  • 天涼小酥風(fēng) 花香意醉迷 恐驚白玉仙 不舍動蘭楫
    漠塘閱讀 267評論 3 3