为自定义View添加属性

为自定义View添加属性

每一个控件在布局或是代码中都有其属性:
<TextView
    android:id="@+id/tv_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textSize="18sp"
    android:maxLines="1"/>

像id,layout_width,gravity…这是Android已经定义好的控件属性,在java代码中还有setText()方法等,为空间的使用提供了很多便捷。

自定义属性的步骤:

1.在attrs.xml文件中声明属性,有属性名:name和格式:format.
<!--自定义ToggleButton,声明属性集的名称-->
<declare-styleable name="MyToggleButton">
    <!--声明一个属性 name format-->
    <attr name="my_background" format="reference"/>
    <attr name="my_slide_btn" format="reference"/>
    <attr name="curr_state" format="boolean"/>
</declare-styleable>
format常用类型:
  • reference 引用
  • color 颜色
  • boolean 布尔值
  • dimension 尺寸值
  • float 浮点值
  • integer 整型值
  • string 字符串
  • enum 布尔值
2.在布局文件中使用新属性,使用之前必须声明命名空间,如:
xmlns:myview="http://schemas.android.com/apk/res/com.example.myview"

<com.jeff.customview.view.MyToggleButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    myview:curr_state="false"
    myview:my_background="@mipmap/switch_background"
    myview:my_slide_btn="@mipmap/slide_button"/>
3.在自定义view的构造方法中,通过AttributeSet对象,获得所需要的属性值
/**
 * 自定义ToggleButton
 *
 * view对象显示在屏幕上的步骤
 * 1.构造方法创建对象
 * 2.测量view大小 onMeasure()
 * 3.确定view的位置,view自身有一些建议权,决定权在父view手中, onlayout()
 * 4.绘制view的内容,onDraw(Canvas)
 */

public class MyToggleButton extends View implements View.OnClickListener {
    private static final String TAG = "MyToggleButton";

    private Bitmap bgBitmap;//背景图片
    private Bitmap slideBtn;//滑动按钮
    private Paint paint;//画笔
    private float slideBtn_left = 0;//slideBtn左边界

    private int backgroundId;//背景图片的资源ID
    private int slideBtnId;//滑动按钮的资源ID
    private boolean currentState = false;//按钮状态

    /**
     * 在代码中创建对象时调用
     *
     * @param context
     */
    public MyToggleButton(Context context) {
        super(context);
    }

    /**
     * 在布局文件声明的view,创建时由系统自动调用
     *
     * @param context
     * @param attrs
     */
    public MyToggleButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        //无命名空间测试(未添加到attrs)
        //获取的属性值为字符串
        String testAttr=attrs.getAttributeValue(null,"testAttr");
        Log.d(TAG, "MyToggleButton: testAttr= "+testAttr);

        //获取自定义属性
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleButton);
        int count = ta.getIndexCount();
        for (int i = 0; i < count; i++) {
            //获取某个属性的ID
            int itemId = ta.getIndex(i);
            switch (itemId) {
                case R.styleable.MyToggleButton_my_background:
                    backgroundId = ta.getResourceId(itemId, -1);
                    Log.d(TAG, "MyToggleButton: backgroundId= "+backgroundId);
                    if (backgroundId==-1){
                        throw new RuntimeException("please set the imgRec of background");
                    }
                    bgBitmap= BitmapFactory.decodeResource(getResources(), backgroundId);
                    break;
                case R.styleable.MyToggleButton_my_slide_btn:
                    slideBtnId = ta.getResourceId(itemId, -1);
                    if (slideBtnId==-1){
                        throw new RuntimeException("please set the imgRec of slideBtn");
                    }
                    slideBtn= BitmapFactory.decodeResource(getResources(), slideBtnId);
                    break;
                case R.styleable.MyToggleButton_curr_state:
                    currentState = ta.getBoolean(itemId, false);
                    break;
            }
        }

        initView();
    }

    private void initView() {
        //初始化图片
//        bgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_background);
//        slideBtn = BitmapFactory.decodeResource(getResources(), R.mipmap.slide_button);

        //初始化画笔
        paint = new Paint();
        paint.setAntiAlias(true);//抗锯齿

        //添加点击事件监听
        setOnClickListener(this);

        flushState();
    }

    /**
     * 测量view大小时调用
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //设置当前view大小
        setMeasuredDimension(bgBitmap.getWidth(), bgBitmap.getHeight());
    }

    /**
     * 确定位置时调用
     * 自定义view时作用不大
     *
     * @param changed
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    /**
     * 绘制view时调用
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        //绘制背景
        canvas.drawBitmap(bgBitmap, 0, 0, paint);
        //绘制可滑动按钮
        canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);
    }

    @Override
    public void onClick(View v) {
        flushState();
        currentState = !currentState;
    }

    /**
     * 刷新当前状态
     */
    private void flushState() {
        if (currentState) {
            slideBtn_left = bgBitmap.getWidth() - slideBtn.getWidth();
        } else {
            slideBtn_left = 0;
        }

        //刷新当前view,会重调onDraw方法
        invalidate();
    }
}
效果展示:

项目用到的图片:

效果图:

效果图

查看布局中控件的属性
//构造方法
public CustomAttrs(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    int count=attrs.getAttributeCount();
    for (int i = 0; i < count; i++) {
        String name=attrs.getAttributeName(i);
        String value=attrs.getAttributeValue(i);
        Log.d(TAG, "CustomAttrs:  name= "+name+"  value= "+value);
    }
}

//log
CustomAttrs:  name= layout_width  value= -2
CustomAttrs:  name= layout_height  value= -2
CustomAttrs:  name= test_msg  value= @2131099681
CustomAttrs:  name= test_bitmap  value= @2130903052
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值