BottomSheetDialog 、DialogFragment 、BottomSheetDialogFragment二次封装及使用方法

这三种dialog,在Android 开发中经常会使用到,基本用法网络上也有很多,下面主要阐述一下我在项目中遇到的坑以及对应的解决办法

BottomSheetDialog

issue :

BottomSheetDialog 弹出时,阴影无法覆盖到状态栏,导致状态栏还是默认的背景色

处理方法:

在oncreate 的时候重新计算并设置window 窗口的高度

public class T3BottomSheetDialog extends BottomSheetDialog {

    public T3BottomSheetDialog(@NonNull Context context) {
        super(context);
    }

    public T3BottomSheetDialog(@NonNull Context context, int theme) {
        super(context, theme);
    }

    protected T3BottomSheetDialog(@NonNull Context context,
            boolean cancelable,
            OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        int statusBarHeight = getStatusBarHeight(getContext());
        int dialogHeight = DisplayUtil.getScreenH(getContext()) - statusBarHeight;
        getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, dialogHeight == 0 ? ViewGroup
                .LayoutParams.MATCH_PARENT : dialogHeight);
    }


    private static int getStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        Resources res = context.getResources();
        int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = res.getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }
}

项目中使用方法:

    private void showSelectPhotoDialog() {
        if (mBottomSheetDialog == null) {
            mBottomSheetDialog = new T3BottomSheetDialog(getContext());
            mBottomSheetDialog.setContentView(R.layout.dialog_photo_selector);
            mBottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet)
                    .setBackgroundResource(android.R.color.transparent);

            mBottomSheetDialog.findViewById(R.id.dialog_cancel_button)
                    .setOnClickListener(v -> mBottomSheetDialog.dismiss());

            mBottomSheetDialog.findViewById(R.id.dialog_from_album_button).setOnClickListener(v -> {
                mBottomSheetDialog.dismiss();
                requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        this::singleAlbum, getString(R.string.album_permission_needed));
            });

            mBottomSheetDialog.findViewById(R.id.dialog_take_photo_button).setOnClickListener(v -> {
                mBottomSheetDialog.dismiss();
                if (!checkPermission()) {
                    new TwoSelectorDialog(getContext(), "权限获取", "是否允许程序调用摄像头权限用于头像拍照", "取消",
                            "允许").setCancelClickListener(Dialog::dismiss).setConfirmClickListener(exSweetAlertDialog -> {
                        exSweetAlertDialog.dismiss();
                        requestPermission(new String[]{Manifest.permission.CAMERA},
                                this::takePhoto, getString(R.string.camera_permission_needed));
                    }).show();
                } else {
                    requestPermission(new String[]{Manifest.permission.CAMERA}, this::takePhoto,
                            getString(R.string.camera_permission_needed));
                }

            });

        }
        mBottomSheetDialog.show();
    }

这里需要注意的一点必选在setContentView之后才可以设置背景
在这里插入图片描述

DialogFragment

DialogFragment 分为 普通Dialog 样式和全屏dialog样式

普通Dialog 样式

主要在onCreateView 中设置相应的dialog 样式

        WindowManager.LayoutParams params = getDialog().getWindow().getAttributes();
        params.windowAnimations = R.style.ad_dialog_anim;
        getDialog().getWindow().setAttributes(params);
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        getDialog().setCanceledOnTouchOutside(false);

并在 onStart 中设置Dialog 对应的宽高,这样默认就在window 窗口中间显示

 Dialog dialog = getDialog();
        if (dialog != null) 
                dialog.getWindow()
                        .setLayout((int) (ScreenUtils.getScreenSizePoint().x * 0.8),
                                ViewGroup.LayoutParams.WRAP_CONTENT);
        }
全屏Dialog 样式

我找了很久始终不能让其全屏显示,最后发现如下方式

同样在onCreateView中

 getDialog().getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL);
            getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

在onStart中

Dialog dialog = getDialog();
        if (dialog != null) {
                dialog.getWindow()
                        .setLayout(  ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.MATCH_PARENT);
最后封装一下

public abstract class BaseDialogFragment extends DialogFragment {

    @Inject
    UserRepository mUserRepository;

    protected View mView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container,
            Bundle savedInstanceState) {

        WindowManager.LayoutParams params = getDialog().getWindow().getAttributes();
        params.windowAnimations = R.style.ad_dialog_anim;
        getDialog().getWindow().setAttributes(params);
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        if (isFullScreen()) {
            getDialog().getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL);
            getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        }
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        getDialog().setCanceledOnTouchOutside(false);
        mView = inflater.inflate(getLayoutId(), null);
        initView();
        initDatas();
        return mView;
    }

    protected abstract int getLayoutId();

    protected abstract void initDatas();

    protected abstract void initView();
    @Override
    public void onStart() {
        super.onStart();

        Dialog dialog = getDialog();
        if (dialog != null) {
            if (isFullScreen()){
                dialog.getWindow()
                        .setLayout(  ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.MATCH_PARENT);
            }else {
                dialog.getWindow()
                        .setLayout((int) (ScreenUtils.getScreenSizePoint().x * 0.8),
                                ViewGroup.LayoutParams.WRAP_CONTENT);
            }

        }
    }


    public boolean isFullScreen() {

        return false;
    }
    /**
     * 是否可以取消
     *
     * @param cancelEnable
     */

    public void setCancelEnable(boolean cancelEnable) {
        setCancelable(cancelEnable);
        getDialog().setCanceledOnTouchOutside(cancelEnable);
    }

}

具体子类继承该类,并实现是否是全屏展示,默认不是全屏展示

BottomSheetDialogFragment

BottomSheetDialogFragment 默认不处理的滑动方式,是先展开一部分,需要手动滑动,才能完整的展开其余内容,项目需求是直接展开全部内容,可以在onStart进行相关处理

public abstract class T3BottomSheetDialogFragment extends BottomSheetDialogFragment {
    protected View mView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
            @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(getLayoutId(), container, false);
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        initView();
        initData();
        return mView;
    }

    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
            bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
        }
        final View view = getView();
        view.post(() -> {
            View parent = (View) view.getParent();
            CoordinatorLayout.LayoutParams params =
                    (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
            CoordinatorLayout.Behavior behavior = params.getBehavior();
            BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
            bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
            parent.setBackgroundColor(Color.TRANSPARENT);
        });
    }
    }

这里会存在另一个问题,就是在点击外部区域的时候,不能自动dismiss 对话框,我使用了一个讨巧的办法,使用了全屏

bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;

并在具体实现类对外部view的点击事件进行了处理

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/id_top_layout1"
        android:layout_width="match_parent"
        android:layout_height="55dp" />

    <View
        android:id="@+id/id_top_layout2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shaper_white_corner_5"
        android:orientation="vertical">

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

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="指派车辆"
                android:textColor="#000"
                android:textSize="16dp" />

            <ImageView
                android:id="@+id/close_dialog"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="12dp"
                android:padding="5dp"
                android:src="@drawable/icon_common_cancel" />

        </RelativeLayout>


        <RelativeLayout
            android:minHeight="100dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.RecyclerView
                android:visibility="gone"
                android:id="@+id/car_list_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </RelativeLayout>
    </LinearLayout>


</LinearLayout>

这里预留了dialog 到屏幕顶部的最小高度 55 dp

    <View
        android:id="@+id/id_top_layout1"
        android:layout_width="match_parent"
        android:layout_height="55dp" />

然后监听了id_top_layout1,id_top_layout2 的touch 事件,一旦触摸直接dismiss 对话框


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            dismiss();
        }
        return false;
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值