Igor Bubelov
Igor Bubelov

Reputation: 5374

How to use BottomSheetDialog?

I want to try BottomSheetDialog introduced in Android Support Library 23.2 but it doesn't seem to work correctly. Here is what the doc says:

While BottomSheetBehavior captures the persistent bottom sheet case, this release also provides a BottomSheetDialog and BottomSheetDialogFragment to fill the modal bottom sheets use case. Simply replace AppCompatDialog or AppCompatDialogFragment with their bottom sheet equivalents to have your dialog styled as a bottom sheet."

So I changed my AppCompatDialog to BottomSheetDialog:

package my.package.ui.dialog;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.design.widget.BottomSheetDialog;

import my.package.R;

public class AccountActionsDialog extends BottomSheetDialog {
    public AccountActionsDialog(Context context) {
        super(context);

        if (context instanceof Activity) {
            setOwnerActivity((Activity) context);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutInflater().inflate(R.layout.dialog_account_actions, null));
    }
}

Here is my layout file:

<?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="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0000"
        android:padding="16dp"
        android:text="Delete account"
        android:textColor="#ffffff" />

</LinearLayout>

Then I use the following code in my Activity:

new AccountActionsDialog(this).show();

My screen becomes dimmed but the content of my dialog is not visible. Any thoughts on what might be missing? It works fine when I use AppCompatDialog instead.

Upvotes: 38

Views: 50821

Answers (6)

Rakesh Jha
Rakesh Jha

Reputation: 379

To open bottom sheet dialog use following code.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="visible"
    android:orientation="vertical">


    <TextView
        android:id="@+id/choosetxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Please verify your SIM Card."
        android:textAlignment="center"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:textStyle="bold" />

    <LinearLayout
        android:id="@+id/layoutEdit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal"
        android:padding="8dp">

        <TextView
            android:id="@+id/tv_bottom_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:textAlignment="center"
            android:textColor="@color/black"
            android:textSize="16sp" />

    </LinearLayout>

    <ProgressBar
        android:id="@+id/loadingBottom_progress_xml"
        style="?android:attr/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:visibility="gone" />

    <TextView
        android:id="@+id/tv_inProgress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="center"
        android:text="Verification in progress."
        android:textColor="@color/black"
        android:textSize="15dp"
        android:textStyle="bold"
        android:visibility="invisible" />

    <Button
        android:id="@+id/btn_verifyss"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:background="@drawable/roundbutton"
        android:text="START SIM VERIFICATION"
        android:textColor="@color/white" />

    <LinearLayout
        android:id="@+id/linear_congrats"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        android:visibility="gone">


        <TextView
            android:id="@+id/tv_verifys"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:gravity="center"
            android:text="Congratulations. Given Number Successfully Verified."
            android:textColor="@color/black"
            android:textSize="15dp"
            android:textStyle="bold" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:src="@drawable/success" />
    </LinearLayout>
</LinearLayout>

Upvotes: 0

Gunaseelan
Gunaseelan

Reputation: 15535

Instead of having a separate class, you can simply create an instance for BottomSheetDialog in your Activity/Fragment like following and you can use it. It is very easier and simpler I think.

val dialog = BottomSheetDialog(this)
val bottomSheet = layoutInflater.inflate(R.layout.bottom_sheet, null)

bottomSheet.buttonSubmit.setOnClickListener { dialog.dismiss() }
        
dialog.setContentView(bottomSheet)
dialog.show()

Upvotes: 14

Nikola Despotoski
Nikola Despotoski

Reputation: 50578

