I have Bottomsheetdialog with Custom view having EditText and on EditText scrolling bottom sheet goes down, How to disable BottomSheetDialog dragging. Any Help Appreciated.
I might be late, but it works fine for me:
#Override
public void setupDialog(final Dialog dialog, int style) {
super.setupDialog(dialog, style);
// This should do the job
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(true);
}
Simple solution, It solved two problem I had.
1- It block the dragging event.
2- It solves the listView scrolling problem
CoordinatorLayout.Behavior<View> behavior;
View profile_config_layout_bottom_sheet = findViewById(R.id.list_view_audience_profile_config_layout);
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) profile_config_layout_bottom_sheet.getLayoutParams();
behavior = layoutParams.getBehavior();
assert behavior != null;
((BottomSheetBehavior<View>) behavior).addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
((BottomSheetBehavior<View>) behavior).setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {}
});
Show the dialog with:
((BottomSheetBehavior) behavior).setState(BottomSheetBehavior.STATE_EXPANDED);
Related
I have a recyclerView and a 'View' in MotionLayout such that the View shows over recyclerView constrained to the bottom of the screen. I have onScrollListener added to the recyclerView such that when I scroll up the RecyclerView, the View hides. The code is like this:
RecyclerView recyclerView;
View v;
#Override
protected void onCreate(Bundle savedInstanceState)
{
//initialise views here
recyclerView.addOnScrollListener(new RecyclerView.onScrollListener(){
#Override
public void onScrolled (RecyclerView recyclerView, int dx, int dy)
{
if(dy > 0)
{
slideDown();
}
else if(dy < 0)
{
slideUp();
}
}
#Override
public void onScrollStateChanged (RecyclerView recyclerView, int newState)
{
}
});
}
public void slideUp()
{
v.clearAnimation();
ObjectAnimator.ofFloat(v, "ScaleY", 1 ).setDuration(200).start(); // to revert back
}
public void slideDown()
{
v.clearAnimation();
ObjectAnimator.ofFloat(v, "ScaleY", -1 ).setDuration(200).start(); //to hide back
}
I don't use BottomNavigationBehaviour here since I can't make it a child of Coordinator layout. I have also specified that View in motionlayout constraints.
Testing:
When I scroll up the recyclerView, the slideDown animation starts only after the recyclerView has stopped scrolling. I don't want this behavoiur. If I change the code in slideDown() to set the View invisible without any animation, the view disappears as soon as I start scrolling; it doesn't wait for the recyclerView to stop.
This behaviour seems strange to me. Is there something I am missing?
I have a two bottom sheets that you can drag from the bottom. You first drag one bottom sheet, then you can drag another on top of it. However if you dismiss one, another one gets dismissed too. I want to be able to dismiss the top sheet first then the bottom one, one by one. I have tried disabling the bottom one but both gets disabled.
OK, I solved the problem. You need to create a custom bottom sheet behavior for this.
Layouts with two bottom sheet :
<FrameLayout
android:id="#+id/first_bottom_sheet_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.xxx.com.CustomBottomSheetBehavior"
app:behavior_hideable="false"
app:behavior_peekHeight="#{model.first_height}">
<FrameLayout
android:id="#+id/first_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:id="#+id/second_bottom_sheet_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.xxx.com.CustomBottomSheetBehavior"
app:behavior_hideable="false"
app:behavior_peekHeight="#{model.second_height}">
<FrameLayout
android:id="#+id/second_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
I added the two fragments that I want to expand from the bottom into the fragment containers of the above layout.
getSupportFragmentManager().beginTransaction()
.add(R.id.first_fragment_container, new FirstFragment())
.commit();
getSupportFragmentManager().beginTransaction()
.add(R.id.second_fragment_container, new SecondFragment())
.commit();
Then I created a custom bottom sheet behavior.
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V>
{
private boolean enableCollapse = true;
public CustomBottomSheetBehavior() {
}
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setEnableCollapse(boolean enableCollapse) {
this.enableCollapse = enableCollapse;
}
#Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (enableCollapse==true) {
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
Now you add callbacks to the above bottom sheets.
FrameLayout firstBottomSheet = activity.findViewById(R.id.first_bottom_sheet_holder);
FrameLayout secondBottomSheet = activity.findViewById(R.id.second_bottom_sheet_holder);
CustomBottomSheetBehavior firstBottomSheetBehavior = (CustomBottomSheetBehavior)BottomSheetBehavior.from(firstBottomSheet);
CustomBottomSheetBehavior secondBottomSheetBehaviour = (CustomBottomSheetBehavior)BottomSheetBehavior.from(secondBottomSheet);
firstBottomSheetBehaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
secondBottomSheetBehaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING||newState==BottomSheetBehavior.STATE_EXPANDED) {
firstBottomSheetBehavior .setEnableCollapse(false);
}else if(newState == BottomSheetBehavior.STATE_COLLAPSED) {
firstBottomSheetBehavior .setEnableCollapse(true);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
All done.
I have a bottom sheet that has inside a listview, I don't want to have the behaviour to expand or to dismiss, I just want to keep it at the fixed size, Now it shows at the size I want (70% of screen) but on slide up or down it changes its state.
Is there a way i can do this?
I have tried:
BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
// dismiss();
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
};
// bottomSheetBehavior.setBottomSheetCallback(bottomSheetCallback);
if (behavior != null && behavior instanceof BottomSheetBehavior) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(bottomSheetCallback);
((BottomSheetBehavior) behavior).setPeekHeight(((RestaurantsActivity) getActivity()).getHeightForFragment());
}
Standard android BottomSheetBehavior has tree state: hidden, collapsed and expanded.
I want to allow user to "leave" bottom sheet between collapsed and expanded. Now, with the default behavior, it will snap to collapsed or expanded based which is closest. How should I disable this snap functionality?
I will present a way to achievie such functionality for a View extending BottomSheetDialogFragment.
Expanding:
First of all overrive onResume:
#Override
public void onResume() {
super.onResume();
addGlobaLayoutListener(getView());
}
private void addGlobaLayoutListener(final View view) {
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
setPeekHeight(v.getMeasuredHeight());
v.removeOnLayoutChangeListener(this);
}
});
}
public void setPeekHeight(int peekHeight) {
BottomSheetBehavior behavior = getBottomSheetBehaviour();
if (behavior == null) {
return;
}
behavior.setPeekHeight(peekHeight);
}
What the code above is supposed to do is just setting the BottomSheet peekHeight to the heigth of the view. The key here is the function getBottomSheetBehaviour(). The implementation is below:
private BottomSheetBehavior getBottomSheetBehaviour() {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) ((View) getView().getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = layoutParams.getBehavior();
if (behavior != null && behavior instanceof BottomSheetBehavior) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
return (BottomSheetBehavior) behavior;
}
return null;
}
This just check if the parent of View has 'CoordinatorLayout.LayoutParams' set. If yes, sets appropriate BottomSheetBehavior.BottomSheetCallback (which is needed in the next part), and more importantly returns the CoordinatorLayout.Behavior, which is supposed to be BottomSheetBehavior.
Collapsing:
Here a [`BottomSheetBehavior.BottomSheetCallback.onSlide (View bottomSheet, float slideOffset)``](https://developer.android.com/reference/android/support/design/widget/BottomSheetBehavior.BottomSheetCallback.html#onSlide(android.view.View, float)) is just exactly what is needed. From the [documentation](https://developer.android.com/reference/android/support/design/widget/BottomSheetBehavior.BottomSheetCallback.html#onSlide(android.view.View, float)):
Offset increases as this bottom sheet is moving upward. From 0 to 1 the sheet is between collapsed and expanded states and from -1 to 0 it is between hidden and collapsed states.
This means, that just checking the second parameter is needed for collapse detection:
define BottomSheetBehavior.BottomSheetCallback in the same class:
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
if (slideOffset < 0) {
dismiss();
}
}
};
I know how to change the height of a Bottom Sheet.
There is no problem to increase the height of a bottom sheet. However I cannot decrease its height with the following code .
bottomSheetBehavior.setPeekHeight(peekHeight); // peekHeight < previous height
bottomSheetBehavior.setState(STATE_COLLAPSED);
Anyone encountered the same problem ?
I am trying to do the same and I don't have such problem. I could easily increase and decrease my BottomSheetDialogFragment height. Here is my code of two methods of my fragment:
private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
};
public static BottomSheetFragment newInstance() {
return new BottomSheetFragment();
}
#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);
CoordinatorLayout.LayoutParams layoutParams = ((CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams());
CoordinatorLayout.Behavior behavior = layoutParams.getBehavior();
if (behavior != null && behavior instanceof BottomSheetBehavior) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(bottomSheetCallback);
((BottomSheetBehavior) behavior).setPeekHeight(getResources().getDimensionPixelSize(R.dimen.bottom_sheet_height) / 4);
}
initRecyclerView(contentView);
}