设置background属性使用selector的时候内置?attr报错的解决方案

本文探讨了在Android中使用selector设置视图背景时遇到的问题,特别是当试图从主题中引用颜色值时导致的崩溃。提供了多种解决方案,包括创建自定义shape文件和使用代码动态生成selector。

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

当我们设置background属性的时候可以设置background="@color/black"

也可以设置 background="@drawable/selector"

然后selector我们可以这样设置

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 没有焦点时的背景图片 -->
    <item android:drawable="@color/colorPressed" android:state_pressed="true"/>
    <item android:drawable="@color/colorPressed" android:state_focused="true"/>
    <item android:drawable="@color/colorPressed" android:state_selected="true"/>
    <item android:drawable="@color/black" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>
</selector>
但是当我们设置了属性来设置这个颜色的时候就会遇到崩溃
比如我们这样
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 没有焦点时的背景图片 -->
    <item android:drawable="@color/colorPressed" android:state_pressed="true"/>
    <item android:drawable="@color/colorPressed" android:state_focused="true"/>
    <item android:drawable="@color/colorPressed" android:state_selected="true"/>
    <item android:drawable="?attr/backgroundColorValue" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>
</selector>
运行的话会直接崩溃,报错的原因是无法获取到对应的drawable对象,至于为什么无法将颜色转换成对应的drawable我也不清楚,既然不能转换那我们可以手动转换
解决方案:
手动创建一个shape.xml,如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="?attr/backgroundColorValue" />
</shape>
然后我们再到selector中引用这个drawable就可以了
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 没有焦点时的背景图片 -->
    <item android:drawable="@color/colorPressed" android:state_pressed="true"/>
    <item android:drawable="@color/colorPressed" android:state_focused="true"/>
    <item android:drawable="@color/colorPressed" android:state_selected="true"/>
    <item android:drawable="@drawable/shape" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>
</selector>

 

2016-11-11补充 :
这种方式在android6.0以上设备可用,但在android5.0及以下设备仍然会崩溃
这个时候将 shape中的
<solid android:color="?attr/backgroundColorValue" />
修改为
<solid android:background="?attr/backgroundColorValue" />
就不会崩溃,但在android6.0设备上背景颜色就变成了透明,而在5.0以下设备就没有问题
因此这不是一个好的解决方案,很多设备没有升级到6.0
参考 http://blog.youkuaiyun.com/qingfeng812/article/details/51601500 

经过一番查找,目前已经了解到根本的原因,出现这个问题,主要是因为android在api23版本才支持selector从主题中读取颜色值
低于api23只能使用代码去支持,所以我们需要用代码去创建这个selector,然后才可以实现对应的切换
参考 http://blog.youkuaiyun.com/qq284565035/article/details/52177225

至于如何用代码创建selector,参见如下代码:

 

StateListDrawable drawable = new StateListDrawable();
        //Non focused states
        drawable.addState(new int[]{-android.R.attr.state_focused, -android.R.attr.state_selected, -android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact));
        drawable.addState(new int[]{-android.R.attr.state_focused, android.R.attr.state_selected, -android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact_sel));
        //Focused states
        drawable.addState(new int[]{android.R.attr.state_focused,-android.R.attr.state_selected, -android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact_sel));
        drawable.addState(new int[]{android.R.attr.state_focused,android.R.attr.state_selected, -android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact_sel));
        //Pressed
        drawable.addState(new int[]{android.R.attr.state_selected, android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact_sel));
        drawable.addState(new int[]{android.R.attr.state_pressed},
                getResources().getDrawable(R.drawable.contact_sel));
         
        TextView textView = (TextView) findViewById(R.id.TextView_title);
                
        textView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);

 

参考 https://my.oschina.net/non6/blog/298156

 

http://www.cnblogs.com/jason-star/archive/2012/09/28/2706698.html

 

使用Selector传递参数时,可以使用Selector的register()方法来注册回调函数,并将参数作为关键字参数传递。例如: ```python import selectors import socket def accept_wrapper(sock, selector): conn, addr = sock.accept() # 接受连接 print(f"Accepted connection from {addr}") conn.setblocking(False) # 将连接设置为非阻塞模式 # 注册回调函数并传递参数 selector.register(conn, selectors.EVENT_READ, read_wrapper, conn) def read_wrapper(conn, selector): data = conn.recv(1024) # 读取数据 if data: print(f"Received data from {conn.getpeername()}: {data.decode()}") else: print(f"Closing connection from {conn.getpeername()}") selector.unregister(conn) conn.close() # 创建一个Selector对象 selector = selectors.DefaultSelector() # 创建一个socket对象并绑定到指定地址和端口 server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind(('localhost', 8888)) server_sock.listen() # 将socket对象注册到Selector中,并设置回调函数 selector.register(server_sock, selectors.EVENT_READ, accept_wrapper, selector) while True: events = selector.select() # 阻塞等待事件发生 for key, _ in events: callback = key.data # 获取回调函数 callback(key.fileobj, selector, **key.kwargs) # 调用回调函数并传递参数 ``` 在上面的例子中,我们在accept_wrapper()方法中注册了read_wrapper()方法,并将连接对象conn作为参数传递。在read_wrapper()方法中,我们可以通过关键字参数conn获取连接对象,并使用它读取数据。注意,在调用回调函数时,需要将SelectorKey对象的kwargs属性作为关键字参数传递给回调函数,以便获取参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值