本demo实现了tablayout 悬浮与顶部效果,仿饿了么列表悬停效果,基于CoordinatorLayout 悬停功能,使tablayout实现悬停效果,再监听RecyclerView 滑动,使需要悬停的View与header重合,使view悬停,此时header只负责占位;
上效果图:
下面介绍下实现逻辑:
首先基于CoordinatorLayout +AppBarLayout悬停功能,使tablayout实现悬停效果:
通过layout_scrollFlags属性实现,app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样上面的view才会滚动出屏幕,否则它将一直固定在顶部。
代码示例:
使View悬浮在tablayout下:
如图:
监听监听RecyclerView 滑动,使需要悬停的View与header重合,使view悬停;
此时需要给RecyclerView 添加个headview;
我们使用ListView的时候知道,要为ListView添加HeaderView是非常方便的,我们只需要调用ListView的addHeaderView(View v)
方法即可。但是RecyclerView却没有这个方法,此时需要在Adapter中进行添加方法:
public class DemoAdapter extends RecyclerView.Adapter {
private List mDatas = new ArrayList<>();
private Context mContext;
private View mHeaderView;
private int ITEM_TYPE_NORMAL = 0;
private int ITEM_TYPE_HEADER = 1;
public DemoAdapter(Context context) {
mContext = context;
}
public void setDatas(List datas) {
mDatas = datas;
notifyDataSetChanged();
}
// 创建视图
@Override
public RecyclerView.ViewHolder
onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_HEADER) {
return new ViewHolder(mHeaderView);
} else {
View v = LayoutInflater.from(mContext).inflate(R.layout.item_common_text, parent, false);
return new ViewHolder(v);
}
}
@Override
public int getItemViewType(int position) {
if (null != mHeaderView && position == 0) {
return ITEM_TYPE_HEADER;
}
return ITEM_TYPE_NORMAL;
}
// 为Item绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int type = getItemViewType(position);
if (type == ITEM_TYPE_HEADER) {
return;
}
int realPos = getRealItemPosition(position);
((ViewHolder) holder).mTextView.setText(mDatas.get(realPos));
}
private int getRealItemPosition(int position) {
if (null != mHeaderView) {
return position - 1;
}
return position;
}
@Override
public int getItemCount() {
int itemCount = mDatas.size();
if (null != mHeaderView) {
itemCount++;
}
return itemCount;
}
public void addHeaderView(View view) {
mHeaderView = view;
notifyItemInserted(0);
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.textView);
}
}
}
java代码:
demoAdapter = new DemoAdapter(getActivity());
final View header3 = LayoutInflater.from(getContext()).inflate(R.layout.view_header, recyclerView, false);
demoAdapter.addHeaderView(header3);
demoAdapter.setDatas(data);
recyclerView.setAdapter(demoAdapter);
监听RecyclerView 滑动,使需要悬停的View与header重合:
首先通过OnGlobalLayoutListener获得headview距离顶部位置:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
top = view.getTop();
addScrollListener();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
使悬浮view在headview位置:
layout_fragment_header.setTranslationY(top);
监听RecyclerView 滑动,当滑动高度大于headview距离顶部的高度是,使悬浮view位于顶部:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy == 0) return;
mScrollY += dy;
int translationY = top - mScrollY;
if (translationY < 0) translationY = 0;
layout_fragment_header.setTranslationY(translationY);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
下面附上demo下载地址:
https://download.csdn.net/download/shanshan_1117/10294681
点击打开链接
补充:
因为最新需求是实现toolbar状态改变,所以补充了下代码,先上效果图:
添加了AppBarStateChangeListener 监听AppBarLayout展开折叠状态,改变标题的效果;
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
public enum State {
EXPANDED, //展开
COLLAPSED,//折叠状态
IDLE //中间状态
}
private State mCurrentState = State.IDLE;
@Override
public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
if (i == 0) {
if (mCurrentState != State.EXPANDED) {
onStateChanged(appBarLayout, State.EXPANDED);
}
mCurrentState = State.EXPANDED;
} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
if (mCurrentState != State.COLLAPSED) {
onStateChanged(appBarLayout, State.COLLAPSED);
}
mCurrentState = State.COLLAPSED;
} else {
if (mCurrentState != State.IDLE) {
onStateChanged(appBarLayout, State.IDLE);
}
mCurrentState = State.IDLE;
}
}
public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
}
在activity中
app_bar_topic.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state) {
if( state == State.EXPANDED ) {
iv_back_topic.setImageResource(R.mipmap.back_white);
toolbar_topic.setBackgroundColor(Color.argb((int) 0, 0, 0, 0));
//展开状态
}else if(state == State.COLLAPSED){
iv_back_topic.setImageResource(R.mipmap.search_back);
toolbar_topic.setBackgroundColor(Color.argb((int) 255, 255, 255, 255));
//折叠状态
}else {
iv_back_topic.setImageResource(R.mipmap.back_white);
toolbar_topic.setBackgroundColor(Color.argb((int) 0, 0, 0, 0));
//中间状态
}
}
});
下面附上修改后的demo地址:
https://download.csdn.net/download/shanshan_1117/10317360
点击打开链接