Bottom Sheet Dialog jumps up after populating RecyclerView
Asked Answered
G

3

9

I have run into a peculiar issue. The flow of the app is as below:

  1. Trigger bottom sheet dialog.
  2. The dialog fragment makes an api call to the server.
  3. A spinner is displayed while waiting for the response
  4. When response is received, the Recycler view along with with some TextViews is populated.
  5. As soon as the Recycler View is updated, the dialog jumps up from bottom, and is no longer attached to the base. However, if we scroll the Recycler View, the returns to the normal position.

Actual

Current Behaviour

Expected

Expected

Bottom Sheet Dialog Relevant Code:

        //We have to override this method to ensure that the Bottom Sheet opens in expanded mode.
        @NonNull
        @Override
        public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {

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

            dialog.setOnShowListener(dialog1 -> {
                BottomSheetDialog d = (BottomSheetDialog) dialog1;

                FrameLayout bottomSheet = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
                BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
            });

            return dialog;
        }

@Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        views.layoutCartItem.setLayoutManager(new LinearLayoutManager(getContext()));
        views.layoutCartItem.setItemAnimator(new DefaultItemAnimator());
    viewModel.getOrderConfirmation().observe(this, res -> {
                if(res.isSuccess()){
                    views.loader.setVisibility(View.GONE);
                    views.layoutImage.setVisibility(View.VISIBLE);
                    showViews(res.value);
                } else if(res.isError()) {
                    views.loader.setVisibility(View.GONE);
                } else {
                    views.loader.setVisibility(View.VISIBLE);
                    views.layoutImage.setVisibility(View.GONE);
                }
            });
    }

    private void showViews(CartOrderSummary summary){
            this.orderSummary = summary;
            showItems(summary.items, summary.currency);
            views.txtName.setText(summary.name);
            views.txtCuisine.setText(summary.cuisineType);
            setTypeIcon(summary.type);
            views.txtAddress.setText(summary.address);

            views.txtItemCount.setText(summary.itemCount + " ITEMS");
            views.txtTax.setText(String.format("%.2f",  summary.tax));
            views.txtTip.setText(String.format("%.2f",  0f));
            views.txtDiscount.setText(String.format("%.2f",  (summary.total - summary.subTotal)));
            views.txtCartTotal.setText(String.format("%.2f",  summary.total));

            views.btShowOnMap.setOnClickListener(v->showMap(summary));


        }

The layout

