android button null,Android CheckBox setButtonDrawable(null) 在 4.x 版本中无效

博客探讨了在Android中如何隐藏CheckBox的按钮,指出setButtonDrawable(null)在4.x版本中无效,而在5.0及以上版本才起作用的原因。通过对比4.4和5.0的源码,揭示了问题所在,并提供了通过setButtonDrawable(newStateListDrawable())解决此问题的方法。同时,内容还涉及了CheckBox的默认样式和初始化过程。
摘要由CSDN通过智能技术生成

当我们需要只显示 CheckBox 的文字,而不显示按钮的时候,通常在 XML 文件中设置 CheckBox 的 android:button="@null"。

当我们自定义 CheckBox 并希望在代码中控制按钮不显示的时候,可以 setButtonDrawable(null) 来达到效果。

但是有一个问题,setButtonDrawable(null) 在 4.x 中是没有效果的,从 5.0 开始才有效果。

为了调查为什么 4.x 没有效果,我们来分别看看 4.4 和 5.0 的源码,到底 setButtonDrawable 方法有什么不同。

关于查看 Android 各版本的源码推荐两个网站:

GrepCode

AndroidXRef

先来看 4.4 的源码,其实 setButtonDrawable 方法在 CheckBox 的父类 CompoundButton 中。

/**

* Set the background to a given Drawable

*

* @param d The Drawable to use as the background

*/

public void setButtonDrawable(Drawable d) {

if (d != null) {

if (mButtonDrawable != null) {

mButtonDrawable.setCallback(null);

unscheduleDrawable(mButtonDrawable);

}

d.setCallback(this);

d.setVisible(getVisibility() == VISIBLE, false);

mButtonDrawable = d;

setMinHeight(mButtonDrawable.getIntrinsicHeight());

}

refreshDrawableState();

}

可以看到如果 Drawable 为 null,就直接跳过去了,没有任何效果!

再来看看 5.0 中的源码

public void More ...setButtonDrawable(Drawable d) {

if (mButtonDrawable != d) {

if (mButtonDrawable != null) {

mButtonDrawable.setCallback(null);

unscheduleDrawable(mButtonDrawable);

}

mButtonDrawable = d;

if (d != null) {

d.setCallback(this);

d.setLayoutDirection(getLayoutDirection());

if (d.isStateful()) {

d.setState(getDrawableState());

}

d.setVisible(getVisibility() == VISIBLE, false);

setMinHeight(d.getIntrinsicHeight());

applyButtonTint();

}

}

}

可以看到并不是判断为不为 null,而是判断和之前的一样不一样,CheckBox 默认是有按钮的,所以默认 mButtonDrawable 是不为 null 的,所以判断成立,mButtonDrawable 被赋为 null。

也许你会问,为什么 android:button="@null" 不管是 4.x 还是 5.0 之后都是有效果的呢?那我们就得看看构造方法初始化的源码了

public More ...CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

final TypedArray a = context.obtainStyledAttributes(

attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes);

final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);

if (d != null) {

setButtonDrawable(d);

}

......

......

}

可以看到,如果传进来的 Drawable 不为 null,才设置初始按钮。这部分代码 4.x 和 5.0 以后都一样,所以 android:button="@null" 是不受版本影响的。

至于初始按钮的样式可以看 CheckBox 中的构造方法的源码

public CheckBox(Context context, AttributeSet attrs) {

this(context, attrs, com.android.internal.R.attr.checkboxStyle);

}

可以看到初始样式是 com.android.internal.R.attr.checkboxStyle。

com.android.internal....可以到 android / frameworks / base / core / res / res / values 下面去找。

checkboxStyle 在 themes.xml 中

@style/Widget.CompoundButton.CheckBox

继续看 style.xml 中的 Widget.CompoundButton.CheckBox

?attr/listChoiceIndicatorMultiple

listChoiceIndicatorMultiple 还是在 themes.xml 中

@drawable/btn_check

继续到 android / frameworks / base / core / res / res / drawable 下去找 btn_check.xml

android:state_enabled="true"

android:drawable="@drawable/btn_check_on" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_off" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_on_pressed" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_off_pressed" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_on_selected" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_off_selected" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_off" />

android:state_enabled="true"

android:drawable="@drawable/btn_check_on" />

android:drawable="@drawable/btn_check_on_disable" />

android:drawable="@drawable/btn_check_off_disable" />

android:drawable="@drawable/btn_check_on_disable_focused" />

android:drawable="@drawable/btn_check_off_disable_focused" />

到这边,我们就找到了 CheckBox 默认的按钮效果。

等等,说了这么多,到底 setButtonDrawable(null) 在 4.x 版本中无效的问题怎么解决呢?办法很简单,setButtonDrawable(new StateListDrawable()) 即可!

最后,不仅仅 CheckBox,所有继承自 CompoundButton 的控件都有这个问题,可以看看 CompoundButton 有哪些子控件

2c9cb653aeab

如图,RadioButton,Switch 等等的控件都是继承自 CompoundButton 的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值