你的位置:首页 > 操作系统

[操作系统]Android自定义标题TitleView


  Android开发过程中,经常遇到一个项目需要重复的定义相同样式的标题栏,Android相继推出了actionBar, toolBar, 相信有用到的朋友也会遇到一些不如意的时候,比如标题栏居中时,需要自定义

  为了提前看到效果,先上效果图:

前期准备 

1.为标题栏titleView预定义id,在values下的ids.

 1 <??> 2 <resources> 3  4   <item name="tv_title_name" type="id"/> 5   <item name="tv_left_text" type="id"/> 6   <item name="iv_left_image" type="id"/> 7   <item name="iv_right_image" type="id"/> 8   <item name="iv_right_image_two" type="id"/> 9   <item name="tv_right_text" type="id"/>10   <item name="tv_right_text_two" type="id"/>11 12 </resources>

这里可以看到定义了左侧返回按钮id,标题id,后侧按钮id,左侧分两种情况:ImageView/TextView,右侧可以同时存在两个按钮,图片按钮、文字按钮组合。

2.自定义标题栏属性,在valuse下的attr.

 1 <??> 2 <resources> 3   <!-- 标题属性 --> 4   <declare-styleable name="TitleAttr"> 5     <attr name="title_name" format="reference|string"/> 6     <attr name="title_text_color" format="reference|color"/> 7     <attr name="title_drawable_right" format="reference"/> 8     <attr name="title_drawable_left" format="reference"/> 9     <attr name="title_text_size" format="reference|dimension"/>10     <attr name="left_text" format="reference|string"/>11     <attr name="left_image" format="reference"/>12     <attr name="small_text_size" format="reference|dimension"/>13     <attr name="title_gravity">14       <enum name="left" value="3"/>15       <enum name="center" value="17"/>16       <enum name="right" value="5"/>17     </attr>18     <attr name="right_image" format="reference"/>19     <attr name="right_text" format="reference|string"/>20     <attr name="right_image_two" format="reference"/>21     <attr name="right_text_two" format="reference|string"/>22     <attr name="title_height" format="dimension"/>23     <attr name="right_text_drawable_right" format="reference"/>24     <attr name="right_text_drawable_left" format="reference"/>25     <attr name="right_text_two_drawable_right" format="reference"/>26     <attr name="right_text_two_drawable_left" format="reference"/>27     <attr name="left_text_drawable_right" format="reference"/>28     <attr name="left_text_drawable_left" format="reference"/>29   </declare-styleable>30 </resources>

  • 编码实现
  •    有了前面的准备后,现在就可以开始编码实现了,这里先看看在 1 <com.jarek.library.TitleView 2 android:id="@+id/title_main" 3 android:layout_width="match_parent" 4 android:background="#0093fe" 5 title:title_name="标题" 6 title:right_text="@string/more" 7 title:title_text_color="@android:color/white" 8 title:right_image_two="@mipmap/icon_crop_rotate" 9 title:title_text_size="20sp"10 title:small_text_size="15sp"11 title:left_text="返回"12 title:left_text_drawable_left="@mipmap/back_normal"13 title:right_text_drawable_right="@mipmap/bar_button_right"14 android:layout_height="50dp"/>

    这里的title标签就是我们自定义,首先创建一个类继承自RelativeLayout,这里选择RelativeLayout作为父类容器,目的在于RelativeLayout便于控制相对位置。 
    首先我们要获得TypedArray对象,所有自定义属性的值通过它来获取:

    TypedArray typeArray = context.obtainStyledAttributes(attrs,   R.styleable.TitleAttr);

    得到了typedArray对象后,就可以开始添加按钮到容器中了,首先看看左边第一个返回按钮如果添加上去,先看代码:

     int leftText = typeArray.getResourceId(R.styleable.TitleAttr_left_text, 0); CharSequence charSequence = leftText > 0 ? typeArray.getResources().getText(leftText) : typeArray.getString(R.styleable.TitleAttr_left_text);

    这里left_text就是自定义属性,表明是左侧TextView显示的文字,文字可以是应用资源文件里的预定义string,也可以是直接输入文字,取到对应的styleable后,首先判断是否大于0,大于0表示是定义在string中的,通过typeArray.getResources().getText()获取值,等于0就直接取值,表示可能是通过直接赋值的方式给值的。取到值后怎么赋值给TextView,这里需要首先给他宽高,这是所有控件都需要的

    /** * layout params of RelativeLayout * @return LayoutParams */private LayoutParams initLayoutParams () {    return new LayoutParams(LayoutParams.WRAP_CONTENT,  LayoutParams.MATCH_PARENT);  }

    我们单独写一个方法,后续就可以直接通过

    LayoutParams params = initLayoutParams();

    来获取预设宽高值了,这里可以看到都是高度填充父控件,宽度是自适应。然后就是new一个TextView了:

    /**   * create TextView   * @param context Context   * @param id the id of TextView   * @param charSequence text to show   * @param params relative params   * @return the TextView which is inited   */  @NonNull  private TextView createTextView(Context context, int id, CharSequence charSequence, LayoutParams params) {    TextView textView = new TextView(context);    textView.setLayoutParams(params);    textView.setGravity(Gravity.CENTER);    textView.setId(id);    textView.setMinWidth((int)getPixelSizeByDp(minViewWidth));    textView.setText(charSequence);    return textView;  }

    这里可以看到我们传入了预设的id值,需要显示的内容,以及上面给定的LayoutParams 。创建好TextView后还可以设置TextView的Drawable,通过自定义属性left_text_drawable_right,left_text_drawable_left设置,这里是设置了左右,上下对应的可以设置:

      /**   * drawable of TextView   * @param typeArray TypedArray   * @param leftDrawableStyleable leftDrawableStyleable   * @param rightDrawableStyleable rightDrawableStyleable   * @param textView which TextView to set   */  private void setTextViewDrawable(TypedArray typeArray, int leftDrawableStyleable, int rightDrawableStyleable, TextView textView) {    int leftDrawable = typeArray.getResourceId(leftDrawableStyleable, 0);    int rightDrawable = typeArray.getResourceId(rightDrawableStyleable, 0);    textView.setCompoundDrawablePadding((int)getPixelSizeByDp(drawablePadding));    textView.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, 0, rightDrawable, 0);  }

    这里也是抽取了一个方法出来,然后通过:

    setTextViewDrawable(typeArray, R.styleable.TitleAttr_left_text_drawable_left, R.styleable.TitleAttr_left_text_drawable_right, mLeftBackTextTv);

    即可给指定的TextView设置drawable了。创建好TextView后,前面提到我们用的是相对布局,需要指定位置规则:

    params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);

    这里居左显示。同时还可以设置字体大小,通过自定义属性:small_text_size(两侧文字大小),title_text_size(标题文字大小)来设置字体:

      /**   * get the dimension pixel size from typeArray which is defined in attr   * @param typeArray TypedArray   * @param stylable stylable   * @param defaultSize defaultSize   * @return the dimension pixel size   */  private float getDimensionPixelSize(TypedArray typeArray, int stylable, int defaultSize) {    int sizeStyleable = typeArray.getResourceId(stylable, 0);    return sizeStyleable > 0 ? typeArray.getResources().getDimensionPixelSize(sizeStyleable) : typeArray.getDimensionPixelSize(stylable, (int)getPiselSizeBySp(defaultSize));  }

    一样,这里也是单独写一个方法来做,TypedArray的用法就不多讲了,可以查看其它文章了解。然后通过如下设置字体大小:

       float textSize = getDimensionPixelSize(typeArray, R.styleable.TitleAttr_small_text_size, defaultSmallTextSize);    mLeftBackTextTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);

    文字颜色,同样的道理:

      /**   * get textColor   * @param typeArray TypedArray   * @return textColor   */  private int getTextColorFromAttr (TypedArray typeArray) {    int textColorStyleable = typeArray.getResourceId(R.styleable.TitleAttr_title_text_color, 0);    if (textColorStyleable > 0) {      return typeArray.getResources().getColor(textColorStyleable);    } else {      return typeArray.getColor(R.styleable.TitleAttr_title_text_color, textColor);    }  }

    然后调用方法设置颜色:

    mLeftBackTextTv.setTextColor(getTextColorFromAttr(typeArray));

    到这里为止,左侧的第一个文字按钮。或者文字带图片的按钮就创建好了,最后就差一步了:

    mLeftBackTextTv.setTextColor(getTextColorFromAttr(typeArray));

    其它按钮,同样的道理,可以依次添加到容器中,就不多讲了,到此为止我们需要的titleView就创建好了,以后使用就可以直接调用了,不需要每个地方去重复的coding

项目地址:github源码下载