10 votes

Android "Top Sheet" équivalent à "Bottom Sheet" ?

Je souhaite mettre en œuvre une mise en page de type "Feuille inférieure", mais avec une particularité : la feuille "inférieure" sera un MapFragment, qui ne fonctionnera pas très bien en tant que vue glissante haut/bas.

J'ai eu l'idée, probablement naïve, d'inverser la logique en adoptant une conception de type "feuille supérieure", où l'on fait glisser la feuille supérieure vers le haut ou vers le bas pour afficher plus ou moins le MapFragment inférieur.

ie : A partir de ce...
Bottom Sheet Example

...à [quelque chose comme] ceci...
Top Sheet Example

Est-ce possible avec les outils de conception de l'assistance, ou vais-je devoir mettre au point quelque chose de ce genre par moi-même ?

2voto

swooby Points 437

Voici la base de ma solution que j'ai commentée plus haut. Je reviendrai plus tard pour l'étoffer.

@Override
protected void onCreate(
        @Nullable
                Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    if (isFinishing())
    {
        return;
    }

    setContentView(R.layout.activity_home);

    ...

    mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);

    final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
    mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
    mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
    {
        @Override
        public void onStateChanged(
                @NonNull
                        View bottomSheet,
                int newState)
        {
            //Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
            //             bottomSheetBehaviorStateToString(newState) + ')');
            int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
            mImageBottomSheetMapClose.setVisibility(visibility);
        }

        @Override
        public void onSlide(
                @NonNull
                        View bottomSheet,
                float slideOffset)
        {
            //Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
            resizeMap();
        }
    });
    bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
    {
        @Override
        public void onGlobalLayout()
        {
            //Log.e(TAG, "onGlobalLayout()");
            bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            resizeMap();
        }
    });

    ...
}

private void resizeMap()
{
    int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
    //Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);

    int[] location = new int[2];
    mGroupMap.getLocationInWindow(location);
    //Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));

    LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
    groupMapLayoutParams.height = screenHeightPixels - location[1];
    mGroupMap.requestLayout();
}

public static String bottomSheetBehaviorStateToString(int state)
{
    String s;
    switch (state)
    {
        case BottomSheetBehavior.STATE_COLLAPSED:
            s = "STATE_COLLAPSED";
            break;
        case BottomSheetBehavior.STATE_DRAGGING:
            s = "STATE_DRAGGING";
            break;
        case BottomSheetBehavior.STATE_EXPANDED:
            s = "STATE_EXPANDED";
            break;
        case BottomSheetBehavior.STATE_HIDDEN:
            s = "STATE_HIDDEN";
            break;
        case BottomSheetBehavior.STATE_SETTLING:
            s = "STATE_SETTLING";
            break;
        default:
            s = "UNKNOWN";
            break;
    }
    return s + '(' + state + ')';
}

private static boolean isBottomSheetExpanded(
        @NonNull
                BottomSheetBehavior bottomSheetBehavior)
{
    return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}

private void bottomSheetMapExpand()
{
    mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
    int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
    mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
    mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    mBottomSheetMapBehavior.setHideable(false);
}

private void bottomSheetMapCollapse()
{
    mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
    int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
    mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
    mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
    mBottomSheetMapBehavior.setHideable(false);
}

private void bottomSheetMapHide()
{
    mBottomSheetMapBehavior.setHideable(true);
    mBottomSheetMapBehavior.setPeekHeight(0);
    mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
    mGroupBottomSheetFiller.setVisibility(View.GONE);
}

2voto

Le présent TopSheetBehavior ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/Android/topsheet/TopSheetBehavior.java ) s'est avéré très efficace dans mon cas. J'ai trouvé beaucoup d'autres TopSheetBehavior qui étaient incomplets ou qui se sont plantés, mais celui-ci ne se plante pas et fonctionne d'emblée en remplaçant uniquement le paramètre de comportement :

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="56dp"
        app:layout_behavior="your.package.components.TopSheetBehavior">

        <!-- Your content goes here -->

    </LinearLayout>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X