Android 代码动态设置TextView的背景、颜色Selector

在Android里面,实现TextView等根据不同状态显示不同的背景和颜色是很简单滴,只需要设置对应的selector就好了!
背景选择器(res/drawable):

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:drawable/ic_delete" android:state_checked="true"/>
    <item android:drawable="@android:drawable/ic_input_add"/>
</selector>

颜色选择器(res/color):

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="#ff0000" />
    <item android:state_focused="true" android:color="#ff0000" />
    <item android:state_pressed="true" android:color="#ff0000" />
    <item android:color="#89683B" />
</selector>

那么我们需要动态设置这些东西怎么写呢?这里就有两个类了:StateListDrawable,ColorStateList看这个名字就知道这两个类是来干嘛的了!

首先说下StateListDrawable
创建对应的StateListDrawable,通过addState (int[] stateSet, Drawable drawable)的方法添加我们指定的一些状态,可以看到第一个参数是一个数组,后面就是对应的Drawable。那么问题来了,一个状态的true或者false是怎么指定的呢?答案就是下面这个样子滴:

    StateListDrawable states = new StateListDrawable();
    states.addState(new int[]{-android.R.attr.state_checked}, getDrawable(android.R.drawable.ic_media_play));
    states.addState(new int[]{android.R.attr.state_checked}, getDrawable(android.R.drawable.ic_delete));
    return states;

前面有一个负号就是false的状态!

然后就是ColorStateList了,它的构造方法public ColorStateList(int[][] states, @ColorInt int[] colors),看着是不是有点儿腻害,颜色状态居然指定的是一个二维的数组,刚刚上面不是都才指定一个一维的数组嘛,为什么这里就是一个二维的呢?第二个参数也是一个color的数组。

其实可以这样理解,就是把上面说的一个状态和一个color又分别装到了一个数组中了,所以维度都对应增加了1,这样我们就不用去添加好几次了,注意上面的写法,每一种状态我们都需要添加一次的!!

那么套路明确了之后就可以把上面的写法改造一下,比如说第一个参数一个二维数组:

    int[][] states = new int[][]{
            new int[]{-android.R.attr.state_checked}, // unchecked
            new int[]{android.R.attr.state_checked}  // checked
    };//把两种状态一次性添加

第二个参数每个状态对应的颜色:

    int[] colors = new int[]{
            Color.RED,
            Color.GREEN
    };//把两种颜色一次性添加

最后再调用构造方法就好啦!!

ColorStateList colorStateList = new ColorStateList(states, colors);

最后,再说说给TextView及它的小弟动态设置CompoundDrawable的问题,这个就是在xml中设置的那个drawableTopdrawableBottom、等等!

这里需要注意一个问题,就是我们代码new出来的Drawable的Bound是没有指定好的,那么导致的问题就是它可能根本就不会绘制的!!

setCompoundDrawables.png

解决办法就是你可以直接调用setCompoundDrawablesRelativeWithIntrinsicBounds()这个老长老长的方法让系统自动去设置那个Bound的参数!

@android.view.RemotableViewMethod
public void setCompoundDrawablesRelativeWithIntrinsicBounds(@Nullable Drawable start,
        @Nullable Drawable top, @Nullable Drawable end, @Nullable Drawable bottom) {

    if (start != null) {
        start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
    }
    if (end != null) {
        end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight());
    }
    if (top != null) {
        top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
    }
    if (bottom != null) {
        bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
    }
    setCompoundDrawablesRelative(start, top, end, bottom);
}

当然你也可以老老实实在创建StateListDrawable的时候手动调用一下setBound()的方法啦!!

到此结束!!希望大家不要再掉到对应的坑里面了!!

---- Edit By Joe ----

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 7,533评论 0 17
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 180,291评论 25 708
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 137,150评论 19 139
  • 更多Android总结知识点 Android中的13种Drawable小结 Android的八种对话框的实现 An...
    侯蛋蛋_阅读 4,193评论 0 5
  • 很久以后,每当小宝路过车站,总是摸摸自己虎虎的小脑袋,粗粗的眉毛拧在一起,小眼睛里满是希冀,顺着长长的铁轨望去,他...
    梁道秋阅读 379评论 0 1

友情链接更多精彩内容