zoukankan      html  css  js  c++  java
  • 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框架?

  • 相关阅读:
    Java Output流写入包装问题
    SpringBoot项目单元测试不经过过滤器问题
    SpringSecurity集成启动报 In the composition of all global method configuration, no annotation support was actually activated 异常
    JWT jti和kid属性的说明
    Maven 排除依赖
    第五章 基因概念的发现
    第三章 孟德尔遗传的拓展
    第二章 孟德尔遗传
    第一章 引言
    GWAS全基因组关联分析
  • 原文地址:https://www.cnblogs.com/gaobig/p/5013174.html
Copyright © 2011-2022 走看看