将BottomSheetDialogFragment的状态设置为展开

use*_*886 66 android android-fragments android-support-library android-support-design

如何使用Android支持设计库(v23.2.1)将片段的状态设置为扩展BottomSheetDialogFragment为扩展BottomSheetBehavior#setState(STATE_EXPANDED)

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

底部工作表首先设置为STATE_COLLAPSED.如果要展开它,请调用BottomSheetBehavior#setState(STATE_EXPANDED).请注意,您无法在视图布局之前调用该方法.

建议的做法需要将第一膨胀的观点,但我不知道我怎么会设置BottomSheetBehaviour到片段(BottomSheetDialogFragment).

View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);  
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);  
Run Code Online (Sandbox Code Playgroud)

efe*_*ney 166

"请注意,您无法在视图布局之前调用该方法."

以上文字是线索.

对话框曾经是对话框被开了听众所示.如果没有布局,则无法显示该对话框.

因此,在onCreateDialog()模态底部工作表(BottomSheetFragment)中,在返回对话框之前(或者在任何地方,只要您对对话框有引用),请调用:

// This listener's onShow is fired when the dialog is shown
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {

        // In a previous life I used this method to get handles to the positive and negative buttons
        // of a dialog in order to change their Typeface. Good ol' days.

        BottomSheetDialog d = (BottomSheetDialog) dialog;

        // This is gotten directly from the source of BottomSheetDialog
        // in the wrapInBottomSheet() method
        FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);

        // Right here!
        BottomSheetBehavior.from(bottomSheet)
            .setState(BottomSheetBehavior.STATE_EXPANDED);
    }
});
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我的习惯BottomSheet结果是:

@SuppressWarnings("ConstantConditions")
public class ShareBottomSheetFragment extends AppCompatDialogFragment {

    @NonNull @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        BottomSheetDialog dialog =
                new BottomSheetDialog(getActivity(), R.style.Haute_Dialog_ShareImage);

        dialog.setContentView(R.layout.dialog_share_image);

        dialog.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;

                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        SwitchCompat switchview = (SwitchCompat) dialog.findViewById(R.id.switchview);
        switchview.setTypeface(FontCache.get(dialog.getContext(), lookup(muli, NORMAL)));

        return dialog;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果这有帮助,请告诉我.

UPDATE

请注意,您还可以覆盖BottomSheetDialogFragment为:

public class SimpleInitiallyExpandedBottomSheetFragment extends BottomSheetDialogFragment {

    @NonNull @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;

                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        // Do something with your dialog like setContentView() or whatever
        return dialog;
    }
}
Run Code Online (Sandbox Code Playgroud)

但我真的不明白为什么有人会这样做,因为基地BottomSheetFragment除了返回之外什么都不做BottomSheetDialog.

更新ANDROIDX

