ComponentActivity中MaterialAlertDialog按钮样式失效问题
我正在开发一款以XML视图框架为主、新增Jetpack Compose页面的Android应用。项目中使用自定义布局实现MaterialAlertDialog,相关代码如下:
对话框布局代码(dialog_simple_btn.xml)
<?xml version="1.0" encoding="utf-8"?> <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" style="@style/CustomCardView" android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="16dp" > <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" > <TextView android:id="@+id/title" style="@style/TextViewRegular.DialogTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" app:layout_constraintBottom_toTopOf="@id/btn" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="@string/dialogMessage_newGridCompleted" /> <Button android:id="@+id/btn" style="@style/DialogButtonOk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@android:string/ok" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/title" /> </androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.card.MaterialCardView>
样式代码
CustomCardView样式
<style name="CustomCardView" parent="Widget.MaterialComponents.CardView"> <item name="cardBackgroundColor">@color/cardBackground</item> </style>
TextView相关样式
<style name="TextViewRegular" parent="Widget.MaterialComponents.TextView"> <item name="android:textColor">@color/white</item> <item name="fontFamily">@font/avenir_next_regular</item> <item name="android:fontFamily">@font/avenir_next_regular</item> <item name="android:textSize">19sp</item> </style> <style name="TextViewRegular.DialogTitle"> <item name="android:textColor">@color/background</item> <item name="android:textSize">19sp</item> </style>
DialogButtonOk样式
<style name="DialogButtonOk" parent="Widget.MaterialComponents.Button"> <item name="android:textColor">@color/white</item> <item name="fontFamily">@font/avenir_next_regular</item> <item name="android:fontFamily">@font/avenir_next_regular</item> <item name="android:gravity">center</item> <item name="android:padding">16dp</item> <item name="android:textSize">14sp</item> <item name="strokeWidth">1dp</item> <item name="strokeColor">@color/white</item> <item name="backgroundTint">@color/btnBackground</item> <item name="rippleColor">@color/white</item> <item name="cornerRadius">5.5dp</item> </style>
对话框展示代码(Kotlin)
private fun displayDialog(@StringRes messageRes: Int) { val customView = LayoutInflater.from(this).inflate(R.layout.dialog_simple_btn, null, false) customView.findViewById<TextView>(R.id.title)?.setText(messageRes) val dialog = MaterialAlertDialogBuilder(this).apply { setView(customView) setCancelable(false) }.create() dialog?.apply { window?.setBackgroundDrawableResource(R.drawable.bg_dialog) show() } customView.findViewById<Button>(R.id.btn)?.setOnClickListener { dialog?.dismiss() } }
背景Drawable代码(bg_dialog.xml)
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="@android:color/transparent" /> <corners android:radius="16dp" /> <padding android:left="16dp" android:right="16dp" /> </shape>
问题
该对话框在AppCompatActivity中展示效果符合预期,但在ComponentActivity中按钮背景丢失、波纹效果失效,请问问题原因是什么?
核心原因
AppCompatActivity默认集成了Material Components主题的AppCompat桥接层,会自动将布局中的原生Button控件替换为MaterialButton,从而支持backgroundTint、rippleColor等Material专属样式属性。
而ComponentActivity是更基础的Activity类,没有内置控件自动替换逻辑,布局中的Button就是原生Android控件——它不支持Material Components样式里的backgroundTint、rippleColor、strokeWidth等属性,导致这些样式失效,按钮显示为原生默认状态(背景丢失、无波纹)。
解决方法
方法1:直接使用MaterialButton控件
修改布局中的Button为com.google.android.material.button.MaterialButton,确保控件本身支持Material样式属性:
<com.google.android.material.button.MaterialButton android:id="@+id/btn" style="@style/DialogButtonOk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@android:string/ok" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/title" />
方法2:让ComponentActivity使用Material主题
在AndroidManifest.xml中,给对应的ComponentActivity指定Material Components主题(如Theme.MaterialComponents.DayNight或自定义继承自该主题的样式):
<activity android:name=".YourComposeActivity" android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar"> </activity>
这样ComponentActivity会自动启用控件替换逻辑,原生Button会被替换为MaterialButton,样式即可正常生效。
内容的提问来源于stack exchange,提问作者rolandl

