Android BottomSheetDialogFragment uses detailed explanation, setting rounded corners, fixed height, default full screen, etc.

Please indicate the source of the reprint: http://blog.csdn.net/zhaoyanjun6/article/details/127967304
This article comes from [Zhao Yanjun's blog]

Effect

insert image description here

insert image description here
The MD-style bottom pop-up window is easier to use than custom dialog or popupwindow, and the function is more powerful.

In fact, in terms of subdivision, it is BottomSheet, BottomSheetDialog, BottomSheetDialogFragment

Code https://gitee.com/zhaoyanjun/bottomSheetDialogFragmentDemo

BottomSheet

The relationship with the main interface is the same level, and can be triggered by events. If the display height is set, it is also possible 拉出来, and it will not affect the interaction of the main interface.
insert image description here
XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">

    <LinearLayout
        android:id="@+id/ll_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:behavior_peekHeight="80dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="上拉解锁隐藏功能"
            android:textColor="@color/white"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center"
            android:text="a"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_orange_dark"
            android:gravity="center"
            android:text="b"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_green_light"
            android:gravity="center"
            android:text="c"
            android:textSize="20sp" />

    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

Notice,

  • Here you need to coordinate the layout of the CoordinatorLayout package
  • app:behavior_peekHeight displays the height, if not displayed, set it to 0
  • app:layout_behavior indicates that this is a bottom_sheet

The above three conditions are all necessary.

the code

 View bottomView = findViewById(R.id.ll_bottom_sheet);
        bottomView.setOnClickListener(v -> {
    
    
            BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomView);
            if (behavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
    
    
                //如果是展开状态,则关闭,反之亦然
                behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            } else {
    
    
                behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });
  • STATE_COLLAPSED: Collapsed state
  • STATE_EXPANDED: Expanded state
  • STATE_DRAGGING : Transition state
  • STATE_SETTLING: The short period of time when the view slides freely from the finger to when it finally stops
  • STATE_HIDDEN : There is no such state by default (this state can be enabled through app:behavior_hideable), after enabling, the user will be able to completely hide the bottom sheet by sliding down

BottomSheetDialog

insert image description here

半透明It can be seen that there is a mask after the pop-up , which affects the interaction of the main interface at this time, which means that BottomSheetDialogthe priority at this time is higher than that of the main interface.

the code

public class MyBottomSheetDialog extends BottomSheetDialog {
    
    

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

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

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

Show Dialog

MyBottomSheetDialog bottomSheetDialog = new MyBottomSheetDialog(this);
bottomSheetDialog.setContentView(R.layout.bottom_dialog_layout);
bottomSheetDialog.show();

bottom_dialog_layout :

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

    <TextView
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#aa8"
        android:text="Bottom Dialog"
        android:gravity="center"
        android:layout_gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

A relatively simple way to use it, just instantiate it setContentViewand then call it show.
This is just a display effect. In fact, the usage scenario may be more complicated, and some operations need to be done, etc. Therefore, you can also customize the dialoginheritance from BottomSheetDialog, and then process your own business logic.

BottomSheetDialogFragment

insert image description here
The effect is BottomSheetDialogsimilar, and the code is DialogFragmentsimilar.

the code

public class MyDialogFragment extends BottomSheetDialogFragment {
    
    

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        View view = inflater.inflate(R.layout.bottom_dialog_fragment_layout, container, false);
        return view;
    }
}

bottom_dialog_fragment_layout

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

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:background="#f00"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

show

MyDialogFragment dialog = new MyDialogFragment();
Bundle bundle = new Bundle();
dialog.setArguments(bundle);
dialog.show(getSupportFragmentManager(), "dialog_fragment");

But in actual development, our needs may not be satisfied, such as the above part 圆角效果, 指定高度etc.

rounded corners

First set the original background to be transparent

style.xml

 <style name="MyBottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/BottomSheetStyleWrapper</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">false</item>
    </style>

    <style name="BottomSheetStyleWrapper" parent="Widget.MaterialComponents.BottomSheet.Modal">
        <item name="android:background">@android:color/transparent</item>
    </style>

Set style in onCreate

public class MyDialogFragment extends BottomSheetDialogFragment {
    
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style.MyBottomSheetDialog);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        View view = inflater.inflate(R.layout.bottom_dialog_fragment_layout, container, false);
        return view;
    }
}

