FloatingActionButton滚动隐藏的另一种实现方法:依赖appBarLayout

上一篇文章中,我们介绍了一种实现FloatingActionButton随内容滚动隐藏的办法,原理是为FAB添加行为属性(behavior),通过对内容的滚动监控来实现隐藏。但是这种办法有一个缺点就是,当item比较少的时候,少到屏幕就能显示所有内容,不会产生滚动,这样FAB就无法隐藏了,可能遮住最后一项要显示的内容。

本文我们将介绍另一种办法,让FAB随toolbar的隐藏而实现隐藏,而不是依赖内容。先上效果图:

准备

首先先把状态栏设置为非透明的,这样toolbar上滑出去标题跟状态栏不会重叠,而是被覆盖。将style(v21)中的

<item name="android:statusBarColor">@android:color/transparent</item>

改为:

<item name="android:statusBarColor">@color/colorPrimaryDark</item>

属性设置

然后设置Toolbar随滚动操作退出屏幕,在activity_main中的Toolbar组间中加入如下属性:

app:layout_scrollFlags="scroll|enterAlways"

一切就绪后,就开始写行为属性类,代码如下:

public class ScrollingFABBehavior extends CoordinatorLayout.Behavior<FloatingActionsMenu> {
    
    //定义toolbar高度和状态栏高度
    private int toolbarHeight;
    private double statusBarHeight;
    public ScrollingFABBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        //得到两个高度值
        this.toolbarHeight = getToolbarHeight(context);
        this.statusBarHeight=getStatusBarHeight(context);

    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionsMenu fab, View dependency) {
        //设定依赖的父布局为AppBarLayout
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionsMenu fab, View dependency) {
        if (dependency instanceof AppBarLayout) {
            //FAB的自身高度+据底边高度的和=要实现FAB隐藏需要向下移动的距离
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
            int fabBottomMargin = lp.bottomMargin;
            int distanceToScroll = fab.getHeight() + fabBottomMargin;
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
                //toolbar被移走的距离与本身高度的比值
                float ty=dependency.getY()-(float)statusBarHeight;
                float ratio = ty / (float) toolbarHeight;
                //toolbar被移走几分之几,fab就向下滑几分之几
                fab.setTranslationY(-distanceToScroll * ratio);
            }
        }
        return true;
    }
    
    private int getToolbarHeight(Context context){
        TypedValue tv = new TypedValue();
        int actionBarHeight = android.support.v7.appcompat.R.attr.actionBarSize;
        if (context.getTheme().resolveAttribute(R.attr.actionBarSize, tv, true))
        {
            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
                    context.getResources().getDisplayMetrics());
        }

        return actionBarHeight;
    }
    //状态栏高度的方法
   private int getStatusBarHeight(Context context) {
       int result = 0;
       int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
       if (resourceId > 0) {
           result = context.getResources().getDimensionPixelSize(resourceId);
       }
       return result;
   }
}

具体办法注释中已经说明了。

然后将FAB的行为属性改成:

app:layout_behavior="com.android.wangkang.fabdemo.ScrollingFABBehavior"

至此运行应用,就能得到上面的效果。

后记

这种方法是参考这篇文章中的办法:https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling(part3)/

刚开始直接复制该文章中的ScrollingFABBehavior类,复制过来并将FAB设置为该属性后,发现启动时FAB并不在原位置,而是向上偏移了很多。该文章中关于FAB的隐藏方法如下:

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        if (dependency instanceof AppBarLayout) {
                CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
                int fabBottomMargin = lp.bottomMargin;
                int distanceToScroll = fab.getHeight() + fabBottomMargin;
                float ratio = (float)dependency.getY()/(float)toolbarHeight;
                fab.setTranslationY(-distanceToScroll * ratio);
        }
        return true;
    }

设置断点后发现应用启动时dependency.getY()并不是0而是75,查资料后发现75是状态栏高度。后来google后找到了几种得到状态栏高度的办法,在初始计算时减去即可。修改后的方法为:

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionsMenu fab, View dependency) {
        if (dependency instanceof AppBarLayout) {
            //FAB的自身高度+据底边高度的和=要实现FAB隐藏需要向下移动的距离
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
            int fabBottomMargin = lp.bottomMargin;
            int distanceToScroll = fab.getHeight() + fabBottomMargin;
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
                //toolbar被移走的距离与本身高度的比值
                float ty=dependency.getY()-(float)statusBarHeight;
                float ratio = ty / (float) toolbarHeight;
                //toolbar被移走几分之几,fab就向下滑几分之几
                fab.setTranslationY(-distanceToScroll * ratio);
            }
        }
        return true;
    }

我的这篇文章介绍了两种获得状态栏高度的办法。

Demo放在:https://github.com/w-kahn/FABDemo/tree/OtherHide




猜你喜欢

转载自blog.csdn.net/w_kahn/article/details/50675080