<layout 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">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="525dp"
        android:minHeight="525dp"
        android:theme="@style/AppTheme">


        <TextView
            android:id="@+id/txtTitle"
            android:layout_width="0dp"
            android:layout_height="22dp"
            android:layout_marginStart="12dp"
            android:layout_marginTop="12dp"
            android:layout_marginEnd="12dp"
            android:fontFamily="@font/avenir_next_lt_pro_regular"
            android:text="Order Confirmation"
            android:textColor="#000000"
            android:textSize="18sp"
            app:layout_constraintEnd_toStartOf="@+id/button_close_drawer"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />


        <TextView
            android:id="@+id/txtCaption"
            android:layout_width="0dp"
            android:layout_height="14dp"
            android:layout_marginStart="12dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="12dp"
            android:fontFamily="@font/avenir_next_lt_pro_regular"
            android:text="Dear customer, please confirm the order."
            android:textColor="@color/grey_40"
            android:textSize="12sp"
            app:layout_constraintEnd_toStartOf="@+id/button_close_drawer"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtTitle" />

        <ImageButton
            android:id="@+id/button_close_drawer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:contentDescription="@string/add_address"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_close_black_24dp" />



        <View
            android:id="@+id/title_divider"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:layout_marginTop="14dp"
            android:background="#FFDADADA"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtCaption" />

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/title_divider"
            app:layout_constraintBottom_toTopOf="@id/btPay"
            >


            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/layoutImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:elevation="9dp"
                android:paddingTop="5dp"
                >
                <androidx.constraintlayout.widget.Guideline
                    android:id="@+id/start"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    app:layout_constraintGuide_begin="12dp" />

                <androidx.constraintlayout.widget.Guideline
                    android:id="@+id/end"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    app:layout_constraintGuide_end="12dp" />



                <TextView
                    android:id="@+id/txtName"
                    android:layout_width="0dp"
                    android:layout_height="24dp"
                    android:layout_marginTop="6dp"
                    android:layout_marginEnd="12dp"
                    android:textColor="@color/black"
                    android:textSize="20sp"
                    android:transitionName="NAME"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="@id/start"
                    app:layout_constraintTop_toTopOf="parent"
                    tools:text="Las Iguanas" />
                <ImageView
                    android:id="@+id/imgType"
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:layout_marginEnd="2dp"
                    app:layout_constraintEnd_toStartOf="@+id/txtType"
                    app:layout_constraintTop_toTopOf="@+id/txtType"
                    app:srcCompat="@drawable/ic_type_cafe" />

                <TextView
                    android:id="@+id/txtType"
                    android:layout_width="wrap_content"
                    android:layout_height="16dp"
                    android:layout_marginEnd="12dp"
                    android:layout_marginTop="14dp"
                    android:fontFamily="@font/avenir_next_lt_pro_bold"
                    android:gravity="bottom"
                    android:lineHeight='18dp'
                    android:textSize="12sp"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    tools:text="Cafe" />
                <TextView
                    android:id="@+id/txtCuisine"
                    android:layout_width="0dp"
                    android:layout_height="20dp"
                    android:layout_marginTop="2dp"
                    android:layout_marginEnd="12dp"
                    android:textColor="@color/black"
                    android:textSize="14sp"
                    android:transitionName="CUISINE"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="@id/start"
                    app:layout_constraintTop_toBottomOf="@id/txtName"
                    tools:text="Tex-Mex, Spicy Veggie" />


                <View
                    android:id="@+id/dividerTitle"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_marginTop="17dp"
                    android:background="@color/grey"
                    app:layout_constraintTop_toBottomOf="@id/txtCuisine" />


                <ImageView
                    android:id="@+id/imgLocationPin"
                    android:layout_width="20dp"
                    android:layout_height="20dp"
                    android:layout_marginTop="9dp"
                    android:src="@drawable/ic_location_pin"
                    app:layout_constraintStart_toStartOf="@id/start"
                    app:layout_constraintTop_toBottomOf="@id/dividerTitle" />

                <TextView
                    android:id="@+id/txtAddress"
                    android:layout_width="0dp"
                    android:layout_height="36dp"
                    android:layout_marginStart="4dp"
                    android:layout_marginTop="10dp"
                    android:layout_marginEnd="4dp"
                    android:maxLines="2"
                    android:minLines="2"
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    app:layout_constraintEnd_toStartOf="@id/btShowOnMap"
                    app:layout_constraintStart_toEndOf="@id/imgLocationPin"
                    app:layout_constraintTop_toBottomOf="@id/dividerTitle"
                    tools:text="3253 Delawae Avenue, San\n Francisco, CA- California, 94107" />


                <com.google.android.material.button.MaterialButton
                    android:id="@+id/btShowOnMap"
                    style="@style/Widget.MaterialComponents.Button.TextButton"
                    android:layout_width="wrap_content"
                    android:layout_height="20dp"
                    android:layout_marginTop="10dp"
                    android:includeFontPadding="false"
                    android:insetTop="0dp"
                    android:insetBottom="0dp"
                    android:text="Show on Map"
                    android:textAlignment="viewEnd"
                    android:textAllCaps="false"
                    android:textColor="@color/pinkishOrange"
                    android:textSize="12sp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/dividerTitle" />


                <View
                    android:id="@+id/dividerAddress"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_marginTop="15dp"
                    android:background="@color/grey"
                    app:layout_constraintTop_toBottomOf="@id/txtAddress" />


                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/layoutCartItem"
                    android:layout_width="0dp"
                    android:layout_height="300dp"
                    android:orientation="vertical"
                    app:layout_constraintStart_toStartOf="@id/start"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/dividerAddress"
                    >
                </androidx.recyclerview.widget.RecyclerView>
                <View
                    android:id="@+id/dividerItemList"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_marginTop="15dp"
                    android:background="@color/grey"
                    app:layout_constraintTop_toBottomOf="@id/layoutCartItem" />

                <TextView
                    android:id="@+id/txtItemCount"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/dividerItemList"
                    android:layout_marginTop="20dp"
                    tools:text="10 items"
                    android:textColor="@color/black"
                    android:textSize="10sp"
                    />

                <TextView
                    android:id="@+id/txtTip"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/txtItemCount"
                    android:layout_marginTop="6dp"
                    tools:text="10 items"
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />

                <TextView
                    android:id="@+id/txtTipLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toStartOf="@id/txtTip"
                    app:layout_constraintTop_toTopOf="@id/txtTip"
                    app:layout_constraintBottom_toBottomOf="@id/txtTip"

                    android:text="Tip: "
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />

                <TextView
                    android:id="@+id/txtTax"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/txtTip"
                    android:layout_marginTop="6dp"
                    tools:text="10 items"
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />

                <TextView
                    android:id="@+id/txtTaxLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toStartOf="@id/txtTax"
                    app:layout_constraintTop_toTopOf="@id/txtTax"
                    app:layout_constraintBottom_toBottomOf="@id/txtTax"
                    android:text="Tax: "
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />


                <TextView
                    android:id="@+id/txtDiscount"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/txtTax"
                    android:layout_marginTop="6dp"
                    tools:text="10 items"
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />

                <TextView
                    android:id="@+id/txtDiscountLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="12dp"
                    app:layout_constraintEnd_toStartOf="@id/txtDiscount"
                    app:layout_constraintTop_toTopOf="@id/txtDiscount"
                    app:layout_constraintBottom_toBottomOf="@id/txtDiscount"
                    android:text="Discount: "
                    android:textColor="@color/black"
                    android:textSize="12sp"
                    />

                <TextView
                    android:id="@+id/txtCartTotal"
                    android:layout_width="wrap_content"
                    android:layout_height="20dp"
                    app:layout_constraintEnd_toEndOf="@id/end"
                    app:layout_constraintTop_toBottomOf="@id/txtDiscount"
                    app:layout_constraintBottom_toBottomOf="parent"
                    android:layout_marginTop="14dp"
                    tools:text="10 items"
                    android:textColor="@color/black"
                    android:layout_marginBottom="24dp"
                    android:textSize="16sp"
                    />

                <TextView
                    android:id="@+id/txtCartTotalLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="20dp"
                    app:layout_constraintEnd_toStartOf="@id/txtCartTotal"
                    app:layout_constraintTop_toTopOf="@id/txtCartTotal"
                    app:layout_constraintBottom_toBottomOf="@id/txtCartTotal"
                    android:text="Total Due: "
                    android:textColor="@color/black"
                    android:textSize="16sp"
                    />


            </androidx.constraintlayout.widget.ConstraintLayout>

        </androidx.core.widget.NestedScrollView>

        <ProgressBar
            android:visibility="gone"
            android:id="@+id/loader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/title_divider"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toTopOf="@id/btPay"

            />
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="12dp"
            android:src="@drawable/shadow_top"
            app:layout_constraintBottom_toTopOf="@id/btPay"
            android:layout_marginBottom="12dp"
            android:elevation="30dp"
            />
        <View
            android:layout_width="match_parent"
            android:layout_height="64dp"
            android:background="@color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            />
        <com.google.android.material.button.MaterialButton
            android:id="@+id/btPay"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginStart="10dp"
            android:layout_marginTop="12dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="12dp"
            android:backgroundTint="@color/grass"
            android:enabled="true"
            android:gravity="center"
            android:insetTop="0dp"
            android:insetBottom="0dp"
            android:paddingRight="4dp"
            android:text="Pay"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="16sp"
            android:elevation="30dp"
            app:layout_constraintBottom_toBottomOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Genteel answered 20/4, 2020 at 12:1 Comment(6)