Set on the view of the root layoutbackground

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="6dp"
    android:background="@drawable/fragment_dialog_bg">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:background="#f00"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

Special attention: In addition to setting android:backgroundthe property also needs to set android:paddingthe property, otherwise the rounded corners will not be displayed.

fragment_dialog_bg

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />
    <solid android:color="@android:color/white" />

</shape>

remove background mask

Need to add attribute styleinandroid:backgroundDimEnabled

<!--  没有蒙版的style-->
    <style name="MyBottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/BottomSheetStyleWrapper</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>

Set mask transparency

styleAdd attribute in android:backgroundDimAmount, attribute value range 0 - 1 .

  • 0 : fully transparent
  • 1: fully opaque
    <style name="MyBottomSheetDialog2" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/BottomSheetStyleWrapper</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:backgroundDimAmount">0.4</item>
    </style>

Click outside the dialog, the dialog does not disappear

Override onCreateDialogthe method , set setCanceledOnTouchOutsidethe value to false

public class MyDialogFragment extends BottomSheetDialogFragment {
    
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style.MyBottomSheetDialog);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    
    
        Dialog dialog =  super.onCreateDialog(savedInstanceState);
        dialog.setCanceledOnTouchOutside(false);
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        View view = inflater.inflate(R.layout.bottom_dialog_fragment_layout, container, false);
        return view;
    }
}

Do not drag down

bottomSheetBehavior.setHideable(false);

Specific usage method:

   @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    
    
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        if (dialog instanceof BottomSheetDialog) {
    
    
            BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
            bottomSheetDialog.setOnShowListener(dialogInterface -> {
    
    
                FrameLayout bottomSheet = bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                bottomSheetBehavior.setHideable(false);
            });
        }
        return dialog;
    }

Set the fixed height of the popup frame

bottomSheetBehavior.setPeekHeight(1200);

use:


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    
    
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        if (dialog instanceof BottomSheetDialog) {
    
    
            BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
            bottomSheetDialog.setOnShowListener(dialogInterface -> {
    
    
                FrameLayout bottomSheet = bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                bottomSheetBehavior.setPeekHeight(1200);
            });
        }
        return dialog;
    }

    @Nullab

Content fills the full screen

When there is a lot of content, such as a recyclerView, we want the height of the dialog to expand to be full screen.

//默认展开
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);

use

 @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    
    
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        if (dialog instanceof BottomSheetDialog) {
    
    
            BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
            bottomSheetDialog.setOnShowListener(dialogInterface -> {
    
    
                FrameLayout bottomSheet = bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                //默认展开
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            });
        }
        return dialog;
    }

Monitor Expand Collapse

bottomSheetBehavior.setBottomSheetCallback()

use

public class MyDialogFragment extends BottomSheetDialogFragment {
    
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style.MyBottomSheetDialog);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    
    
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        if (dialog instanceof BottomSheetDialog) {
    
    
            BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
            bottomSheetDialog.setOnShowListener(dialogInterface -> {
    
    
                FrameLayout bottomSheet = bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                //默认展开
                bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
    
    
                    @Override
                    public void onStateChanged(@NonNull View view, int newState) {
    
    
                        switch (newState) {
    
    
                            case BottomSheetBehavior.STATE_EXPANDED:

                                break;
                            case BottomSheetBehavior.STATE_COLLAPSED:

                                break;
                            case BottomSheetBehavior.STATE_DRAGGING:

                                break;
                            case BottomSheetBehavior.STATE_SETTLING:

                                break;
                            case BottomSheetBehavior.STATE_HIDDEN:

                                break;
                        }
                    }

                    @Override
                    public void onSlide(@NonNull View view, float v) {
    
    

                    }
                });
            });
        }
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        View view = inflater.inflate(R.layout.bottom_dialog_fragment_layout, container, false);
        return view;
    }
}

Permanent View at the bottom

It is difficult to realize the bottom resident layout in BottomSheetDialogFragment. Fortunately, some people have achieved it in a clever way.

https://github.com/dorianpavetic/StickyBottomSheet

Android: Sticky view at the bottom of bottom sheet dialog fragment

Guess you like

Origin blog.csdn.net/zhaoyanjun6/article/details/127967304