由于项目中经常用到此种组合控件,就封装了下,具体效果看下图,老司机可以绕道哈!
Image.png
一、主要功能
- 支持左右图标动态设置
- 支持左右、中间文字动态修改
- 支持字体大小、颜色修改
- 支持左右图标,左中右文字隐藏显示
- 支持左右图标和文案的点击监听
二、基本使用方式
三、基本属性介绍
属性名 | 属性说明 | 属性值 |
---|---|---|
titleBarBackground | 标题栏背景色 | color,reference,默认为white |
leftImage | 左边图片 | reference |
leftImageVisiable | 左边图片是否可见 | boolean,默认为true,显示控件 |
leftText | 左边文案 | string,reference |
leftTextVisibale | 左边文案是否可见 | boolean,默认为true,显示控件 |
leftTextFontSize | 左边文案字体大小 | dimension,reference,默认为16sp |
leftTextColor | 左边文案字体颜色 | color,reference |
midText | 中间文案 | string,reference |
midTextVisiable | 中间文案是否可见 | boolean,默认为true,显示控件 |
midTextFontSize | 中间文案字体大小 | dimension,reference,默认为18sp |
midTextFontColor | 中间文案字体颜色 | color,reference |
rightText | 右边文案 | color,reference |
rightTextVisible | 右边文案是否可见 | boolean,默认为true,显示控件 |
rightTextFontSize | 右边文案字体大小 | dimension,reference,默认为16sp |
rightTextColor | 右边文案字体颜色 | color,reference |
rightImage | 右边图片 | reference |
rightImageVisible | 右边图片是否可见 | boolean,默认为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);
}
/**
* 有兴趣的请参考鸿洋大神的自定义讲解
*
* 初始化属性值:这种写法,不管你在布局中有没有使用该属性,都会执行getXXX方法赋值
*假设一个场景:
* private int attr_mode = 1;//默认为1
* //然后你在写getXXX方法的时候,是这么写的:
* attr_mode = array.getInt(i, 0);
*
* 可能你的自定义属性有个默认的值,然后你在写赋值的时候,一看是整形,就默默的第二个参数就给了个0,
* 然而用户根本没有在布局文件里面设置这个属性,你却在运行时将其变为了0(而不是默认值),而第二种就不存在这个问题。
* 当然这个场景可以由规范的书写代码的方式来避免,(把默认值提取出来,都设置对就好了)。
*
* 场景二:
*
* 其实还有个场景,假设你是继承自某个View,父类的View已经对该成员变量进行赋值了,然后你这边需要根据用户的设置情况,
* 去更新这个值,第一种写法,如果用户根本没有设置,你可能就将父类的赋值给覆盖了。
*
* @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
* 初始化属性值:这种写法,只有在布局中设置了该属性值后,才会调用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
五、attrs.xml
六、组合控件布局(custom_title_bar.xml)
为什么使用merge,因为组合控件已经extends RelativeLayout,如果根布局还是用viewGroup的话,会使布局重复嵌套,影响View的绘制性能;
七、具体使用
CustomNavigatorBar customNavigatorBar = (CustomNavigatorBar) findViewById(R.id.customView);
/**
* 第一种监听的具体实现
*/
customNavigatorBar.setLeftImageOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"left",Toast.LENGTH_SHORT).show();
}
});
/**
* 第二种监听的具体实现
*/
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 ;
}
}
});