You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:57:36