【笔记】第三章Android控件架构与自定义控件详解(2)

本文深入探讨了Android控件架构,重点讲解如何创建复合控件,即自定义ViewGroup子类。介绍了自定义属性的步骤,包括在values下创建attrs资源文件,声明自定义变量,避免重名,自定义类并利用TypedArray获取属性值,以及在布局文件中引用和设置属性。同时,文章还讨论了如何实现button和textview的位置信息,并将它们添加到GroupView中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

详见《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>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值