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

如何将带单选按钮的CardView作为对话框弹出并实现背景模糊效果

自定义CardView排序对话框实现指南

需求实现目标

  • 将包含2个互斥单选按钮的自定义CardView布局作为对话框展示
  • 对话框弹出时,底层的HomeFragment布局添加模糊效果
  • 用户选中任意单选按钮后,延迟500ms再关闭对话框,保证用户能看到选中状态反馈

用到的布局文件

sort_image.xml(自定义对话框布局)

<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="300dp"
    android:layout_height="200dp"
    android:layout_gravity="center"
    android:backgroundTint="@color/grey"
    app:cardCornerRadius="20dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/sort_textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerInParent="true"
            android:layout_marginTop="5dp"
            android:fontFamily="@font/roboto"
            android:text="Sort by"
            android:textAlignment="center"
            android:textColor="@color/lite_grey"
            android:textSize="25sp" />

        <com.google.android.material.card.MaterialCardView
            android:id="@+id/divider_line_sort_by"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_below="@id/sort_textView"
            android:layout_marginStart="10dp"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="10dp"
            android:backgroundTint="@color/lite_grey"
            app:cardCornerRadius="50dp" />

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true">

            <TextView
                android:id="@+id/latest_sort_textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="30dp"
                android:layout_marginTop="30dp"
                android:fontFamily="@font/roboto"
                android:text="Latest"
                android:textAlignment="center"
                android:textColor="@color/lite_grey"
                android:textSize="25sp" />

            <TextView
                android:id="@+id/most_popular_sort_textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/latest_sort_textView"
                android:layout_alignParentStart="true"
                android:layout_centerInParent="true"
                android:layout_marginStart="30dp"
                android:layout_marginTop="25sp"
                android:fontFamily="@font/roboto"
                android:text="Most Popular"
                android:textAlignment="center"
                android:textColor="@color/lite_grey"
                android:textSize="25sp" />

            <RadioGroup
                android:id="@+id/sort_radio_group"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true">

                <RadioButton
                    android:id="@+id/latest_sort_radio_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="25sp" />

                <RadioButton
                    android:id="@+id/most_popular_sort_radio_button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp" />

            </RadioGroup>

        </RelativeLayout>


    </RelativeLayout>

</com.google.android.material.card.MaterialCardView>

fragment_home.xml(触发弹窗的底层布局,仅核心代码)

注:仅提供该布局的核心代码

<com.google.android.material.card.MaterialCardView
                android:id="@+id/sort"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:layout_marginEnd="5dp"
                android:layout_marginBottom="5dp"
                android:layout_toStartOf="@id/divider_line"
                android:backgroundTint="@color/black"
                android:elevation="6dp"
                android:paddingBottom="10dp"
                android:textAlignment="center"
                app:cardCornerRadius="10dp">

                <TextView
                    android:id="@+id/sort_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="8dp"
                    android:layout_marginEnd="8dp"
                    android:layout_marginBottom="5dp"
                    android:fontFamily="@font/roboto"
                    android:text="@string/sort"
                    android:textAlignment="center"
                    android:textColor="@color/white"
                    android:textSize="17sp"
                    android:textStyle="bold" />

            </com.google.android.material.card.MaterialCardView>

功能实现代码

首先在res/values/styles.xml中添加透明对话框样式,避免默认对话框背景遮挡自定义布局:

<style name="TransparentDialog" parent="Theme.MaterialComponents.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
</style>

然后在HomeFragment中添加如下逻辑:

import android.app.Dialog;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.RadioGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class HomeFragment extends Fragment {
    // 底层根布局,用于添加模糊效果
    private View rootView;
    // 触发弹窗的排序卡片按钮
    private MaterialCardView sortCard;
    // 对话框关闭延迟时间,单位ms,可自行调整
    private static final long DISMISS_DELAY = 500;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_home, container, false);
        sortCard = rootView.findViewById(R.id.sort);
        
        // 排序按钮点击弹出对话框
        sortCard.setOnClickListener(v -> showSortDialog());
        
        return rootView;
    }

    private void showSortDialog() {
        Dialog sortDialog = new Dialog(requireContext(), R.style.TransparentDialog);
        sortDialog.setContentView(R.layout.sort_image);
        sortDialog.setCanceledOnTouchOutside(true);
        
        // 给底层布局添加模糊效果(Android 12+ 可用系统RenderEffect,低版本可引入BlurView等第三方库实现)
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
            rootView.setRenderEffect(android.graphics.RenderEffect.createBlurEffect(25f, 25f, android.graphics.Shader.TileMode.CLAMP));
        }
        
        // 对话框关闭时移除模糊效果
        sortDialog.setOnDismissListener(dialog -> {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
                rootView.setRenderEffect(null);
            }
        });
        
        // 单选按钮选中监听
        RadioGroup sortRadioGroup = sortDialog.findViewById(R.id.sort_radio_group);
        sortRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
            // 选中后延迟关闭,保证用户看到选中状态
            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                if (sortDialog.isShowing()) {
                    sortDialog.dismiss();
                }
                // 在这里添加选中后的业务逻辑
                if (checkedId == R.id.latest_sort_radio_button) {
                    // 按最新排序逻辑
                } else if (checkedId == R.id.most_popular_sort_radio_button) {
                    // 按最热门排序逻辑
                }
            }, DISMISS_DELAY);
        });
        
        sortDialog.show();
    }
}

补充说明

  • 低版本Android模糊效果可以用RenderScript或者第三方Blur库实现,调用逻辑和上述代码一致,仅模糊方法不同
  • 延迟时间推荐设置在300-800ms区间,兼顾用户感知和操作流畅度

内容的提问来源于stack exchange,提问作者Vasant Raval

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:45:06