wrap your ConstraintLayout in FrameLayout and add this to the ConstraintLayout android:layout_gravity="bottom". Try this.Romanism
Extra nesting seems like a band-aid solution. It defeats the very purpose of ConstraintLayout. Any idea why the above case is happening?Genteel
FYI, wrapping didn't work.Genteel
have you defined the peek height of the bottomsheet?Taskwork
@WahdatKashmiri I did try it with and without peek height. Adding items to RecyclerView after BottomSheetDialog has been added to the view makes it jump up. If the BottomSheetDialog is loaded from cached data, it doesn't jump. Its just weird.Genteel
Hi @Puneet, did something fix this issue for you?Remembrancer
D
2

It worked for me by changing View.GONE to View.INVISIBLE, and removing android:animateLayoutChanges="true". if that does not work try using BottomSheetDialogFragment

Darrelldarrelle answered 4/8, 2021 at 14:12 Comment(0)
G
1

For me it only occured when i set android:animateLayoutChanges="true" to my root layout.

Guru answered 29/6, 2022 at 12:8 Comment(1)
Also I wanted to add here, if you are using custom views and the root layout of them has android:animateLayoutChanges="true" included, you need to remove it as well.Legra
S
0

after some digging, i found this and this answer may related to your problem.

based from Jimmy Macaraeg answer, try change View.Gone to View.INVISIBLE, Since the View.GONE has no size, the bottom sheet can't compute the height of the child being updated.

another possible solution i can think of :

  1. close bottomsheet when data not present, otherwise expand it
  2. use Viewswitcher to changing layout from one to another instead using if else view visibility
Sarcophagus answered 23/6, 2020 at 16:25 Comment(1)
View.Gone shouldn't matter as the parent element of the BottomSheet has a fixed height, i.e. 525DP. Nevertheless, I changed it to View.Gone and the behavior remained unchanged. Viewswitcher is not feasible here as the switch can be between more than 2 views. The problem seems be rooted in RecyclerView getting updated after the BottomSheetFragment has been loaded. As soon as I populate ReryclerView, it jumps. IF I don't update RecyclerView irrespective of the View.Gone/View.Visible/View.Invisible, it works just fine.Genteel

© 2022 - 2024 — McMap. All rights reserved.