• Android中如何为自定义控件增加状态?


      

    在android开发中我们常常需要对控件进行相关操作,虽然网上已有很多对控件酷炫的操作,但小编今天给大家分享的纯属实用出发。在查看了一些列安卓教程和文档后,发现了一位大牛分享的非常不错的有关android自定义控件增加状态的文章,分享给大家,学习、参考。

     

     

    场景

     

    View类是Android UI组件的基础构建模块,主要负责组件的绘制及事件的处理。我们在一些自定义控件的场合,可能需要在一个组件上画些东西,也是通过重写View的onDraw方法,通过其参数的Canvas对象进行绘制。

     

    我们学习<selector/>的时候,就知道了关于一个视图组件会有许多种状态,比如按下(pressed),选择(selected),可用(enabled),正常状态,其他状态等等。View也处理了关于一个组件在不同状态下的显示的绘制逻辑,通常继承自View的组件都有着以上所说的这些状态。但是也有一些状态是View没有提供的,而我们可能正需要它们,所以就需要对状态进行扩展,增加我们的状态,比如增加checked。

     

    这里有一个具体的场景:

     

    这是一个开关按钮,开关状态下背景不同,文字不同,文字旁边的图片也不同。状态我用checked,文字我定义了两个属性:onText以及offText,文字旁边的图片我打算只用一个foreground属性,但需要写一个selector来定义正常状态(未锁)和checked状态(锁定)下的图片。

     

     

    实现

     

    首先写一个类继承自TextView,因为我打算用TextView的setCompoundDrawables来设定文字旁边的图片。

     

    然后定义属性:

     

        <declare-styleable name="ToggleView">

            <attr name="android:foreground"/>

            <attr name="pwOnText"/>

            <attr name="pwOffText"/>

            <attr name="pwColor"/>

            <attr name="pwDrawableHeight"/>

        </declare-styleable>

     

    读取属性:

     

            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ToggleView);

            stateListDrawable = (StateListDrawable) a.getDrawable(R.styleable.ToggleView_android_foreground);

            colorStateList = a.getColorStateList(R.styleable.ToggleView_pwColor);

            offText = a.getString(R.styleable.ToggleView_pwOffText);

            onText = a.getString(R.styleable.ToggleView_pwOnText);

            drawableHeight = a.getDimensionPixelSize(R.styleable.ToggleView_pwDrawableHeight, 0);

            a.recycle();

     

     

    通过在类中实现Checkable接口,可以完成选中的逻辑,但是画出来的状态却没有更新,所以接下来的实现过程就是本篇的主要内容:

     

    首先定义状态集:

     

        private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};

     

    然后我们要把状态给加进去。我们需要重写protected int[] onCreateDrawableState(int extraSpace)方法,如下:

     

        @Override

        protected int[] onCreateDrawableState(int extraSpace) {

            final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);

            if (isChecked) {

                mergeDrawableStates(drawableState, CHECKED_STATE_SET);

            }

            return drawableState;

        }

     

    先调用父类的onCreateDrawableState方法得到状态数组对象drawableState,但是参数extraSpace要加上1,因为我们要往里面增加一个状态。然后判断在代码逻辑中,是否为选中状态,如果是的话,调用mergeDrawableStates(drawableState, CHECKED_STATE_SET)方法把我们的状态值给加进去,最终返回drawableState。

     

    但是我们虽然实现了Checkable接口,在设置状态时却没有触发到这个状态。所以我们需要自己去触发这个状态。

     

        @Override

        public void setChecked(boolean checked) {

            if (isChecked != checked) {

                isChecked = checked;

                refreshDrawableState();

            }

        }

     

    在状态改变时,调用refreshDrawableState()刷新状态。

     

    最后,我们要重写drawableStateChanged()方法,获取到当前状态的drawable,然后绘制出来。

     

        @Override

        protected void drawableStateChanged() {

            super.drawableStateChanged();

            if (stateListDrawable != null) {

                int[] myDrawableState = getDrawableState();

                stateListDrawable.setState(myDrawableState);

                Drawable drawable = stateListDrawable.getCurrent();

                if(drawableHeight != 0) {

                    drawable.setBounds(0, 0, drawable.getIntrinsicWidth() * drawableHeight / drawable.getIntrinsicHeight(), drawableHeight);

                } else {

                    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

                }

                if (isChecked) {

                    setCompoundDrawables(drawable, null, null, null);

                } else {

                    setCompoundDrawables(null, null, drawable, null);

                }

            }

            setText(isChecked ? onText : offText);

        }

     

    这部分代码中我需要设定drawable的大小,以及在不同的状态下设置drawable的位置,因此稍微比较复杂一点点,实际上逻辑只需要如下:

     

    获取当前的drawableState状态

    对stateListDrawable(带状态的drawable集)设置状态。

    获取stateListDrawable的当前状态的drawable

    进行你所想要的绘制。

    这样就完成了。

     

    总结

     

    从上面可知,增加状态的过程如下:

     

    定义状态数组

    重写protected int[] onCreateDrawableState(int extraSpace)

    调用refreshDrawableState()

    重写protected void drawableStateChanged()

     

    以上就是android自定义控件增加状态的方法,如果你还有更好的实现方法,欢迎补充分享。

    相关文章:《如何实现自己的Android MVP框架?

  • 相关阅读:
    PR工具栏(选择、轨道选择、剃刀工具)
    PPT动画与多媒体制作
    小微企业增值税申报操作流程
    标题样式
    样式排版
    文本框排版
    使用SmartArt
    插图片与调整
    表格的运用
    Word标尺与段落
  • 原文地址:https://www.cnblogs.com/gaobig/p/5013174.html
Copyright © 2020-2023  润新知