开发中有些包含数个控件集合的布局可能会经常重复使用,可能有时候直接写个layout布局,然后在需要时通过include将其添加进来使用,但是会发现所有有添加这个layout的地方我们都需要对其中的控件做绑定findViewById,而且定义之后的控件做相同的操作。因此最好的方法就是将这些具有相同功能效果的控件集合包装起来,自定义做个复合控件。
自定义复合控件方式可以直接将不同的控件添加到layout布局然后使用LayoutInflater绑定,也可在代码中组合控件。此处仅仅是三个控件的组合,所以采用后者。下面以一个常见的标题栏做个简单的例子。
此处定义一个TitleBar的标题栏,功能相对简单,仅仅是左右两个Button和中间的一个TextView。效果如下:
这里我按钮中使用文字,Button有默认的padding会显得太大,为图个方便我就都采用TextView了,因为Button继承自TextView,所以没多大关系。
由这里看出我们需要的属性有左右两边按钮的文字、文字颜色及背景,中间标题的文字、文字颜色、文字大小。当然左右文字也可以设置文字大小,可以根据需要添加,方法和中间的标题文字一样。
确定下需要设置的属性后就可以在values目录下创建一个attrs.xml的属性定义的文件。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TitleBar">
<attr name="title" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="leftText" format="string"/>
<attr name="rightText" format="string"/>
<attr name="titleTextColor" format="color"/>
<attr name="leftTextColor" format="color"/>
<attr name="rightTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="rightBackground" format="reference|color"/>
<attr name="titlebarBackground" format="color"/>
</declare-styleable>
</resources>
代码中通过declare-styleable标签声明自定义属性,该标签中name是用来引用这些属性名称。attr标签定义具体的属性其中的name和format分别是属性名称和它的类型,如果类型具有多种则用“|”隔开。取值时将这些属性的值存入TypedArray中,通过get各属性获取其对应的值。 如获取标题文字的字体大小,其查找的名字格式为{declare-styleable标签中的name}_{attr标签中的name},两个名称中间用下划线“_”连接,后面参数为默认值。注意:在取完值后加上recycle()方法以避免重新创建时发生错误。
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TitleBar);
titleTextSize = ta.getFloat(R.styleable.TitleBar_titleTextSize,15);
ta.recycle();
复合控件通常继承自ViewGroup,但可根据布局方式复杂程度做不同的选择,如此控件可以通过继承RelativeLayout实现。接下来开始获取attrs中的值
public class TitleBar extends RelativeLayout {
// 取出attrs中styleable的值
// 文字
private String titleText,leftText,rightText;
// titilebar背景颜色和三个控件文字颜色
private int titlebarBackgroundColor,titleTextColor,leftTextColor,rightTextColor;
// 左右两个TextView的背景资源
private int leftBackground,rightBackground;
// 标题的文字字体大小
private float titleTextSize;
public TitleBar(Context context, AttributeSet attrs) {
super(context, attrs);
initVariable(context,attrs);
}
/**
初始化变量
*/
private void initVariable(Context context,AttributeSet attrs) {
// 将attrs中的值存储到TypedArray中
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TitleBar);
titleText = ta.getString(R.styleable.TitleBar_title);
leftText = ta.getString(R.styleable.TitleBar_leftText);
rightText = ta.getString(R.styleable.TitleBar_rightText);
titlebarBackgroundColor = ta.getColor(R.styleable.TitleBar_titlebarBackground, 0);
titleTextColor = ta.getColor(R.styleable.TitleBar_titleTextColor,
ContextCompat.getColor(context,R.color.titleTextColor));
leftTextColor = ta.getColor(R.styleable.TitleBar_leftTextColor,
ContextCompat.getColor(context,R.color.leftTextColor));
rightTextColor = ta.getColor(R.styleable.TitleBar_rightTextColor,
ContextCompat.getColor(context,R.color.rightTextColor));
leftBackground = ta.getResourceId(R.styleable.TitleBar_leftBackground,
R.drawable.titlebar_left_btn_bg);
rightBackground = ta.getResourceId(R.styleable.TitleBar_rightBackground,
R.drawable.titlebar_right_btn_bg);
titleTextSize = ta.getFloat(R.styleable.TitleBar_titleTextSize,15);
// 注意!此处获取完属性值后要添加recycle()方法,避免重新创建时发生错误
ta.recycle();
}
}
此处我添加了文字的默认颜色及按钮的背景图片,三个文字的颜色的色值都一样ÿ