如何使用BottomSheetDialog?

时间:2016-02-25 03:07:11

标签: android android-support-library

我想尝试在Android支持库 23.2 中引入 BottomSheetDialog ,但它似乎无法正常工作。以下是该文档所说的内容:

  

当BottomSheetBehavior捕获持久性底部工作表案例时,此版本还提供了BottomSheetDialog和   BottomSheetDialogFragment填充模态底部工作表用例。   只需将AppCompatDialog或AppCompatDialogFragment替换为它们即可   底部工作表相当于将对话框设置为底部   片材。

所以我将AppCompatDialog更改为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));
    }
}

这是我的布局文件:

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

然后我在我的Activity中使用以下代码:

new AccountActionsDialog(this).show();

我的屏幕变暗,但我的对话框内容不可见。有什么可能遗漏的想法?当我使用 AppCompatDialog 时,它可以正常工作。

5 个答案:

答案 0 :(得分:2)

这是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>

您的内容视图位于视图design_bottom_sheet内,它将被CoordinatorLayout垂直定位,而BottomSheetBehavior将偏移它。

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);
}

它意图在design_bottom_sheet处定位mMaxOffset,但实际上子视图的初始getTop不是0,而是(mParentHeight - childHeight) / 2,因此您可以查看偏移量是否大于所需的偏移量。

查看视图design_bottom_sheet并将其重力设置为Gravity.TOP | Gravity.CENTER_HORIZONTAL即可解决问题。但是,如果childHeight小于mPeekHeight,则内容视图下方会有空白区域。

但是,如果peekHeight > childHeight,则mMaxOffset将小于mMinOffset,这将导致奇怪的行为。

也许代码应该改为

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

insted of

mMaxOffset = mParentHeight - child.getHeight();

答案 1 :(得分:2)

我遇到了同样的问题,背景和内容变得模糊不清。以下是我通过在setupDialog()隐藏方法中设置内容视图来设法解决此问题的方法。

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);
    }

}

布局:

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

答案 2 :(得分:2)

以下是code.google.com https://code.google.com/p/android/issues/detail?id=201793

上的问题

一些用户看到的问题归结为FrameLayout,它将我们的内容视图包装为垂直居中。仅当此视图顶部对齐时,BottomSheetBehavior才有效。我还没弄清楚导致FrameLayout垂直居中的原因,但这可能是一种解决方法:

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;

答案 3 :(得分:1)

当我为TextView(200dp)设置固定高度时,它开始工作,虽然对于某些高度值,它仍然表现不正确。显然这是一个支持lib的问题。在bug跟踪器中已经很少有与BottomSheetDialog相关的报告:

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

答案 4 :(得分:0)

除了拥有一个单独的类,您还可以像下面的操作一样在Activity / Fragment中为BottomSheetDialog创建一个实例,然后就可以使用它了。我认为这非常容易和简单。

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

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

dialog.setContentView(bottomSheet)
dialog.show()

有关简短的教程,您可以参考here