一:去除自带的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;
}
}
}
});
最后的效果图: