RecyclerView 滑动隐藏,显示ToolBar

一:去除自带的ActionBar,在styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

二:布局文件,注意这里使用FrameLayout,是为了把ToolBar叠加放在RecyclerView上,如果不这样,当你隐藏ToolBar时,原ToolBar所在位置会出现空白。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

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

</FrameLayout>

三:具体实现

package com.example.kirito.testapp.testtoolbarscroll;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;

import com.example.kirito.testapp.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by kirito on 2017.02.13.
 */

public class TooBarScroll extends AppCompatActivity {
    private Toolbar toolbar;
    private RecyclerView rv;
    private RvAdapter adapter;
    private List<String> list;

    private static int THRESHOLD_OFFSET = 10;

    private static final String TAG = "TooBarScroll";

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

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle(R.string.app_name);
        rv = (RecyclerView) findViewById(R.id.rv);

        rv.setLayoutManager(new LinearLayoutManager(this));
        list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add(i + "");
        }
        adapter = new RvAdapter(this);
        rv.setAdapter(adapter);
        adapter.addAll(list);

        rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            boolean controlVisible = true;
            int scrollDistance = 0;

            //onScrolled 滑动停止的时候调用
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                if (controlVisible && scrollDistance > THRESHOLD_OFFSET){//手指上滑即Scroll向下滚动的时候,dy为正
                    animationHide();

                    //重置使下面的if语句起作用
                    controlVisible = false;
                    scrollDistance = 0;
                }else if (!controlVisible && scrollDistance < -THRESHOLD_OFFSET){//手指下滑即Scroll向上滚动的时候,dy为负
                    animationShow();
                    controlVisible = true;
                    scrollDistance = 0;
                }

                //当scrollDistance累计到隐藏(显示)ToolBar之后,如果Scroll向下(向上)滚动,则停止对scrollDistance的累加
                //直到Scroll开始往反方向滚动,再次启动scrollDistance的累加
                if ((controlVisible && dy > 0) || (!controlVisible && dy < 0)){
                    scrollDistance += dy;
                }
            }
        });
    }

    private void animationShow() {
        toolbar.animate()
                .setInterpolator(new AccelerateInterpolator(1))
                .setDuration(180)
                .translationY(0);
    }

    private void animationHide(){

        toolbar.animate()
                .translationY(-toolbar.getBottom())
                .setInterpolator(new LinearInterpolator())
                .setDuration(180);

    }
}

效果图:
这里写图片描述


这里有个问题,ToolBar把RecyclerView最开头的几行挡住了,因为布局文件里使用的是FrameLayout。

四:此时有两个解决方法,一是对RecyclerView的属性进行修改

<android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:paddingTop="?actionBarSize"
        android:clipToPadding="false"//若没有这句在隐藏ToolBar的时候会出现空白,如下所示
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

这里写图片描述

改进后的效果

这里写图片描述


五:第二种解决方法:在原ToolBar下面给RecyclerView添加一个子View

1.修改的RecyclerView adapter

package com.example.kirito.testapp.testtoolbarscroll;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.example.kirito.testapp.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by kirito on 2017.02.13.
 */

public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private LayoutInflater mLayoutInflater;
    private List<String> list = new ArrayList<>();

    private int hearder = 0;
    private int item = 1;

    public RvAdapter(Context mContext) {
        mLayoutInflater = LayoutInflater.from(mContext);
    }

    public void addAll(List<String> items){
        list = items;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //添加header
        if (viewType == 0){
            return new Holder(mLayoutInflater.inflate(R.layout.rv_header,parent,false));
        }else {
            return new Holder(mLayoutInflater.inflate(R.layout.rv_item,parent,false),0);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        //不是header才绑定数据
        if (position != 0){
            ((Holder)holder).bindHolder(list.get(position - 1));
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0){
            return hearder;
        }else {
            return item;
        }
    }

    @Override
    public int getItemCount() {
        //count + 1
        return list.size() + 1;
    }
}

2.修改的RecyclerView.ViewHolder

package com.example.kirito.testapp.testtoolbarscroll;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

import com.example.kirito.testapp.R;

/**
 * Created by kirito on 2017.02.13.
 */

public class Holder extends RecyclerView.ViewHolder {
    private TextView tv;

    //使用不同的构造器区分
    public Holder(View itemView) {
        super(itemView);
    }

    public Holder(View itemView, int flag) {
        super(itemView);
        tv = (TextView) itemView.findViewById(R.id.rv_item_tv);
    }

    public void bindHolder(String i){
        tv.setText(i);
    }
}

3.header的布局文件

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="?actionBarSize"/>


4.实现效果
这里写图片描述


六:这里还是有一个问题在ToolBar隐藏之后,显示header时会有空白

这时,只需修改onScrolled方法就可以了

@Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                int firstViewPosition = ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
                if (firstViewPosition == 0){//当header是FirstVisibleItem并且隐藏了ToolBar时,显示ToolBar
                    if (!controlVisible){
                        animationShow();
                        controlVisible = true;
                    }
                }else {

                    if (controlVisible && scrollDistance > THRESHOLD_OFFSET){//手指上滑即Scroll向下滚动的时候,dy为正
                        animationHide();

                        //重置使下面的if语句起作用
                        controlVisible = false;
                        scrollDistance = 0;
                    }else if (!controlVisible && scrollDistance < -THRESHOLD_OFFSET){//手指下滑即Scroll向上滚动的时候,dy为负
                        animationShow();
                        controlVisible = true;
                        scrollDistance = 0;
                    }

                    //当scrollDistance累计到隐藏(显示)ToolBar之后,如果Scroll向下(向上)滚动,则停止对scrollDistance的累加
                    //直到Scroll开始往反方向滚动,再次启动scrollDistance的累加
                    if ((controlVisible && dy > 0) || (!controlVisible && dy < 0)){
                        scrollDistance += dy;
                    }
                }
            }
        });

最后的效果图:
这里写图片描述

参考

猜你喜欢

转载自blog.csdn.net/zzldm/article/details/55050293