详见《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类继承GroupViewpublic 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>
新闻热点
疑难解答