问题
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:
- I show my BottonSheetFragments like this:
- I inflated my BottomSheetDialog in OnCreateView (not in setupDialog()) for ability of adding View Pager inside. As you may know ViewPager wont attach to BottonSheetDialog if you inflate view in onSetupDialog().
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;
}
回答1:
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.
回答2:
in your CoordinatorLayout you have child that have this app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
so you need to make BottomSheetBehavior behavior = BottomSheetBehavior.from(your CoordinatorLayout child);
And on it you need to make setBottomSheetCallback.
behavior.setBottomSheetCallback(...)
来源:https://stackoverflow.com/questions/53360648/bottomsheetdialog-get-behavour-always-returns-null