FloatingActionButton的显示与隐藏

FloatingActionButton简介

FloatingActionButton(FAB) 是Android 5.0 新特性——Material Design 中的一个控件,是一种悬浮的按钮,并且是 ImageView 的子类,因此它具备ImageView的全部属性。一般FloatingActionButton 结合 CoordinatorLayout 使用,即可实现悬浮在任意控件的任意位置。

FloatingActionButton使用

本文主要实现的效果:Toolbar和FloatingActionButton根据页面列表的上下滑动来隐藏和显示。

效果图:

当我上滑列表时:隐藏Toolbar和FloatingActionButton

当我下滑列表的时:显示Toolbar和FloatingActionButton

实现方法(一)

监听页面列表(RecyclerView)的滑动回调事件,通过回调来决定Toolbar和FAB的显示和隐藏。

1)封装RecyclerView.OnScrollListener,封装的原因是为了让Activity显得没那么臃肿。

public class MyScrollListener extends RecyclerView.OnScrollListener {

    private HideAndShowListener mHideAndShowListener;
    private static final int THRESHOLD = 20;
    private int distance = 0;
    private boolean visible = true;


    public MyScrollListener(HideAndShowListener hideAndShowListener) {
        mHideAndShowListener = hideAndShowListener;
    }


    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        /**
         * dy:Y轴方向的增量
         * 有正和负
         * 当正在执行动画的时候,就不要再执行了
         */
        Log.i("tag","dy--->"+dy);
        if (distance > THRESHOLD && visible) {
            //隐藏动画
            visible = false;
            mHideAndShowListener.hide();
            distance = 0;
        } else if (distance < -20 && !visible) {
            //显示动画
            visible = true;
            mHideAndShowListener.show();
            distance = 0;
        }
        if (visible && dy > 0 || (!visible && dy < 0)) {
            distance += dy;
        }
    }

    public interface HideAndShowListener {
        void hide();

        void show();
    }
}
复制代码

主要在onScrolled方法计算判断FAB的显示和隐藏,然后设置HideAndShowListener回调,调用相应的显示和隐藏的方法即可。

2)RecyclerView添加OnScrollListener监听并且设置HideAndShowListener回调,通过HideAndShowListener的hide()和show()来设置FAB的隐藏和显示。

public class FABActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private FloatingActionButton fab;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fab);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        setSupportActionBar(toolbar);
        setTitle("FAB");

        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 60; i++) {
            list.add("Item"+i);
        }
        FabRecyclerAdapter adapter = new FabRecyclerAdapter(list);
        mRecyclerView.setAdapter(adapter);
        setListener();

    }

    /**
     * 添加ScrollListener监听
     * 以及HideAndShowListener回调
     */
    private void setListener() {

        mRecyclerView.addOnScrollListener(new MyScrollListener(new MyScrollListener.HideAndShowListener() {
            @Override
            public void hide() {
                // 隐藏动画--属性动画
                toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams();

                fab.animate().translationY(fab.getHeight() + layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3));
            }

            @Override
            public void show() {
                // 显示动画--属性动画
                toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));

                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams();
                fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
            }
        }));
    }


}
复制代码

在hide()和show()方法中,设置了FAB的隐藏和显示的动画。

接下来给出RecyclerView的Adapter

public class FabRecyclerAdapter extends RecyclerView.Adapter {


    private List<String> list;

    public FabRecyclerAdapter(List<String> list) {
        this.list = list;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        String str = list.get(position);
        MyViewHolder hd = (MyViewHolder) holder;
        hd.mButton.setText(str);
    }

    @Override
    public int getItemCount() {
        if (list != null) {
            return list.size();
        }
        return 0;
    }


    class MyViewHolder extends RecyclerView.ViewHolder {

        private Button mButton;

        public MyViewHolder(View itemView) {
            super(itemView);
            mButton = (Button) itemView.findViewById(R.id.btn);
        }

    }

}
复制代码

MyViewHolder的xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <Button
        android:id="@+id/btn"
        android:layout_margin="5dp"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
        />

</LinearLayout>

复制代码

Activity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.main.fab.FABActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize"
        />

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

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_margin="16dp"
        />
</RelativeLayout>
复制代码

以上就是实现Toolbar和FloatingActionButton根据页面列表的上下滑动来隐藏和显示方法一的这个过程。

实现方法(二)

通过封装CoordinatorLayout.Behavior,通过它的onNestedScroll方法计算判断显示和隐藏,同时给Toolbar和FAB设置app:layout_behavior,该属性指定使用封装的CoordinatorLayout.Behavior即可。

1)封装CoordinatorLayout.Behavior

public class FabBehavior extends CoordinatorLayout.Behavior {

    public FabBehavior() {
    }

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

    private boolean visible = true;//是否可见


    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
        //被观察者(RecyclerView)发生滑动的开始的时候回调的
        //nestedScrollAxes:滑动关联轴,现在只关心垂直的滑动。
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
                target, nestedScrollAxes);
    }


    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        //被观察者滑动的时候回调的
        if (dyConsumed > 0 && visible) {
            //show
            visible = false;
            onHide(child);
        } else if (dyConsumed < 0) {
            //hide
            visible = true;
            onShow(child);
        }
    }

    public void onHide(View view) {
        // 隐藏动画--属性动画
        if (view instanceof Toolbar){
            ViewCompat.animate(view).translationY(-(view.getHeight() * 2)).setInterpolator(new AccelerateInterpolator(3));
        }else if (view instanceof FloatingActionButton){
            ViewCompat.animate(view).translationY(view.getHeight() * 2).setInterpolator(new AccelerateInterpolator(3));
        }else{

        }

    }

    public void onShow(View view) {
        // 显示动画--属性动画
        ViewCompat.animate(view).translationY(0).setInterpolator(new DecelerateInterpolator(3));

    }


}
复制代码

onStartNestedScroll:列表(RecyclerView)刚开始滑动时候会回调该方法,需要在方法内设置滑动关联轴。这里只需要垂直方向上的滑动即可。

onNestedScroll:滑动的时候不断的回调该方法,通过dyConsumed来判断是上滑还是下滑。

2)Toolbar和FAB设置app:layout_behavior

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.main.behavior.BehaviorActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingTop="?attr/actionBarSize"
        />

    <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_behavior="com.main.behavior.FabBehavior"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_launcher"
        app:layout_behavior="com.main.behavior.FabBehavior"/>

</android.support.design.widget.CoordinatorLayout>
复制代码

在布局文件中给Toolbar和FAB直接设置app:layout_behavior即可。

BehaviorActivity.java

/**
 * FloatActionButton
 * 滑动显示与隐藏
 */

public class BehaviorActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private Toolbar toolbar;
    private FloatingActionButton fab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_behavior);

        mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
        fab = (FloatingActionButton)findViewById(R.id.fab);
        toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        setTitle("FAB");

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 60; i++) {
            list.add("Item"+i);
        }
        FabRecyclerAdapter adapter = new FabRecyclerAdapter(list);
        mRecyclerView.setAdapter(adapter);

    }
}
复制代码

这样就可以使用该方案实现Toolbar和FloatingActionButton根据页面列表的上下滑动来隐藏和显示。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值