I was expriencing the same issue, dimmed background and content not visible. Here is how I managed to workaround it by setting the content view in setupDialog() hidden method.

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {

    private TextView mOffsetText;
    private TextView mStateText;
    private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {

        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            setStateText(newState);
            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                dismiss();
            }

        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            setOffsetText(slideOffset);
        }
    };
    private LinearLayoutManager mLinearLayoutManager;
    private ApplicationAdapter mAdapter;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return super.onCreateDialog(savedInstanceState);
    }

    @Override
    public void onViewCreated(View contentView, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(contentView, savedInstanceState);
    }

    @Override
    public void setupDialog(Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        View contentView = View.inflate(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
        dialog.setContentView(contentView);
       mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
        if (mBottomSheetBehavior != null) {
            mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);   
        }
        mOffsetText = (TextView) contentView.findViewById(R.id.offsetText);
        mStateText = (TextView) contentView.findViewById(R.id.stateText);
    }

}

And the layout:

<?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">


    <TextView
        android:id="@+id/offsetText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black" />

    <TextView
        android:id="@+id/stateText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Upvotes: 2

Igor Bubelov
Igor Bubelov

Reputation: 5374

It started to work when I set fixed height for my TextView (200dp), although for some height values it still behaves incorrectly. Obviously it's an issue of support lib. There are already few reports related to BottomSheetDialog in the bug tracker:

https://code.google.com/p/android/issues/detail?id=201793&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened

https://code.google.com/p/android/issues/detail?id=201826

Upvotes: 1

Edward Kimmel
Edward Kimmel

Reputation: 96

Here's the issue on code.google.com https://code.google.com/p/android/issues/detail?id=201793

An issue some users are seeing boils down to the FrameLayout that wraps our content view being centered vertically. The BottomSheetBehavior only works if this view is top aligned. I haven't figured out what causes the FrameLayout to become centered vertically yet, but here's a possible workaround:

View contentView = ...
// You may have to measure your content view first.
dialog.setContentView(contentView);

// Change this to a percentage or a constant, whatever you want to do.
// The default is 1024 - any views smaller than this will be pulled off 
// the bottom of the screen.
float peekHeight = contentView.getMeasuredHeight();

View parent = (View)contentView.getParent();
BottomSheetBehavior behavior = BottomSheetBehavior.from(parent);
behavior.setPeekHeight(peekHeight);
CoordinatorLayout.LayoutParams layoutParams = 
   (CoordinatorLayout.LayoutParams)parent.getLayoutParams();
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;

Upvotes: 2

Angel Devil
Angel Devil

Reputation: 51

This is the layout file of BottomSheetDialog.

<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="match_parent"
    android:soundEffectsEnabled="false">

<FrameLayout
        android:id="@+id/design_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        app:layout_behavior="@string/bottom_sheet_behavior"
        style="?attr/bottomSheetStyle"/>

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

Your content view is inside the view design_bottom_sheet, it will be positioned center vertically by CoordinatorLayout, and BottomSheetBehavior will offset it.

mParentHeight = parent.getHeight();
mMinOffset = Math.max(0, mParentHeight - child.getHeight());
mMaxOffset = mParentHeight - mPeekHeight;
if (mState == STATE_EXPANDED) {
    ViewCompat.offsetTopAndBottom(child, mMinOffset);
} else if (mHideable && mState == STATE_HIDDEN) {
    ViewCompat.offsetTopAndBottom(child, mParentHeight);
} else if (mState == STATE_COLLAPSED) {
    ViewCompat.offsetTopAndBottom(child, mMaxOffset);
}

It intented to positon design_bottom_sheet at mMaxOffset, but actually the initial getTop of the child view is not 0, but (mParentHeight - childHeight) / 2, so you view if offset more than the desired offset.

Find the view design_bottom_sheet and set its gravity to Gravity.TOP | Gravity.CENTER_HORIZONTAL will fix it. But, if the childHeight is less than mPeekHeight, there will be blank area below you content view.

However, if peekHeight > childHeight, the mMaxOffset will less than mMinOffset, which will cause weird behavior.

Maybe the code should be changed to

mMaxOffset = Math.max((mParentHeight - mPeekHeight), mMinOffset);

insted of

mMaxOffset = mParentHeight - child.getHeight();

Upvotes: 4

Related Questions