web-dev-qa-db-fra.com

Android BottomSheetDialogFragment ne se développe pas complètement

J'ai l'implémentation de feuille de fond de test suivante.

Lorsque j'ai défini peekHeight sur une valeur inférieure à 500, cela fonctionne. Après une certaine valeur, toute augmentation de la hauteur de l'aperçu ne changera pas la façon dont la feuille inférieure est développée. Il reste juste là pour ne faire glisser que manuellement. Comment définissons-nous le peekHeight par programme pour garantir que la feuille inférieure est automatiquement développée à la hauteur de l'aperçu.

enter image description here

bottom_sheet_dialog_main

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/locUXCoordinatorLayout"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

    <LinearLayout
        Android:id="@+id/locUXView"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:fitsSystemWindows="true"
        Android:orientation="vertical"
        app:behavior_hideable="false"
        app:behavior_peekHeight="0dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="1 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="2 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="3 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="4 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="5 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="6 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="7 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="8 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="9 Value" />

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="100dp"
            Android:text="First Value" />
    </LinearLayout>
</Android.support.design.widget.CoordinatorLayout>

Code Java

public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {

    private static BottomSheetBehavior bottomSheetBehavior;
    private static View bottomSheetInternal;
    private static MyBottomSheetDialogFragment INSTANCE;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;
                CoordinatorLayout coordinatorLayout = (CoordinatorLayout)d.findViewById(R.id.locUXCoordinatorLayout);
                bottomSheetInternal = d.findViewById(R.id.locUXView);
                bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal);
                bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight());
                bottomSheetInternal.requestLayout();
                coordinatorLayout.getLayoutParams().height = bottomSheetInternal.getHeight();
                Toast.makeText(getActivity(), "Height is" + bottomSheetInternal.getHeight() + "  " + coordinatorLayout.getLayoutParams().height, Toast.LENGTH_LONG).show();

            }
        });
        INSTANCE = this;
        return inflater.inflate(R.layout.bottom_sheet_dialog_main, container, false);
    }
}
17
Nandish A

Par une inspection plus approfondie de l'interface utilisateur, nous constatons qu'il existe un autre CoordinatorLayout qui enveloppe notre disposition de coordinateur. Le parent CoordinatorLayout a un FrameLayout avec un BottomSheetBehavior avec l'id design_bottom_sheet. La hauteur d'aperçu définie à partir de notre code ci-dessus devenait contrainte en raison de match_parent hauteur du FrameLayout avec l'id design_bottom_sheet

En définissant la hauteur de l'aperçu de FrameLayout avec l'id design_bottom_sheet, ce problème a été résolu

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            coordinatorLayout = (CoordinatorLayout) d.findViewById(R.id.locUXCoordinatorLayout);
            bottomSheetInternal = d.findViewById(R.id.locUXView);
            bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal);
            bottomSheetBehavior.setHidable(false);
            BottomSheetBehavior.from((View)coordinatorLayout.getParent()).setPeekHeight(bottomSheetInternal.getHeight());
            bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight());
            coordinatorLayout.getParent().requestLayout();

        }
    });
8
Nandish A

Utilisation de ce code dans onCreateView.

getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.design_bottom_sheet);
            CoordinatorLayout coordinatorLayout = (CoordinatorLayout) bottomSheet.getParent();
            BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
            bottomSheetBehavior.setPeekHeight(bottomSheet.getHeight());
            coordinatorLayout.getParent().requestLayout();
        }
    });
23
athysirus

J'ai trouvé une autre solution. Peut-être que pour les futurs lecteurs, cela peut être utile.

@Override
public void setupDialog(Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    final View root = View.inflate(getContext(), R.layout.fragment_bottom_sheet_choose_time, null);
    dialog.setContentView(root);
    initView(root);

    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) root.getParent()).getLayoutParams();
    CoordinatorLayout.Behavior behavior = params.getBehavior();

    if (behavior != null && behavior instanceof BottomSheetBehavior) {
        mBottomSheetBehavior = (BottomSheetBehavior) behavior;
        mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);

        root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                int height = root.getMeasuredHeight();
                mBottomSheetBehavior.setPeekHeight(height);
            }
        });
    }
}

Comme @Anthonyeef l'a mentionné, ici ViewTreeObserver vise à obtenir la hauteur de mesure exacte après que la vue est vraiment mesurée et que GlobalOnLayoutListener est supprimé pour de meilleures performances.

Mais s'il vous plaît, avant de l'utiliser en production, testez cette solution sur différents appareils et écrans, car si votre contenu dans la feuille inférieure est plus élevé que votre écran, il peut produire un comportement de balayage étrange.

18

Merci @athysirus pour l'approche soignée. Voici la version avec laquelle je me suis retrouvé, au cas où quelqu'un voudrait avoir un échantillon de kotlin fonctionnel.

Il est important de noter que vous devez également supprimer l'écouteur de disposition globale, une fois terminé.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val bottomSheet = (dialog as BottomSheetDialog).findViewById<View>(com.google.Android.material.R.id.design_bottom_sheet)
            BottomSheetBehavior.from<View>(bottomSheet).apply {
                state = BottomSheetBehavior.STATE_EXPANDED
                peekHeight = 0
            }
            view.viewTreeObserver.removeOnGlobalLayoutListener(this)
        }
    })
1
Mike T