web-dev-qa-db-fra.com

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

Je veux implémenter un type de mise en page "Bottom Sheet", mais avec une torsion où la feuille "bottom" sera un MapFragment, qui ne fonctionnera pas très bien comme une vue déplaçable haut/bas.

J'ai eu une idée probablement naïve de "retourner" la logique à un design "Top Sheet", où vous faites glisser la Top Sheet vers le haut/bas pour afficher plus/moins le MapFragment inférieur.

à savoir: De cela ...
Bottom Sheet Example

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

Est-ce possible compte tenu des outils de conception de support, ou vais-je devoir lancer quelque chose comme ça par moi-même?

13
swooby

Voici la base de ma solution que j'ai commentée ci-dessus. Je reviendrai et l'étofferai plus tard.

@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);
}
2
swooby

Cette implémentation de TopSheetBehavior ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/Java/com/github/techisfun/Android/topsheet/TopSheetBehavior.Java ) s'est avéré fonctionner assez bien dans mon cas. J'ai trouvé de nombreux autres TopSheetBehavior qui étaient incomplets ou qui se sont écrasés, mais celui-ci ne plante pas et fonctionne hors de la boîte 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>
5
xarlymg89