Android XML仅一个ID却报重复ID错误?配置变更崩溃求助
Android配置变更时View状态恢复崩溃问题(三星Android 13设备)
错误日志
java.lang.IllegalArgumentException: Wrong state class, expecting ViewState but received class com.google.android.material.button.MaterialButton$SavedState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/left_arrow_btn. Make sure other views do not use the same id
相关代码
XML布局代码
<Button android:id="@+id/left_arrow_btn" android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="left" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@drawable/arrow_left" android:gravity="left" android:visibility="gone" />
Kotlin调用代码
var left_arrow:Button = findViewById(R.id.left_arrow_btn) left_arrow.setOnClickListener { rWebView?.goBack() }
补充信息
- 已确认项目中仅存在一个
left_arrow_btnID - 错误在配置变更(如屏幕旋转)导致
onCreate被调用两次时触发 - 仅在Android 13的三星设备上崩溃,Android 12/13模拟器及部分Android 12实体设备运行正常
解决方案
方案1:统一View类型为MaterialButton
将XML中的<Button>替换为<com.google.android.material.button.MaterialButton>,同时更新Kotlin代码中的类型声明:
<com.google.android.material.button.MaterialButton android:id="@+id/left_arrow_btn" android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="left" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@drawable/arrow_left" android:gravity="left" android:visibility="gone" />
var left_arrow: MaterialButton = findViewById(R.id.left_arrow_btn) left_arrow.setOnClickListener { rWebView?.goBack() }
方案2:阻止系统自动替换View类型
在XML的Button标签中添加android:viewClass="android.widget.Button",强制系统使用原生Button类,避免被替换为MaterialButton:
<Button android:id="@+id/left_arrow_btn" android:viewClass="android.widget.Button" android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="left" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@drawable/arrow_left" android:gravity="left" android:visibility="gone" />
方案3:跳过单个View的状态恢复(不推荐)
如果不需要保存该按钮的状态,可以在onCreate中移除对应View的状态数据后再调用super.onCreate:
override fun onCreate(savedInstanceState: Bundle?) { savedInstanceState?.let { bundle -> val viewState = bundle.getParcelable<Parcelable>("android:viewHierarchyState") as? SparseArray<Parcelable> viewState?.remove(R.id.left_arrow_btn) } super.onCreate(savedInstanceState) // 后续初始化代码 }
问题原因
三星Android 13设备在使用MaterialComponents主题时,会自动将布局中的原生Button替换为MaterialButton,但在配置变更恢复状态时,系统仍按照原Button类型去读取SavedState,导致类型不匹配引发崩溃。其他设备/模拟器无此自动替换逻辑,因此未出现问题。
内容的提问来源于stack exchange,提问作者Tito
相关产品推荐
相关产品推荐

