Android Material容器转场时Dialog Activity闪烁问题求助
Material容器转场时Dialog Activity闪烁问题解决
我在包含BottomSheetDialog的Activity中,点击Dialog内的View,需要实现该View与一个以Dialog形式展示的新Activity(使用Theme.MaterialComponents.DayNight.Dialog主题)之间的Material容器转场。转场功能可正常运行,但动画结束前Dialog Activity会闪烁一次,日志报错:
E/RippleDrawable: The RippleDrawable.STYLE_PATTERNED animation is not supported for a non-hardware accelerated Canvas. Skipping animation.
E/FrameEvents: updateAcquireFence: Did not find frame.
注:已尝试开启硬件加速
已尝试的解决方法:
- 为包含子控件的RelativeLayout和CardView开启
transitionGroup - 使用淡入动画并为视图设置
excludeTarget
相关代码
主Activity(QuickPanelMain)
public class QuickPanelMain extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { config(); super.onCreate(savedInstanceState); setContentView(R.layout.activity_quick_panel_main); MaterialButton show = findViewById(R.id.show); show.setOnClickListener(v -> showMainDialog()); } private void config() { setExitSharedElementCallback(new MaterialContainerTransformSharedElementCallback()); getWindow().setSharedElementsUseOverlay(false); } private void showMainDialog() { BottomSheetDialog dialogZ = new BottomSheetDialog(this); dialogZ.setContentView(R.layout.dialog_quick_panel); dialogZ.setCancelable(true); CardView sectionOne = dialogZ.findViewById(R.id.sectionOne); RelativeLayout parentX = findViewById(R.id.parentX); sectionOne.setOnClickListener(v -> { Intent intentZ = new Intent(this, SensorInformationActivity.class); Bundle transitionData = ActivityOptions .makeSceneTransitionAnimation(this, sectionOne, sectionOne.getTransitionName()).toBundle(); startActivity(intentZ, transitionData); }); dialogZ.show(); } }
BottomSheetDialog内CardView布局
<com.google.android.material.card.MaterialCardView android:id="@+id/sectionOne" android:layout_width="100dp" android:layout_height="100dp" android:layout_below="@+id/header" android:layout_centerHorizontal="true" android:layout_marginVertical="10dp" android:transitionName="sensorinfo" android:transitionGroup="true" app:cardBackgroundColor="#1AFFFFFF" app:cardCornerRadius="20dp" app:cardElevation="0dp">
闪烁的Dialog Activity(SensorInformationActivity)
public class SensorInformationActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { config(); setTheme(R.style.Dialog_Grey); super.onCreate(savedInstanceState); setContentView(R.layout.activity_sensor_info); } private void config() { RelativeLayout dialogY = findViewById(R.id.dialogY); setEnterSharedElementCallback(new MaterialContainerTransformSharedElementCallback()); MaterialContainerTransform transform = new MaterialContainerTransform(); transform.setEndView(dialogY); transform.addTarget(R.id.dialogY); transform.setDuration(500); getWindow().setSharedElementEnterTransition(transform); getWindow().setSharedElementReturnTransition(transform); } }
Dialog Activity布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null" tools:context=".quickpanel.SensorInformationActivity" android:id="@+id/parentY"> <RelativeLayout android:id="@+id/dialogY" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" android:background="@drawable/background_blue" android:transitionName="sensorinfo" android:transitionGroup="true"> <TextView android:id="@+id/header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:text="@string/sensor_info" android:textSize="25sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="60dp" android:layout_below="@+id/header" android:layout_marginHorizontal="20dp" android:layout_marginVertical="10dp" android:background="@drawable/section_white"> </RelativeLayout> </RelativeLayout> </RelativeLayout>
主题样式
<style name="Dialog.Grey" parent="Theme.MaterialComponents.DayNight.Dialog"> <item name="colorPrimary">@color/grey</item> <item name="colorPrimaryVariant">@color/grey</item> <item name="colorOnPrimary">@color/white_dim</item> <item name="colorSecondary">@color/blue</item> <item name="colorSecondaryVariant">@color/blue</item> <item name="colorOnSecondary">@color/white_dim</item> <item name="colorPrimaryDark">@color/grey</item> <item name="android:textColor">?attr/colorOnPrimary</item> <item name="background">@null</item> <item name="android:animateLayoutChanges">true</item> <item name="windowNoTitle">true</item> <item name="android:windowBackground">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:fontFamily">@font/leaguespartanfont</item> <item name="android:windowContentTransitions">true</item> <item name="android:windowActivityTransitions">true</item> <item name="android:windowSharedElementsUseOverlay">false</item> </style>
解决方案
1. 修正Dialog Activity初始化顺序
当前config()在setContentView()前调用,导致findViewById返回null,转场配置未生效。调整顺序并完善配置:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { setTheme(R.style.Dialog_Grey); super.onCreate(savedInstanceState); setContentView(R.layout.activity_sensor_info); config(); // 移到setContentView之后 } private void config() { RelativeLayout dialogY = findViewById(R.id.dialogY); if (dialogY == null) return; setEnterSharedElementCallback(new MaterialContainerTransformSharedElementCallback()); MaterialContainerTransform transform = new MaterialContainerTransform(); transform.setEndView(dialogY); transform.addTarget(R.id.dialogY); transform.setDuration(500); transform.setScrimColor(Color.TRANSPARENT); // 禁用遮罩动画避免闪烁 getWindow().setSharedElementEnterTransition(transform); getWindow().setSharedElementReturnTransition(transform); // 强制开启硬件加速 getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); }
2. 替换Drawable背景为Material组件
用MaterialCardView代替RelativeLayout作为Dialog容器,避免Drawable背景的渲染冲突:
修改activity_sensor_info.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" tools:context=".quickpanel.SensorInformationActivity" android:id="@+id/parentY"> <com.google.android.material.card.MaterialCardView android:id="@+id/dialogY" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" android:transitionName="sensorinfo" android:transitionGroup="true" app:cardBackgroundColor="@color/blue" app:cardCornerRadius="20dp" app:cardElevation="4dp"> <TextView android:id="@+id/header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top|center_horizontal" android:layout_marginTop="10dp" android:text="@string/sensor_info" android:textSize="25sp" /> <com.google.android.material.card.MaterialCardView android:layout_width="match_parent" android:layout_height="60dp" android:layout_gravity="top|center_horizontal" android:layout_marginHorizontal="20dp" android:layout_marginTop="50dp" app:cardBackgroundColor="@color/white" app:cardCornerRadius="10dp"> </com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView> </RelativeLayout>
3. 优化主题配置
移除冲突属性,确保转场平滑:
<style name="Dialog.Grey" parent="Theme.MaterialComponents.DayNight.Dialog"> <item name="colorPrimary">@color/grey</item> <item name="colorPrimaryVariant">@color/grey</item> <item name="colorOnPrimary">@color/white_dim</item> <item name="colorSecondary">@color/blue</item> <item name="colorSecondaryVariant">@color/blue</item> <item name="colorOnSecondary">@color/white_dim</item> <item name="colorPrimaryDark">@color/grey</item> <item name="android:textColor">?attr/colorOnPrimary</item> <item name="windowNoTitle">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsFloating">true</item> <item name="android:fontFamily">@font/leaguespartanfont</item> <item name="android:windowContentTransitions">true</item> <item name="android:windowSharedElementsUseOverlay">false</item> </style>
4. 为BottomSheetDialog开启硬件加速
private void showMainDialog() { BottomSheetDialog dialogZ = new BottomSheetDialog(this); dialogZ.setContentView(R.layout.dialog_quick_panel); // 强制开启Dialog窗口硬件加速 dialogZ.getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); dialogZ.setCancelable(true); CardView sectionOne = dialogZ.findViewById(R.id.sectionOne); sectionOne.setOnClickListener(v -> { Intent intentZ = new Intent(this, SensorInformationActivity.class); Bundle transitionData = ActivityOptions .makeSceneTransitionAnimation(this, sectionOne, sectionOne.getTransitionName()).toBundle(); startActivity(intentZ, transitionData); }); dialogZ.show(); }
内容的提问来源于stack exchange,提问作者Max Devtec
相关产品推荐
相关产品推荐

