自定义ActionBar 显示规则简析

来源:互联网 发布:js原型对象 编辑:程序博客网 时间:2024/06/05 16:38
我们的APP做了做到风格统一和简化代码

通常会统一做一个titleBar

类似这种



这种


总的来说 是这个统一模式


我们可以首先创建一个titleBar 的xml布局,可供我们调试UI
毕竟这个比较于画更简单方便一点

view_action_bar.xml
<?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="@dimen/space_45">    <TextView        android:id="@+id/left_text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"/>    <ImageView        android:id="@+id/left_image"        android:layout_width="42dp"        android:layout_height="42dp"        android:layout_centerVertical="true"        android:padding="10dp"        android:scaleType="fitStart"        android:src="@drawable/icon_arrow_left_green"/>    <TextView        android:id="@+id/title_text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:ellipsize="end"        android:maxEms="8"        android:singleLine="true"        android:text="主页"        android:textColor="@color/black"        android:textSize="@dimen/text_size_17"/>    <ImageView        android:id="@+id/title_image"        android:layout_width="42dp"        android:layout_height="42dp"        android:layout_centerVertical="true"        android:padding="15dp"        android:scaleType="fitStart"/>    <RelativeLayout        android:id="@+id/right_container"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_centerVertical="true">        <TextView            android:id="@+id/right_text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            android:text="导航"            android:textColor="@color/green01"            android:textSize="@dimen/text_size_16"/>        <ImageView            android:id="@+id/right_image"            android:layout_width="42dp"            android:layout_height="42dp"            android:padding="10dp"            android:scaleType="fitEnd"/>    </RelativeLayout>    <TextView        android:id="@+id/subtitle_text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:layout_marginRight="@dimen/space_px_20"        android:text="副标题"        android:layout_toLeftOf="@id/right_container"        android:textColor="@color/green01"        android:textSize="@dimen/text_size_16"/>    <View        android:id="@+id/bottom_line"        android:layout_width="match_parent"        android:layout_height="1px"        android:layout_alignParentBottom="true"        android:background="@color/gray_line"/></RelativeLayout>

下面开始准备自定义的属性了 attrs 下
<declare-styleable name="MyActionBar">        <attr name="title_text" format="string" />        <attr name="subtitle_text" format="string" />        <attr name="title_text_size" format="dimension" />        <attr name="title_text_color" format="color" />        <attr name="title_image" format="reference" />        <attr name="title_image_width" format="dimension" />        <attr name="title_image_height" format="dimension" />        <attr name="right_text" format="string" />        <attr name="right_text_size" format="dimension" />        <attr name="right_text_color" format="color" />        <attr name="right_image" format="reference" />        <attr name="right_image_width" format="dimension" />        <attr name="right_image_height" format="dimension" />        <attr name="left_text" format="string" />        <attr name="left_text_size" format="dimension" />        <attr name="left_text_color" format="color" />        <attr name="left_image" format="reference" />        <attr name="left_image_width" format="dimension" />        <attr name="left_image_height" format="dimension" />        <attr name="line_visible" format="boolean" />        <attr name="child_visible">            <flag name="LT" value="0x01" />            <flag name="LI" value="0x02" />            <flag name="TT" value="0x04" />            <flag name="TI" value="0x08" />            <flag name="RT" value="0x10" />            <flag name="RI" value="0x20" />            <flag name="ST" value="0x40" />            <flag name="NULL" value="0x00" />        </attr>    </declare-styleable>
当然重点就是child_visible 这个枚举属性的定义了


