FloatingActionButton的滚动隐藏和弹出特效的实现

FloatingActionButton可以说是Material Design 的标志之一了,但是却有很多人并不是很喜欢它,其中一条主要的原因就是FAB的存在挡住了要显示的内容,从而影响体验。

本文主要介绍对FAB两方面的优化,一方面是点击FAB弹出子菜单的特效,一方面是在滑动时自动隐藏FAB。最终的实现效果见下图:

FloatingActionButton的滚动隐藏和弹出特效的实现_第1张图片


弹出特效的实现

这里用到一个第三方FAB库,主要实现步骤如下。

先用Android Studio 新建一个Blank的Activity,我们发现默认情况下该Activity自带一个FAB,如图所示:

FloatingActionButton的滚动隐藏和弹出特效的实现_第2张图片

在build.gradle中导入依赖:

compile 'com.getbase:floatingactionbutton:1.10.1'

然后点击"Sync Now" AS就会自动完成对依赖的下载,不需要我们再去GitHub上下载。

接下来使用该第三方库的FloatingActionsMenu来代替之前布局文件中的FloatingActionButton。FloatingActionsMenu可以说是一个FAB集合,其本身包含一个add按钮,点击该按钮后便展开子菜单,从而实现弹出特效。布局文件activity_main.xml如下:




    

        

    

    

    

        
        
    


这里别忘了添加命名空间

xmlns:fab="http://schemas.android.com/apk/res-auto"


我们需要自己设置labelStyle,首先在colors.xml中加入以下两个颜色:

#B2000000
#FFFFFF


在styles中加入如下代码:

上面的fab_label_background可以自己在drawable文件夹中定义一个,参考如下:



    
    
    


布局文件中的ic_add_24dp、ic_timer_24dp和ic_accessibility_24dp都可以通过右键drawable文件夹--New--Vector asset来选择,在material icon下点choose即可进行图标的挑选。

将MainActivity中关于FloatingActionButton的代码删掉,然后运行应用就能得到如下效果:

FloatingActionButton的滚动隐藏和弹出特效的实现_第3张图片

滚动隐藏的实现

这篇文章里实现了对FloatingActionButton滚动隐藏,这里我们采用一样的办法实现FloatingActionsMenu的滚动隐藏。
首先利用Android Studio新建一个RecyclerView,在包名下右键--New--Fragment--Fragment(List)即可,然后AS会自动为我们建立好RecyclerView所需要的类以及布局文件。并且默认产生了一个包含25个item的RecyclerView,这里我们直接使用即可。
在主布局文件activity_main中删掉这一行


在该位置放置一个fragment的容器:

在MainActivity中的onCreate()方法中添加含有 RecyclerView的Fragment:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FragmentManager fm=getSupportFragmentManager();
    Fragment mFragment=fm.findFragmentById(R.id.fragmentContainer);

    if (mFragment==null){
        mFragment=new ItemFragment();
        fm.beginTransaction().add(R.id.fragmentContainer,mFragment).commit();
    }
}


因为默认生成的ItemFragment有一个监听接口,我们需要在MainActivity中实现该接口并且覆盖接口中的方法,可以选择什么都不做或者加入你需要的点击事件:
public class MainActivity extends AppCompatActivity implements ItemFragment.OnListFragmentInteractionListener {
    @Override
    public void onListFragmentInteraction(DummyContent.DummyItem item) {

    }


然后新建一个ScrollAwareFABBehavior类,继承自CoordinatorLayout.Behavior,代码如下:

public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior {

    private static final android.view.animation.Interpolator INTERPOLATOR=new FastOutSlowInInterpolator();
    private boolean mIsAnimatingOut=false;

    public ScrollAwareFABBehavior(Context context, AttributeSet attrs){
        super();
    }
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View directTargetChild, View target, int nestedScrollAxes) {
        //处理垂直方向上的滚动事件
        return nestedScrollAxes== ViewCompat.SCROLL_AXIS_VERTICAL|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        //向上滚动进入,向下滚动隐藏
        if (dyConsumed>0&&!this.mIsAnimatingOut && child.getVisibility()==View.VISIBLE){
            //如果是展开的话就先收回去
            if (child.isExpanded()){
                child.collapse();
            }
            //animateOut()和animateIn()都是私有方法,需要重新实现
            animateOut(child);
        } else if (dyConsumed<0 && child.getVisibility()!=View.VISIBLE){
            animateIn(child);
        }
    }

    private void animateOut(final FloatingActionsMenu button){
            ViewCompat.animate(button).translationY(500)
                .setInterpolator(INTERPOLATOR).withLayer()
                    .setListener(new ViewPropertyAnimatorListener() {
                        @Override
                        public void onAnimationStart(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=true;
                        }

                        @Override
                        public void onAnimationEnd(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=false;
                            view.setVisibility(View.GONE);
                        }

                        @Override
                        public void onAnimationCancel(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=false;

                        }
                    }).start();
        }

    private void animateIn(FloatingActionsMenu button){
        button.setVisibility(View.VISIBLE);
            ViewCompat.animate(button).translationY(0)
                    .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
                    .start();
        }
}

最后在布局文件的FloatingActionsMenu中添加下面的属性(记得把包名改为自己的):

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


运行应用,就可得到自动隐藏效果,并且在隐藏前展开的菜单会先收回:

FloatingActionButton的滚动隐藏和弹出特效的实现_第4张图片

Demo的源码:https://github.com/w-kahn/FABDemo


你可能感兴趣的:(Android,开发)