I'm using edge-to-edge in my app. I want to add info window (ViewStub) at the top of the screen. Also i need to apply margin to this window to avoid it drawing on system top panel. I'm using this code:
fun View.applyTopInsetAsMargin() {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
windowInsets
}
}
It's working fine but it's overriding margin to just inset size. In my viewstub i'm setting topMagin to 8 dp because i need to lay it down from status bar and add extra 8 dp margin.
The problem is: when i'm using this extension my 8 dp margin getting overrided so viewstub is only getting top inset size. How can i presave my extra margin and apply it to my view?
val popupBinding = DemoPopupWindowBinding.bind(binding.demoPopupStub.inflate())
popupBinding.root.applyTopInsetAsMargin()
<ViewStub
android:id="#+id/demo_popup_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/horizontal_margin_16"
android:layout_marginTop="#dimen/vertical_margin_8"
android:layout_marginEnd="#dimen/horizontal_margin_16"
android:inflatedId="#+id/demo_popup_window"
android:layout="#layout/demo_popup_window" />
viewstub layout:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/demo_scheme_popup_background"
android:padding="#dimen/padding_8">
...
Related
It seems like the official way, to listen to keyboard height change, is to use WindowInsetsCompat based on https://developer.android.com/develop/ui/views/layout/sw-keyboard
( An unofficial is to have an invisible PopupWindow to monitor keyboard height change. But, this is not a reliable method due to today numerous devices with different notch, split screen mode, ... - Is there any way in Android to get the height of virtual keyboard of device )
We try to experiment, to see how we can monitor keyboard height correctly.
Before applying WindowInsetsCompat
After applying WindowInsetsCompat with the following code.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View keyboardView = findViewById(R.id.keyboard_view);
ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView().getRootView(), (v, insets) -> {
boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
android.util.Log.i("CHEOK", "imeVisible = " + imeVisible + ", imeHeight = " + imeHeight);
ViewGroup.LayoutParams params = keyboardView.getLayoutParams();
params.height = imeHeight;
keyboardView.setLayoutParams(params);
return insets;
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top" />
<LinearLayout
android:id="#+id/bottom_linear_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:background="#22000000">
<ImageButton
android:id="#+id/image_button_0"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/actionBarItemBackground"
android:src="#drawable/ic_baseline_alarm_on_24" />
</LinearLayout>
<View
android:id="#+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#ff0000" />
</LinearLayout>
Outcome of WindowInsetsCompat (When keyboard is not visible)
Outcome of WindowInsetsCompat (When keyboard is visible)
Here's the observation
For testing purpose, we do not use android:windowSoftInputMode="adjustResize".
After applying WindowInsetsCompat, the top status bar and bottom soft key background become white!
The returned keyboard's height isn't correct. (If the keyboard height is correct, we shouldn't see the red color keyboardView, because we have set the height of keyboardView to be same as keyboard's height)
May I know, when using WindowInsetsCompat to monitor keyboard's height, how can I
Avoid status bar and bottom soft key background from becoming white?
Get the correct keyboard's height?
The following is the workable demo - https://github.com/yccheok/wediary-sandbox/tree/master/keyboard-bottom-sheet-integration
Thanks.
Avoid status bar and bottom soft key background from becoming white?
This requires to readjust the insets to WindowInsetsCompatby returning ViewCompat.onApplyWindowInsets(v, insets) instead of insets from the setOnApplyWindowInsetsListener() callback.
Get the correct keyboard's height?
The insets are calculated based on the far ends of the screen (it makes sense as they're named as window insets, not the activity insets).
So, in case of the ime/keyboard we are interested in the bottom inset which equals to the top edge of the keyboard to the bottom edge of the screen; this includes the system navigation insets (i.e., the height of the navigation bar).
The red view is shown because it's drawn on top of the navigation bar; it doesn't take the navBar height into consideration.
So, to get the exact height of the keyboard, we need to subtract the navBarHeight from the imeHeight:
int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
- insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
Please notice the quote of the documentation about ime insets:
When running on devices with API Level 29 and before, the returned
insets are an approximation based on the information available. This
is especially true for the IME type, which currently only works when
running on devices with SDK level 23 and above.
I am facing a specific issue of view background overlay. I did simple example project to show my problem
i have 2 view with the same size. Also both view have background - GradientDrawable with corner radius.
xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="100dp">
<View
android:id="#+id/view_1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View
android:id="#+id/view_2"
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:layout_height="match_parent"/>
</FrameLayout>
And my mainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val view1 = findViewById<View>(R.id.view_1)
val view2 = findViewById<View>(R.id.view_2)
val bg1 = GradientDrawable().apply {
setColor(Color.BLUE)
cornerRadius = 20.toPxF()
}
val bg2 = GradientDrawable().apply {
setColor(Color.RED)
cornerRadius = 20.toPxF()
}
view1.background = bg1
view2.background = bg2
}
}
what i see
full screen full screen
also there are transitions between colors in rounded corners
top
bottom
Actually I don't want to see color changes (colour overlays) in the rounded corners.
How can I achieve this?
UPDATE: i added stroke for second gradient drawable
this and i see that border color smoothed out.
i also try to add stroke for second (red color) view and positioned it directly above the first (blue color) view
click
I want something like that click
bottom bounds have the same coordinates, both views have the same rounding
I could elaborate on this topic for hours, but in short: you want this effect. well, at least on top part of your view. and bottom doesn't look well, but you can add layout_marginBottom to it, right? homework: read about antialiasing
Android ViewGroup has the following methods to add (child) Views:
I know we can easily define horizontal/vertical orientation to LinearLayout in xml/programatically and add child views, eg.
Similarly with RelativeLayout, we can use ViewGroup's addView and RelativeLayout.LayoutParams's method:
I am also aware that we can use LinearLayout as a child inside ConstraintLayout and play with it.
Is there any solid and recommended way to add child views to ConstraintLayout dynamically?
UPDATE:
Let me give a not-so-simple example which I what I want to achieve.
Suppose you have a View1, View2 and View3. All V1, V2 and V3 are aligned vertically one below another and are complex views consisting of multiple TextViews and ImageViews. Based on user action and what server sends information, I need to add multiple V1 and V2 (can be 1 pair of V1-V2 and can be 3 pairs of V1-V2)between original V2 and V3. If I am using ConstraintLayout, would it be best if I add multiple constraints programatically when I can easily use LinearLayout with vertical orientation?
Now, in terms of efficiency, performance and less-and-beautiful-code, is ConstraintLayout best for this requirement as compared to Linear Layout?
Views can be added to ConstraintLayout using addView() in the same way as you would with LinearLayout. The difference is that with ConstraintLayout the added views must be constrained. To constrain a view programmatically, use ConstraintSet.
This class allows you to define programmatically a set of constraints to be used with ConstraintLayout. It lets you create and save constraints, and apply them to an existing ConstraintLayout.
Here is a brief example:
activity_main
Define two TextViews. Center them horizontally and positioned at the top.
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/topView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Top View"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/bottomView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Bottom View"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/topView" />
</android.support.constraint.ConstraintLayout>
This is what you will see when a new TextView ("Middle View") is added to this layout without setting constraints. Notice that the new view defaults to position (0,0).
Let's say that we want the generated middle view to be placed between the top view and the bottom view centered horizontally in the window like this:
Here is the code that will produce this result:
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Define the new TextView and add it to the ConstraintLayout. Without constraints,
// this view will be positioned at (0,0).
TextView middleView = new TextView(this);
middleView.setId(View.generateViewId());
middleView.setText("Middle View");
middleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20.0f);
ConstraintLayout layout = findViewById(R.id.constraintLayout);
ConstraintLayout.LayoutParams lp =
new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT);
layout.addView(middleView, lp);
// Move the new view into place by applying constraints.
ConstraintSet set = new ConstraintSet();
// Get existing constraints. This will be the base for modification.
set.clone(layout);
int topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
16, getResources().getDisplayMetrics());
// Set up the connections for the new view. Constrain its top to the bottom of the top view.
set.connect(middleView.getId(), ConstraintSet.TOP, R.id.topView, ConstraintSet.BOTTOM, topMargin);
// Constrain the top of the bottom view to the bottom of the new view. This will replace
// the constraint from the bottom view to the bottom of the top view.
set.connect(R.id.bottomView, ConstraintSet.TOP, middleView.getId(), ConstraintSet.BOTTOM, topMargin);
// Since views must be constrained vertically and horizontally, establish the horizontal
// constaints such that the new view is centered.
set.centerHorizontally(middleView.getId(),ConstraintSet.PARENT_ID);
// Finally, apply our good work to the layout.
set.applyTo(layout);
}
Let's say that my Bottom Sheet has lines of widgets like the following. If I want to show only the first two lines (i.e., the first two LinearLayouts) initially, but not the rest of the widgets below. I do not want those to be seen initially. How can I set the correct peek height? Hard-coding app:behavior_peekHeight probably would not work, so I would need to set it programatically, but how to calculate the height?
Or is there a more recommended way to get the same result? I mean, if I test Google Maps, long pressing a location first shows only the title part as the bottom sheet, but when I try to scroll up the bottom sheet, it feels as if the title part (which might not have been a real bottom sheet) is replaced by a real bottom sheet that contains all the elements. If my explanation is not enough, please try Google Maps yourself.
<android.support.v4.widget.NestedScrollView
android:id="#+id/bottom_sheet"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView/>
<android.support.v7.widget.AppCompatSpinner/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView/>
<TextView/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView/>
<TextView/>
</LinearLayout>
<android.support.v7.widget.RecyclerView/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
I would solve this by using a ViewTreeObserver.OnGlobalLayoutListener to wait for your bottom sheet to be laid out, and then calling BottomSheetBehavior.setPeekHeight() with the y-coordinate of the first view you don't want to see.
private BottomSheetBehavior<View> behavior;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View bottomSheet = findViewById(R.id.bottomSheet);
behavior = BottomSheetBehavior.from(bottomSheet);
final LinearLayout inner = findViewById(R.id.inner);
inner.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
inner.getViewTreeObserver().removeOnGlobalLayoutListener(this);
View hidden = inner.getChildAt(2);
behavior.setPeekHeight(hidden.getTop());
}
});
}
In this case, my bottom sheet is a NestedScrollView holding a LinearLayout that holds many TextViews. By setting the peek height to be the top of the third TextView (obtained by getChildAt(2)), my bottom sheet winds up showing exactly two TextViews while collapsed.
Customized #Ben P.'s answer to target a view id as a reference of the peekHeight and made a function:
/**
* Gets the bottom part of the target view and sets it as the peek height of the specified #{BottomSheetBehavior}
*
* #param layout - layout of the bottom sheet.
* #param targetViewId - id of the target view. Must be a view inside the 'layout' param.
* #param behavior - bottom sheet behavior recipient.
*/
private fun <T : ViewGroup> getViewBottomHeight(layout: ViewGroup,
targetViewId: Int,
behavior: BottomSheetBehavior<T>) {
layout.apply {
viewTreeObserver.addOnGlobalLayoutListener(
object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
behavior.peekHeight = findViewById<View>(targetViewId).bottom
}
})
}
}
In our use case, we needed to target the bottom part of the view, so we set it that way. It can be adjusted depending on the use-case.
That's smart!
My problem was trying to getTop() or getHeight() at wrong timing, it returns 0 if the view is not ready.
And yes, use viewTreeObserver to avoid that.
This is actually no different with #Ben P.'s previous answer, just a kotlin version:
class MyBottomSheetDialog() : BottomSheetDialogFragment(){
private val binding by viewBinding(SomeLayoutViewBinding::bind)
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(this.dialog as BottomSheetDialog).behavior.let { behavior ->
/* Set "pivotView" as interested target and make it the pivot of peek */
binding.pivotView.viewTreeObserver.addOnGlobalLayoutListener(object :
OnGlobalLayoutListener {
override fun onGlobalLayout() {
binding.pivotView.viewTreeObserver.removeOnGlobalLayoutListener(this)
behavior.peekHeight = binding.pivotView.top
}
})
}
}
}
I have a BottomSheetView which has animateLayoutChanges="true". Initially it shows up fine. But if change the visibility of a view (inside BottomSheetView) from GONE to VISIBLE, the app messes up calculations and my BottomSheetView moves to the top of the screen. i have tried setting layout_gravity=bottom at the root of the BottomSheetView layout. But no success.
Here I have the image of my BottomSheetView before changing the visibility of any view. (Click image for full size)
After I change the visibility of a view (GONE to VISIBLE or VISIBLE to GONE), my BottomSheetView moves to the top. (Click image for full size)
I guess, Android is messing up while making calculations about the measurement of view width and height. Any way to solve this??
I also tried to make my BottomSheetView extend fully to match the parent view, but somehow that is making the height of the BottomSheetView longer than the phone screen and in-tun creating scrolling issues.
Expected solutions:
1> Prevent BottomSheetView from changing its position even when the visibility of a view is changed.
OR
2>Make the BottomSheetView match parent so that it does not look bad after messing up with the calculations.
The BottomSheetBehavior does not work well with LayoutTransition (animateLayoutChanges="true") for now. I will work on a fix.
For now, you can use Transition instead. Something like this will fade the view inside and animate the size of the bottom sheet.
ViewGroup bottomSheet = ...;
View hidingView = ...;
TransitionManager.beginDelayedTransition(bottomSheet);
hidingView.setVisibility(View.GONE);
You can refer to Applying a Transition for more information including how to customize the animation.
I was running into the same issue and determined to find a fix. I was able to find the underlying cause but unfortunately I do not see a great fix at the moment.
The Cause:
The problem occurs between the bottomsheet behavior and the LayoutTransition. When the LayoutTransition is created, it creates a OnLayoutChangeListener on the view so that it can capture its endValues and setup an animator with the proper values. This OnLayoutChangeListener is triggered in the bottomSheetBehavior's onLayout() call when it first calls parent.onLayout(child). The parent will layout the child as it normally would, ignoring any offsets that the behavior would change later. The problem lies here. The values of the view at this point are captured by the OnLayoutChangeListener and stored in the animator. When the animation runs, it will animate to these values, not to where your behavior defines. Unfortunately, the LayoutTransition class does not give us access to the animators to allow updating of the end values.
The Fix:
Currently, I don't see an elegant fix that involves LayoutTransitions. I am going to submit a bug for a way to access and update LayoutTransition animators. For now you can disable any layoutTransition on the parent container using layoutTransition.setAnimateParentHierarchy(false). Then you can animate the change yourself. I'll update my answer with a working example as soon as I can.
The question was asked more than two years ago, but unfortunately the problem persists.
I finally got a solution to keep the call to the addView and removeView functions in a BottomSheet, while having animateLayoutChanges="true".
BottomSheetBehavior cannot calculate the correct height when it changes, so the height must remain the same. To do this, I set the height of the BottomSheet to match_parent and divide it into two children: the content and a Space that changes height according to the height of the content.
To best mimic the true behavior of a BottomSheet, you also need to add a TouchToDismiss view that darkens the background when the BottomSheet is extended but also to close the BottomSheet when the user presses outside the content.
Here's the code:
activity.xml
<androidx.coordinatorlayout.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/show_bottom_sheet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show bottom sheet"/>
<View
android:id="#+id/touch_to_dismiss"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:background="#9000"/>
<LinearLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<Space
android:id="#+id/space"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:id="#+id/bottom_sheet_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true">
<Button
android:id="#+id/add_or_remove_another_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add another view"/>
<TextView
android:id="#+id/another_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Another view"/>
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
activity.java
BottomSheetBehavior bottomSheetBehavior;
View touchToDismiss;
LinearLayout bottomSheet;
Button showBottomSheet;
Space space;
LinearLayout bottomSheetContent;
Button addOrRemoveAnotherView;
TextView anotherView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
touchToDismiss = findViewById(R.id.touch_to_dismiss);
touchToDismiss.setVisibility(View.GONE);
touchToDismiss.setOnClickListener(this);
bottomSheet = findViewById(R.id.bottom_sheet);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setPeekHeight(0);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN || newState == BottomSheetBehavior.STATE_COLLAPSED) {
touchToDismiss.setVisibility(View.GONE);
}else {
touchToDismiss.setVisibility(View.VISIBLE);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
touchToDismiss.setAlpha(getRealOffset());
}
});
showBottomSheet = findViewById(R.id.show_bottom_sheet);
showBottomSheet.setOnClickListener(this);
space = findViewById(R.id.space);
bottomSheetContent = findViewById(R.id.bottom_sheet_content);
addOrRemoveAnotherView = findViewById(R.id.add_or_remove_another_view);
addOrRemoveAnotherView.setOnClickListener(this);
anotherView = findViewById(R.id.another_view);
bottomSheetContent.removeView(anotherView);
}
#Override
public void onClick(View v) {
if (v == showBottomSheet)
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
else if (v == addOrRemoveAnotherView) {
if (anotherView.getParent() == null)
bottomSheetContent.addView(anotherView);
else
bottomSheetContent.removeView(anotherView);
}
else if (v == touchToDismiss)
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
/**
* Since the height does not change and remains at match_parent, it is required to calculate the true offset.
* #return Real offset of the BottomSheet content.
*/
public float getRealOffset() {
float num = (space.getHeight() + bottomSheetContent.getHeight()) - (bottomSheet.getY() + space.getHeight());
float den = bottomSheetContent.getHeight();
return (num / den);
}
This is the result obtained with this code:
Hopefully it will be useful to someone since the problem is still there!
I use this and I got to keep the animations!
val transition = LayoutTransition()
transition.setAnimateParentHierarchy(false)
{Parent View which has animateLayoutChanges="true" }.layoutTransition = transition
In the BottomSheetDialog default layout (design_bottom_sheet_dialog) there is a TOP gravity on the dialog's design_bottom_sheet FrameLayout:
android:layout_gravity="center_horizontal|top"
I don't really know why on BottomSheetDialog gravity is top.
You need to create the same layout file (same content and name) in your project and replace this line with:
android:layout_gravity="center_horizontal|bottom"
In our case, we were displaying a progress bar on a button component. This was hiding the button text and displaying progress bar. This was causing a jump in bottom sheet fragment. Using Invisible instead of Gone fixed the problem.
If your view allows, make the visibility INVISIBLE instead of GONE.