使用AndroidX时,android.support.design.R.id.design_bottom_sheet现在可以在以下位置找到以前找到的资源com.google.android.material.R.id.design_bottom_sheet.

  • 使用AndroidX时,可以在`com.google.android.material.R.id.design_bottom_sheet`找到该资源. (14认同)
  • 更新支持库后,只是我找不到包`android.support.design.R`? (5认同)
  • 我也有解决`android.support.design.R`的问题,就像@natario一样。我正在使用“实施“ com.google.android.material:material:1.0.0”`。我还在项目中使用AndroidX。 (2认同)

goo*_*ode 32

efeturi的答案很棒,但是,如果你想使用onCreateView()创建BottomSheet,而不是使用onCreateDialog(),那么你需要在onCreateView()方法下添加代码:

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    });
    return inflater.inflate(R.layout.your_bottomsheet_content_layout, container, false);
}
Run Code Online (Sandbox Code Playgroud)

  • 或者,您根本不需要调用getDialog.我发现最干净的方法是覆盖onCreateView和onCreateDialog.在onCreateView中构建视图(就像使用任何片段一样)并在onCreateDialog中执行特定于对话框的代码(调用super.onCreateDialog来获取实例) (3认同)
  • 这救了我的一天。谢谢。 (2认同)
  • @Vincent_Paing,是的。在您附加的链接中,它说“不需要实现 onCreateView”。它并没有说它不会被调用。在这里查看源代码https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/bottomsheet/BottomSheetDialogFragment.java。默认实现调用 onCreateDialog 来创建底部工作表,上面的每个解决方案仍然使用 onCreateView 这意味着它们总是被调用。如果您确实覆盖了 super.onCreateDialog(),请确保您仍然调用它。 (2认同)

Yel*_*sov 32

一条线解决方案:

(dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
Run Code Online (Sandbox Code Playgroud)

BottomSheetDialogFragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
Run Code Online (Sandbox Code Playgroud)

或准备好展示时:

private fun onContentLoaded(items: List<Any>) {
    adapter.submitList(items)
    (dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案对我来说非常有效。这是一句简单的话,比之前的所有内容都简单得多。不知道为什么它没有得到更多的支持...... (3认同)

Aja*_*rya 12

在 Kotlin 中,将以下行添加到onStart()您的BottomSheetDialogFragment

(dialog as BottomSheetDialog).behavior.state = BottomSheetBehavior.STATE_EXPANDED
Run Code Online (Sandbox Code Playgroud)


DYS*_*DYS 10

一个简单而优雅的解决方案:

BottomSheetDialogFragment 可以子类化以解决此问题:

class NonCollapsableBottomSheetDialogFragment extends BottomSheetDialogFragment {

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);

    bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);

            BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
            behavior.setSkipCollapsed(true);
            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    });
    return bottomSheetDialog;
}
Run Code Online (Sandbox Code Playgroud)

}

因此,扩展此类而不是BottomSheetDialogFragment创建自己的底页。

注意

更改com.google.android.material.R.id.design_bottom_sheetandroid.support.design.R.id.design_bottom_sheet项目是否使用旧的Android支持库。

  • 现在似乎是“com.google.android.material.R”而不是“android.support.design.R”。 (2认同)

Tin*_* Lu 8

我觉得上面的比较好。可悲的是,我在解决之前没有找到这些解决方案。但是写我的解决方案。非常相似。

================================================== ================================

我面临同样的问题。这就是我解决的。Behavior 隐藏在BottomSheetDialog 中,可以通过它获取行为如果你不想把你的父布局改成CooridateLayout,你可以试试这个。

STEP 1:自定义BottomSheetDialogFragment

open class CBottomSheetDialogFragment : BottomSheetDialogFragment() {
   //wanna get the bottomSheetDialog
   protected lateinit var dialog : BottomSheetDialog 
   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
      dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
      return dialog
   }

   //set the behavior here
   fun setFullScreen(){
      dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
   }
}
Run Code Online (Sandbox Code Playgroud)

STEP 2:让你的片段扩展这个自定义片段

class YourBottomSheetFragment : CBottomSheetDialogFragment(){
    
   //make sure invoke this method after view is built
   //such as after OnActivityCreated(savedInstanceState: Bundle?)
   override fun onStart() {
      super.onStart()
      setFullScreen()//initiated at onActivityCreated(), onStart()
   }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*aňa 5

当显示软键盘时,使用 onShow() 的所有结果都会导致随机渲染错误。请参见下面的屏幕截图 - BottomSheet 对话框不在屏幕底部,而是像显示键盘一样放置。这个问题并不总是发生,但经常发生。

在此输入图像描述

更新

我的解决方案与私人成员的反映是不必要的。使用 postDelayed(大约 100 毫秒)在隐藏软键盘后创建和显示对话框是一个更好的解决方案。那么上面用onShow()的解决方案就可以了。

Utils.hideSoftKeyboard(this);
mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        MyBottomSheetDialog dialog = new MyBottomSheetDialog();
        dialog.setListener(MyActivity.this);
        dialog.show(getSupportFragmentManager(), TAG_BOTTOM_SHEET_DLG);
    }
}, 100);
Run Code Online (Sandbox Code Playgroud)

因此,我实现了另一个解决方案,但它需要使用反射,因为 BottomSheetDialog 将所有成员设为私有。但它解决了渲染错误。BottomSheetDialogFragment 类只是带有 onCreateDialog 方法的 AppCompatDialogFragment,它创建 BottomSheetDialog。我创建了自己的 AppCompatDialogFragment 子级,它创建了我的类扩展 BottomSheetDialog 并解决了对私有行为成员的访问问题,并在 onStart 方法中将其设置为 STATE_EXPANDED 状态。

public class ExpandedBottomSheetDialog extends BottomSheetDialog {

    protected BottomSheetBehavior<FrameLayout> mBehavior;

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

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

        try {
            Field privateField = BottomSheetDialog.class.getDeclaredField("mBehavior");
            privateField.setAccessible(true);
            mBehavior = (BottomSheetBehavior<FrameLayout>) privateField.get(this);
        } catch (NoSuchFieldException e) {
            // do nothing
        } catch (IllegalAccessException e) {
            // do nothing
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mBehavior != null) {
            mBehavior.setSkipCollapsed(true);
            mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    }
}


public class AddAttachmentBottomSheetDialog extends AppCompatDialogFragment {

    ....

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new ExpandedBottomSheetDialog(getContext(), getTheme());
    }

    ....
}
Run Code Online (Sandbox Code Playgroud)


pra*_*eek 5

我的答案与上述大多数答案或多或少相同,但稍作修改。与其使用 findViewById 来首先查找底部工作表视图,我宁愿不硬编码任何框架视图资源 ID,因为它们将来可能会发生变化。

setOnShowListener(dialog -> {
            BottomSheetBehavior bottomSheetBehavior = ((BottomSheetDialog)dialog).getBehavior();
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        });
Run Code Online (Sandbox Code Playgroud)


小智 5

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState).apply {
        setOnShowListener {
            (this@TipsBottomDialogFragment.dialog as BottomSheetDialog).behavior.setState(
                BottomSheetBehavior.STATE_EXPANDED
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


cul*_*ins 5

将其发布给未来的读者,因为我认为现在我们可以使用另一种解决方案。

我试图解决与您描述的相同的问题BottomSheetDialog

我不喜欢使用内部 Android id,我刚刚发现里面有一个方法BottomSheetDialog getBehavior可以使用:

您可以在您的BottomSheetDialog

behavior.state = BottomSheetBehavior.STATE_EXPANDED

使用BottomSheetDialogFragment您可以执行相同的操作,将对话框从 DialogFragment 转换为BottomSheetDialog.


小智 5

您可以执行以下操作(Kotlin 版本):

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.let {
        val sheet = it as BottomSheetDialog
        sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

    // rest of your stuff
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是一个非常简洁的 Kotlin 解决方案,效果很好。

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply {
        setOnShowListener {
           behavior.state = BottomSheetBehavior.STATE_EXPANDED
        }
    }
}
Run Code Online (Sandbox Code Playgroud)