如何用drawableLeft加载XML图标?Android旧API(如16)崩溃问题
嘿,这个坑我之前踩过!你遇到崩溃的核心原因很简单:android:drawableStart这个属性是从API Level 17(Android 4.2)才正式引入的,而API 16(Android 4.1)及更早的系统根本不认识这个属性,加载布局时就会直接抛出异常。下面给你几个实用的解决办法,按需选择:
方案1:使用AppCompatButton兼容组件(推荐)
如果你的项目已经引入了AndroidX或者旧版Support Library,直接把原生Button换成AppCompatButton就可以完美解决问题。AppCompat系列组件会自动处理低版本系统对新属性的兼容,既保留drawableStart的RTL(从右到左)布局适配能力,又不会在API 16上崩溃。
修改后的布局代码如下:
<androidx.appcompat.widget.AppCompatButton android:id="@+id/vitimas" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:drawableLeft="@drawable/ic_person_black_24dp" android:drawableStart="@drawable/ic_person_black_24dp" android:background="@drawable/botao_verde" android:text="Vítimas"/>
注:如果用的是旧版Support Library,把
androidx.appcompat.widget.AppCompatButton换成android.support.v7.widget.AppCompatButton即可。
方案2:移除drawableStart属性(简单粗暴)
如果你的应用不需要适配RTL布局,或者低版本设备用户群体对RTL没有需求,直接删掉android:drawableStart属性,只保留android:drawableLeft就可以了。drawableLeft是从API Level 1就支持的属性,所有版本都能正常识别。
修改后的代码:
<Button android:id="@+id/vitimas" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:drawableLeft="@drawable/ic_person_black_24dp" android:background="@drawable/botao_verde" android:text="Vítimas"/>
方案3:代码动态设置(灵活适配)
如果不想修改布局组件,也可以通过Java/Kotlin代码动态判断系统版本,分别设置对应的Drawable属性:
Java版本:
Button vitimasBtn = findViewById(R.id.vitimas); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API 17及以上使用兼容RTL的方法 vitimasBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_person_black_24dp, 0, 0, 0); } else { // API 16及以下使用传统方法 vitimasBtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_person_black_24dp, 0, 0, 0); }
Kotlin版本:
val vitimasBtn = findViewById<Button>(R.id.vitimas) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { vitimasBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_person_black_24dp, 0, 0, 0) } else { vitimasBtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_person_black_24dp, 0, 0, 0) }
个人最推荐方案1,因为AppCompatButton不仅解决了这个崩溃问题,还能为低版本设备带来更多Material Design风格的兼容优化,一举多得。
内容的提问来源于stack exchange,提问作者Woton Sampaio