这里给出我们自定义的控件
MyActionBar.class
public class MyActionBar extends RelativeLayout implements View.OnClickListener {    private static final int LEFT_TEXT_VISIBLE = 0x01;    private static final int LEFT_IMAGE_VISIBLE = 0x02;    private static final int TITLE_TEXT_VISIBLE = 0x04;    private static final int TITLE_IMAGE_VISIBLE = 0x08;    private static final int RIGHT_TEXT_VISIBLE = 0x10;    private static final int RIGHT_IMAGE_VISIBLE = 0x20;    private static final int SUBTITLE_TEXT_VISIBLE = 0x40;    private TextView mLeftTextView;    private ImageView mLeftImageView;    private TextView mTitleTextView;    private TextView mSbutitleTextView;    private ImageView mTitleImageView;    private TextView mRightTextView;    private ImageView mRightImageView;    private View mBottomLine;    private Drawable background = null;    private int mChildVisible = 0x06;    private String mTitleText;    private String mSubTitleText;    private int mTitleTextSize = -1;    private int mTitleTextColor = -1;    private int mTitleImage;    private int mTitleImageWidth;    private int mTitleImageHeight;    private String mLeftText;    private int mLeftTextSize;    private int mLeftTextColor;    private Drawable mLeftDrawable;    private int mLeftDrawableWidth;    private int mLeftDrawableHeight;    private boolean isLineVisible = true;    private String mRightText;    private int mRightTextSize;    private ColorStateList mRightTextColor;    private Drawable mRightDrawable;    private int mRightDrawableWidth;    private int mDRightrawableHeight;    private OnActionBarClickListener listener;    public MyActionBar(Context context) {        super(context);        initActionBarView();    }    public MyActionBar(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MyActionBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        if (getBackground() == null) {            setBackgroundColor(getResources().getColor(R.color.gray_title));        }        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyActionBar, defStyle, 0);        for (int i = 0; i < typedArray.getIndexCount(); i++) {            int attr = typedArray.getIndex(i);            switch (attr) {                case R.styleable.MyActionBar_child_visible:                    mChildVisible = typedArray.getInt(attr, mChildVisible);                    break;                case R.styleable.MyActionBar_title_text:                    mTitleText = typedArray.getString(attr);                    break;                case R.styleable.MyActionBar_subtitle_text:                    mSubTitleText = typedArray.getString(attr);                    break;                case R.styleable.MyActionBar_title_text_size:                    mTitleTextSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));                    break;                case R.styleable.MyActionBar_title_text_color:                    mTitleTextColor = typedArray.getColor(attr, Color.BLACK);                    break;                case R.styleable.MyActionBar_title_image:                    break;                case R.styleable.MyActionBar_title_image_width:                    break;                case R.styleable.MyActionBar_title_image_height:                    break;                case R.styleable.MyActionBar_left_text:                    break;                case R.styleable.MyActionBar_left_text_size:                    break;                case R.styleable.MyActionBar_left_text_color:                    break;                case R.styleable.MyActionBar_left_image:                    mLeftDrawable = typedArray.getDrawable(attr);                    break;                case R.styleable.MyActionBar_left_image_width:                    break;                case R.styleable.MyActionBar_left_image_height:                    break;                case R.styleable.MyActionBar_right_text:                    mRightText = typedArray.getString(attr);                    break;                case R.styleable.MyActionBar_right_text_size:                    break;                case R.styleable.MyActionBar_right_text_color:                    mRightTextColor = typedArray.getColorStateList(attr);                    break;                case R.styleable.MyActionBar_right_image:                    mRightDrawable = typedArray.getDrawable(attr);                    break;                case R.styleable.MyActionBar_right_image_width:                    break;                case R.styleable.MyActionBar_right_image_height:                    break;                case R.styleable.MyActionBar_line_visible:                    isLineVisible = typedArray.getBoolean(attr, true);                    break;            }        }        typedArray.recycle();        initActionBarView();        initActionBarData();        initActionBarVisible();    }    private void initActionBarView() {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {            setPadding(getPaddingLeft(), getPaddingTop() + DensityUtils.getStatusBarHeight(getContext()),                    getPaddingRight(), getPaddingBottom());        }        View view = View.inflate(getContext(), R.layout.view_action_bar, null);        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(                RelativeLayout.LayoutParams.MATCH_PARENT, DensityUtils.dip2px(getContext(), 45));        view.setLayoutParams(layoutParams);        mLeftTextView = (TextView) view.findViewById(R.id.left_text);        mLeftTextView.setOnClickListener(this);        mLeftImageView = (ImageView) view.findViewById(R.id.left_image);        mLeftImageView.setOnClickListener(this);        mTitleTextView = (TextView) view.findViewById(R.id.title_text);        mTitleTextView.setOnClickListener(this);        mTitleImageView = (ImageView) view.findViewById(R.id.title_image);        mTitleImageView.setOnClickListener(this);        mSbutitleTextView = (TextView) view.findViewById(R.id.subtitle_text);        mSbutitleTextView.setOnClickListener(this);        mRightTextView = (TextView) view.findViewById(R.id.right_text);        mRightTextView.setOnClickListener(this);        mRightImageView = (ImageView) view.findViewById(R.id.right_image);        mRightImageView.setOnClickListener(this);        mBottomLine = view.findViewById(R.id.bottom_line);        addView(view);    }    private void initActionBarData() {        if (!TextUtils.isEmpty(mTitleText)) {            mTitleTextView.setText(mTitleText);        }        if (!TextUtils.isEmpty(mSubTitleText)) {            mSbutitleTextView.setText(mSubTitleText);        }        if (mTitleTextSize != -1) {            mTitleTextView.setTextSize(DensityUtils.sp2px(getContext(), mTitleTextSize));        }        if (mTitleTextColor != -1) {            mTitleTextView.setTextColor(mTitleTextColor);        }        if (mLeftDrawable != null) {            mLeftImageView.setImageDrawable(mLeftDrawable);        }        if (!TextUtils.isEmpty(mRightText)) {            mRightTextView.setText(mRightText);        }        if (mRightDrawable != null) {            mRightImageView.setImageDrawable(mRightDrawable);        }        mRightTextView.setTextColor(mRightTextColor != null ? mRightTextColor : ColorStateList.valueOf(0xFF32A238));    }    private void initActionBarVisible() {        if ((LEFT_TEXT_VISIBLE & mChildVisible) == 0) {            mLeftTextView.setVisibility(View.GONE);        } else {            mLeftTextView.setVisibility(View.VISIBLE);        }        if ((LEFT_IMAGE_VISIBLE & mChildVisible) == 0) {            mLeftImageView.setVisibility(View.GONE);        } else {            mLeftImageView.setVisibility(View.VISIBLE);        }        if ((TITLE_TEXT_VISIBLE & mChildVisible) == 0) {            mTitleTextView.setVisibility(View.GONE);        } else {            mTitleTextView.setVisibility(View.VISIBLE);        }        if ((TITLE_IMAGE_VISIBLE & mChildVisible) == 0) {            mTitleImageView.setVisibility(View.GONE);        } else {            mTitleImageView.setVisibility(View.VISIBLE);        }        if ((RIGHT_TEXT_VISIBLE & mChildVisible) == 0) {            mRightTextView.setVisibility(View.GONE);        } else {            mRightTextView.setVisibility(View.VISIBLE);        }        if ((RIGHT_IMAGE_VISIBLE & mChildVisible) == 0) {            mRightImageView.setVisibility(View.GONE);        } else {            mRightImageView.setVisibility(View.VISIBLE);        }        if ((SUBTITLE_TEXT_VISIBLE & mChildVisible) == 0) {            mSbutitleTextView.setVisibility(View.GONE);        } else {            mSbutitleTextView.setVisibility(View.VISIBLE);        }        if (isLineVisible) {            mBottomLine.setVisibility(View.VISIBLE);        } else {            mBottomLine.setVisibility(View.GONE);        }    }    @Override    public void onClick(View v) {        if (listener == null) {            return;        }        switch (v.getId()) {            case R.id.left_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_LEFT_TEXT);                break;            case R.id.left_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_LEFT_IMAGE);                break;            case R.id.title_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_TITLE_TEXT);                break;            case R.id.title_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_TITLE_IMAGE);                break;            case R.id.right_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_RIGHT_TEXT);                break;            case R.id.right_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_RIGHT_IMAGE);                break;            case R.id.subtitle_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_SUBTITLE_TEXT);                break;        }    }    public void setTitleText(String text) {        mTitleTextView.setText(text);    }    public TextView getRightTextView() {        return mRightTextView;    }    public void setRightText(String text) {        mRightTextView.setText(text);    }    public void setRightTextColor(int color) {        mRightTextView.setTextColor(color);    }    public void setRightVisibility(int visibility) {        mRightTextView.setVisibility(visibility);    }    public void setRightTextClickable(boolean clickable) {        mRightTextView.setClickable(clickable);    }    public interface OnActionBarClickListener {        int POS_LEFT_TEXT = 0;        int POS_LEFT_IMAGE = 1;        int POS_TITLE_TEXT = 2;        int POS_TITLE_IMAGE = 3;        int POS_RIGHT_TEXT = 4;        int POS_RIGHT_IMAGE = 5;        int POS_SUBTITLE_TEXT = 6;        void onActionBarClick(View view, int postion);    }    public void setOnActionBarClickListener(OnActionBarClickListener listener) {        this.listener = listener;    }}

