带有appbar_scrolling_behaviour的appbar下方的BottomSheet

Posted

技术标签:

【中文标题】带有appbar_scrolling_behaviour的appbar下方的BottomSheet【英文标题】:BottomSheet below appbar with appbar_scrolling_behaviour 【发布时间】:2017-07-13 09:07:10 【问题描述】:

我想让我的bottomsheet 最多扩展到appbar。我有带有标签的viewpagerviewpagerappbar_scrolling_view_behavior,所以它里面的列表被滚动,toolbar 被折叠。但是底部的表格被扩展了,这是我不希望有的行为。基本上我希望折叠的bottomsheet 保持在相同的高度,并且在展开模式下它应该只展开到toolbar,无论toolbar 是否折叠。

这是我的 xml 的样子。这可行,但底部工作表也会以这种方式对appbar 崩溃作出反应。

如果我从第二个 CoordinatorLayout 中删除行为,bottomsheet 会保持原位,但会扩展到全屏。

<android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator"
    android:layout_
    android:layout_
    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_
        android:layout_
        android:theme="@style/AppTheme.AppBarOverlay">

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

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_
            android:layout_ />

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

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

      ... content with viewpager

    </FrameLayout>

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

        <LinearLayout
            android:id="@+id/bottomSheet"
            android:layout_
            android:layout_
            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>

【问题讨论】:

我也遇到同样的问题你有解决办法吗? 在下面查看我的答案。我只能通过实现自己的处理子布局的 BottomSheetBehaviour 来解决这个问题 java.lang.IllegalArgumentException: 该视图与 BottomSheetBehavior 无关,请发布您的 xml 代码 【参考方案1】:

实际上,我自己通过为 bottomSheet 编写自己的 Behavior 来重新计算自身来解决这个问题。还将所有元素放在 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;
    

解决方案有点复杂,但我找不到其他更好的方法来解决这个问题。因此,如果有人知道此案例的更好解决方案,请发帖,我会进行调查。

【讨论】:

以上是关于带有appbar_scrolling_behaviour的appbar下方的BottomSheet的主要内容,如果未能解决你的问题,请参考以下文章

带有和不带有聚合的 sql 查询

如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片

CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?

带有滚动的 Div 和带有绝对位置的内容

带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢

访问控制允许带有和不带有 www 的来源