BottomSheet под панелью приложений с appbar_scrolling_behaviour

Я хотел бы, чтобы мой bottomsheet был расширен только до appbar. У меня viewpager с вкладками, а viewpager с appbar_scrolling_view_behavior, поэтому список внутри него прокручивается, а toolbar сворачивается. Но нижний лист расширен, чего я не хочу. В основном я хотел бы, чтобы свернутый bottomsheet оставался на месте с той же высотой, а в расширенном режиме он должен расширяться только до toolbar, независимо от того, свернутый toolbar или нет.

Вот как выглядит мой xml. Это работает, но нижний лист также реагирует на appbar разрушение.

Если я удалю поведение из второго CoordinatorLayout, bottomsheet останется на месте, но развернется на весь экран.

<android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <FrameLayout
        android:id="@+id/loadingContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

      ... content with viewpager

    </FrameLayout>

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:id="@+id/bottomSheet"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:behavior_hideable="false"
            app:behavior_peekHeight="55dp"
            app:layout_behavior="@string/bottom_sheet_behavior"/>

    </android.support.design.widget.CoordinatorLayout>

</android.support.design.widget.CoordinatorLayout>

person Datenshi    schedule 13.07.2017    source источник
comment
я тоже столкнулся с той же проблемой, у вас есть какое-нибудь решение?   -  person Sarath Kumar    schedule 13.11.2018
comment
Смотрите мой ответ ниже. Мне удалось исправить это только путем реализации моего собственного BottomSheetBehaviour, который обрабатывает дочерние макеты.   -  person Datenshi    schedule 13.11.2018
comment
java.lang.IllegalArgumentException: представление не связано с BottomSheetBehavior, пожалуйста, опубликуйте свой xml-код   -  person Sarath Kumar    schedule 13.11.2018


Ответы (1)


На самом деле я исправил это сам, написав собственное поведение для нижнего листа, чтобы пересчитать себя. Также разместил все элементы внутри CoordinatorLayout.

public class BottomSheetBehaviour extends AppBarLayout.ScrollingViewBehavior {

    public BottomSheetBehaviour () { }

    public BottomSheetBehaviour (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        setDimensions((CoordinatorLayout) child, child.getLayoutParams().width,
            parent.getHeight() - (int) getOffset(parent));
        return true;
    }

    @Override
    protected void layoutChild(final CoordinatorLayout parent, final View child, final int layoutDirection) {
        final List<View> dependencies = parent.getDependencies(child);
        final View header = findFirstDependency(dependencies);
        final Rect available = new Rect();
        if (header != null) {
            final CoordinatorLayout.LayoutParams lp =
                (CoordinatorLayout.LayoutParams) child.getLayoutParams();

            available.set(parent.getPaddingLeft() + lp.leftMargin, header.getBottom() + lp.topMargin,
                parent.getWidth() - parent.getPaddingRight() - lp.rightMargin,
                parent.getHeight() + header.getBottom() - parent.getPaddingBottom() - lp.bottomMargin);

            final Rect out = new Rect();
            GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(),
                child.getMeasuredHeight(), available, out, layoutDirection);
            final int overlap = getOverlapPixelsForOffset();
            child.layout(out.left, out.top - overlap, out.right, parent.getHeight() - overlap);
        }
    }

    private int getOverlapPixelsForOffset() {
        return getOverlayTop() == 0 ? 0 :
            constrain((int) (1f * getOverlayTop()), 0, getOverlayTop());
    }

    private AppBarLayout findFirstDependency(List<View> views) {
        for (int i = 0, z = views.size(); i < z; i++) {
            View view = views.get(i);
            if (view instanceof AppBarLayout) {
                return (AppBarLayout) view;
            }
        }
        return null;
    }

    private static int constrain(int amount, int low, int high) {
        return amount < low ? low : (amount > high ? high : amount);
    }

    private static int resolveGravity(int gravity) {
        return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity;
    }

    private void setDimensions(CoordinatorLayout view, int width, int height) {
        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) view.getLayoutParams();
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }

    private float getOffset(CoordinatorLayout coordinatorLayout) {

        for (int i = 0; i < coordinatorLayout.getChildCount(); i++) {
            View child = coordinatorLayout.getChildAt(i);

            if (child instanceof AppBarLayout) {
                return child.getY() + child.getHeight();
            }
        }
        return 0;
    }
}

Решение довольно сложное, но я не смог найти другого лучшего способа решить эту проблему. Поэтому, если кто-нибудь знает лучшее решение для этого случая, напишите, и я его расследую.

person Datenshi    schedule 26.03.2018