tablayout 悬浮与顶部效果,仿饿了么列表悬停效果

本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

点击打开链接


你可能感兴趣的:(自定义view)