下面具体解释下
1.首先我们在2个参数的构造方法中初始化我们子控件的显示属性


2. 在 initActionBarView()方法中建立各个子控件的引用
3. 在 initActionBarData()方法中的到子控件显示值
4. 在 initActionBarVisible()方法中的初始化子控件的显示问题。

下面重点来了,我贴一下控件的使用,在仔细讲解
 <com.ruiyi.view.ui.MyActionBar        android:id="@+id/action_bar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:child_visible="LI|TT|RI"        app:right_image="@drawable/icon_help_info"        app:title_text="@string/apply_card_car_step3_title" />

我们对属性child_visible 指定为 LI | TT | RI 采取的是 | 运算
我简单解释一下或运算
   参加运算的两个对象,按二进制位进行“或”运算。
   运算规则:0|0=0;   0|1=1;   1|0=1;    1|1=1;
   即 :参加运算的两个对象只要有一个为1,其值为1。
   例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111   因此,3|5的值得7。

这里我们的定义为
 LI = 0x02 = 0000 0010
 TT = 0x04  0000 0100
 RI = 0x20  0001 0100
LI|TT|RI = 0001 0110 = Ox21
在自定义控件中得到的mChildVisivible = 0x21

在判断显示的时候,我们采取的是& 运算
我简单解释一下与运算
运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1;
即:两位同时为“1”,结果才为“1”,否则为0
例如:3&5  即 0000 0011 & 0000 0101 = 0000 0001   因此,3&5的值得1。

