详见《Android群英传》
3.6.2创建复合控件(本质是在讲如何自定义属性)
复合控件实质上是一个ViewGroup,通过自定义ViewGroup的子类来实现
其中关于自定义属性:
先在values下创建attrs资源文件,然后在styleable中声明自定义变量,变量名不应该与已有的重名
自定义类,并通过TypedArray类来获取自定义的属性值,赋给控件
在布局文件中指定命名空间,然后引入自定义控件,在其中通过命名空间来指定属性
此过程的本质是重写了传入属性的构造函数
代码如下
//在此构造函数中声明属性
public MyTopBar(Context context, AttributeSet attrs) {
//super中会将原生的属性从布局中获取,然后进行赋值
super(context, attrs);
setBackgroundColor(0xFFF59563);//设置topbar的属性
/*有个问题不太明白,如何将布局中赋的值映射到attrs.xml上自定义的属性上的*/
//将attrs中的自定义属性由布局中存储到TypedArray对象中,然后从该对象中获取值
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyTopBar);//获取attrs.xml中的MyTopBar的自定义属性
mLeftTextColor=ta.getColor(R.styleable.MyTopBar_leftTextColor, 0);//第二个参数为缺省值
mLeftBackground=ta.getDrawable(R.styleable.MyTopBar_leftBackground);
mLeftText=ta.getString(R.styleable.MyTopBar_leftText);
mRightTextColor=ta.getColor(R.styleable.MyTopBar_rightTextColor, 0);
mRightBackground=ta.getDrawable(R.styleable.MyTopBar_rightBackground);
mRightText=ta.getString(R.styleable.MyTopBar_rightText);
mTitleTextColor=ta.getColor(R.styleable.MyTopBar_mtitleTextColor, 0);
mTitleTextSize=ta.getDimension(R.styleable.MyTopBar_mtitleTextSize, 10);
mTitle=ta.getString(R.styleable.MyTopBar_mtitle);
ta.recycle();//获取完TypedArray的值后,要调用recycle方法,回收
mLeftButton=new Button(context);
mRightButton=new Button(context);
mTitleView=new TextView(context);
//将获取到的值赋给相应的组件元素
mLeftButton.setTextColor(mLeftTextColor);
mLeftButton.setBackground(mLeftBackground);
mLeftButton.setText(mLeftText);
mRightButton.setTextColor(mRightTextColor);
mRightButton.setBackground(mRightBackground);
mRightButton.setText(mRightText);
mTitleView.setText(mTitle);
mTitleView.setTextColor(mTitleTextColor);
mTitleView.setTextSize(mTitleTextSize);
mTitleView.setGravity(Gravity.CENTER);
组合控件是由两个button和一个textview组成的,上面的过程对于已有的属性,是已经封装过的了。
接着是对button,textview的位置信息实现,并将其添加打GroupView中
//为组件元素设置相应的布局元素
/*ViewGroup.LayoutParams和LayoutParams的区别是,后者是前者的子类*/
mLeftParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mLeftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);//设置在相对布局左边
addView(mLeftButton, mLeftParams);//将Button以mLeftParams的方式添加到RelativeLayout中
mRightParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mRightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);//设置在相对布局右边
addView(mRightButton, mRightParams);
mTitleParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mTitleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(mTitleView, mTitleParams);
1.在attrs.xml声明属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTopBar">
<attr name="mtitle" format="string"/>
<attr name="mtitleTextSize" format="dimension"/>
<attr name="mtitleTextColor" format="color"/>
<attr name="leftTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="leftText" format="string"/>
<attr name="rightTextColor" format="color"/>
<attr name="rightBackground" format="reference|color"/>
<attr name="rightText" format="string"/>
</declare-styleable>
</resources>
2.自定义GroupView类,RelativeLayout类继承GroupView
public class MyTopBar extends RelativeLayout {
private Button mLeftButton,mRightButton;//topbar的左按钮和右按钮
private TextView mTitleView;//topbar的标题
private LayoutParams mLeftParams,mTitleParams,mRightParams;//布局属性
//在attrs.xml中的各属性定义
private int mLeftTextColor;
private Drawable mLeftBackground;//背景图片
private String mLeftText;
private int mRightTextColor;
private Drawable mRightBackground;
private String mRightText;
private float mTitleTextSize;
private int mTitleTextColor;
private String mTitle;
public MyTopBar(Context context) {
super(context);
}
//在此构造函数中声明属性
public MyTopBar(Context context, AttributeSet attrs) {
//super中会将原生的属性从布局中获取,然后进行赋值
super(context, attrs);
setBackgroundColor(0xFFF59563);//设置topbar的属性
/*有个问题不太明白,如何将布局中赋的值映射到attrs.xml上自定义的属性上的*/
//将attrs中的自定义属性由布局中存储到TypedArray对象中,然后从该对象中获取值
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyTopBar);//获取attrs.xml中的MyTopBar的自定义属性
mLeftTextColor=ta.getColor(R.styleable.MyTopBar_leftTextColor, 0);//第二个参数为缺省值
mLeftBackground=ta.getDrawable(R.styleable.MyTopBar_leftBackground);
mLeftText=ta.getString(R.styleable.MyTopBar_leftText);
mRightTextColor=ta.getColor(R.styleable.MyTopBar_rightTextColor, 0);
mRightBackground=ta.getDrawable(R.styleable.MyTopBar_rightBackground);
mRightText=ta.getString(R.styleable.MyTopBar_rightText);
mTitleTextColor=ta.getColor(R.styleable.MyTopBar_mtitleTextColor, 0);
mTitleTextSize=ta.getDimension(R.styleable.MyTopBar_mtitleTextSize, 10);
mTitle=ta.getString(R.styleable.MyTopBar_mtitle);
ta.recycle();//获取完TypedArray的值后,要调用recycle方法,回收
mLeftButton=new Button(context);
mRightButton=new Button(context);
mTitleView=new TextView(context);
//将获取到的值赋给相应的组件元素
mLeftButton.setTextColor(mLeftTextColor);
mLeftButton.setBackground(mLeftBackground);
mLeftButton.setText(mLeftText);
mRightButton.setTextColor(mRightTextColor);
mRightButton.setBackground(mRightBackground);
mRightButton.setText(mRightText);
mTitleView.setText(mTitle);
mTitleView.setTextColor(mTitleTextColor);
mTitleView.setTextSize(mTitleTextSize);
mTitleView.setGravity(Gravity.CENTER);
//为组件元素设置相应的布局元素
/*ViewGroup.LayoutParams和LayoutParams的区别是,后者是前者的子类*/
mLeftParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mLeftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);//设置在相对布局左边
addView(mLeftButton, mLeftParams);//将Button以mLeftParams的方式添加到RelativeLayout中
mRightParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mRightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);//设置在相对布局右边
addView(mRightButton, mRightParams);
mTitleParams=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mTitleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(mTitleView, mTitleParams);
mRightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//此处调用一个接口函数,调用者自己实现其方法
}
});
mLeftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//同上
}
});
}
}
3.布局中添加控件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:topbar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.test301.MainActivity">
<com.example.administrator.test301.MyTopBar
android:layout_below="@+id/mytextview"
android:layout_width="match_parent"
android:layout_height="60dp"
topbar:leftBackground="#903234"
topbar:leftText="Back"
topbar:leftTextColor="#FFFFFF"
topbar:rightBackground="#903234"
topbar:rightText="MORE"
topbar:rightTextColor="#FFFFFF"
topbar:mtitle="自定义amazing"
topbar:mtitleTextColor="#f40fff"
topbar:mtitleTextSize="10sp"/>
</RelativeLayout>