I working with BottomSheetDialog and i have to get Behavior so can set setBottomSheetCallback() to handle some stuff.
As google says i had to put Coordinator on parentView and add behavior to it. I defined CoordinatorLayout in MainActivity (root activity) like this:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:tag="coordinatorLayout"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
...
This is try to get from activity:
public void setupDialog(final Dialog dialog, int style) {
CoordinatorLayout coordinatorLayout = getActivity().getWindow().getDecorView();
BottomSheetBehavior behavior = BottomSheetBehavior.from(coordinatorLayout);
I also tried:
CoordinatorLayout coordinatorLayout = getActivity().getWindow().getDecorView().findViewById(R.id.coordinatorLayout);
//this is point to the coordinatorView
BottomSheetBehavior behavior = BottomSheetBehavior.from(coordinatorLayout);
//But this returns same error that "The view is not a child of CoordinatorLayout"
As you see i passed the coordinator-layout but method can not find behavior in it. I also should mention to points in using BottonSheetDialog:
Any way i could not get behavior of CoordinatorLayout of parent. In my bottonSheetDialog i try these methods and non of them works and i get "The view is not a child of CoordinatorLayout" error.
code for point 1:
MyFragment myFragment= MyFragment.getInstance(bundle);
myFragment.show(fragment.getChildFragmentManager(),"tag");
code for point 2:
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_bottomsheet, null, false);
return rootView;
}
BottomSheetDialog
is a rather peculiar Dialog
implementation. It is not added to, nor does it rely on*, a CoordinatorLayout
in your Activity
's layout. It sets up its own CoordinatorLayout
internally, and within that, a FrameLayout
with BottomSheetBehavior
, into which your View
is placed. The BottomSheetDialog
itself fills the whole screen, and has a transparent background, so that it can handle the bottom sheet interaction, and any outside touches.
If you need access to that bottom sheet and its BottomSheetBehavior
, we'll need to get it from the Dialog
's View
hierarchy. That's as simple as calling findViewById(R.id.design_bottom_sheet)
on the Dialog
, but we'll need to wait until the Dialog
is shown to modify the BottomSheetBehavior
. Furthermore, since BottomSheetDialog
sets its own BottomSheetCallback
, we must ensure that we replace it appropriately. That is, we must take care of cancelling the Dialog
when it hits the closed state. For example:
final BottomSheetDialog bsd = new BottomSheetDialog(MainActivity.this);
bsd.setContentView(R.layout.your_dialog_layout);
bsd.show();
FrameLayout bottomSheet = (FrameLayout) bsd.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(View bottomSheet, int newState) {
// This is the crucial bit.
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
bsd.cancel();
}
}
@Override
public void onSlide(View bottomSheet, float slideOffset) {}
}
);
If you're using a BottomSheetDialogFragment
, the Dialog
is shown in DialogFragment
's onStart()
, and we can override that method to do our modifications there, after the super
call. For example:
public class MyFragment extends BottomSheetDialogFragment {
public MyFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.your_dialog_layout, container, false);
}
@Override
public void onStart() {
super.onStart();
FrameLayout bottomSheet = getDialog().findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(View bottomSheet, int newState) {
// This is the crucial bit.
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
getDialog().cancel();
}
}
@Override
public void onSlide(View bottomSheet, float slideOffset) {}
}
);
}
}
In either case, you can do pretty much whatever you want in the BottomSheetCallback
, as long as you cancel()
the Dialog
in onStateChanged()
when newState == BottomSheetBehavior.STATE_HIDDEN
.
*Incidentally, this means that you do not have to have a CoordinatorLayout
in your Activity
'a layout to use BottomSheetDialog
or BottomSheetDialogFragment
, though I'm not sure that's made clear anywhere in the documentation or other developer resources.