我们的判断规则是
 if ((LEFT_TEXT_VISIBLE & mChildVisible) == 0) {            mLeftTextView.setVisibility(View.GONE);        } else {            mLeftTextView.setVisibility(View.VISIBLE);        }        if ((LEFT_IMAGE_VISIBLE & mChildVisible) == 0) {            mLeftImageView.setVisibility(View.GONE);        } else {            mLeftImageView.setVisibility(View.VISIBLE);        }        if ((TITLE_TEXT_VISIBLE & mChildVisible) == 0) {            mTitleTextView.setVisibility(View.GONE);        } else {            mTitleTextView.setVisibility(View.VISIBLE);        }

当运算结果为0 ,子控件隐藏,反之就显示

这里我简单验证下

left text : 0000 0001 & 0001 0110 = 0000 0000 = 0 不显示
left image : 0000 0010 & 0001 0110 = 0000 0010 = 2 显示
title text : 0000 0100 & 0001 0110 = 0000 0100 = 8 显示
title image: 0000 1000 & 0001 0110 = 0000 0000 = 0 不显示

这就是显示规则的原理了。

最后 我们可以将各个子控件的点击事件抽离处理,运用回调处理
我们创建一个接口,包括View 和标记
  public interface OnActionBarClickListener {        int POS_LEFT_TEXT = 0;        int POS_LEFT_IMAGE = 1;        int POS_TITLE_TEXT = 2;        int POS_TITLE_IMAGE = 3;        int POS_RIGHT_TEXT = 4;        int POS_RIGHT_IMAGE = 5;        int POS_SUBTITLE_TEXT = 6;        void onActionBarClick(View view, int postion);    }
拿到listener
  public void setOnActionBarClickListener(OnActionBarClickListener listener) {        this.listener = listener;    }
给每个子控件设置点击事件,统一处理
     mLeftTextView.setOnClickListener(this);        mLeftImageView = (ImageView) view.findViewById(R.id.left_image);        mLeftImageView.setOnClickListener(this);        mTitleTextView = (TextView) view.findViewById(R.id.title_text);        mTitleTextView.setOnClickListener(this);        mTitleImageView = (ImageView) view.findViewById(R.id.title_image);        mTitleImageView.setOnClickListener(this);        mSbutitleTextView = (TextView) view.findViewById(R.id.subtitle_text);        mSbutitleTextView.setOnClickListener(this);        mRightTextView = (TextView) view.findViewById(R.id.right_text);        mRightTextView.setOnClickListener(this);        mRightImageView = (ImageView) view.findViewById(R.id.right_image);        mRightImageView.setOnClickListener(this);

统一处理回传
@Override    public void onClick(View v) {        if (listener == null) {            return;        }        switch (v.getId()) {            case R.id.left_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_LEFT_TEXT);                break;            case R.id.left_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_LEFT_IMAGE);                break;            case R.id.title_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_TITLE_TEXT);                break;            case R.id.title_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_TITLE_IMAGE);                break;            case R.id.right_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_RIGHT_TEXT);                break;            case R.id.right_image:                listener.onActionBarClick(v, OnActionBarClickListener.POS_RIGHT_IMAGE);                break;            case R.id.subtitle_text:                listener.onActionBarClick(v, OnActionBarClickListener.POS_SUBTITLE_TEXT);                break;        }    }
在收到事件,我们自己处理
  @Override    public void onActionBarClick(View v, int postion) {        super.onActionBarClick(v, postion);        if (postion == POS_RIGHT_TEXT) {          。。。。        }    }

嗯,就这样!






0 0