吸顶效果的另一种实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yoonerloop/article/details/83351361

 

前面介绍过一篇文章,是使用ItemDecoration来实现吸顶效果,使用起来很解耦,简单,方便,但是优缺点是拓展性比较差,今天就通过另一种方式来实现吸顶效果,并且吸顶栏可以高度制定布局和交互,步入正题,下面来实现它,先看看效果图:

一、实现原理

头部的内容位于Recycleview上面,监听Recycleview的滑动,当Recycleview的分组item顶部接触到头部的内容布局底部时候,浮层随处Recycleview的上滑而上推,当分组完全到达顶部时候,浮层复位,这样吸顶效果就产生了,依据这个思路来实现吸顶效果。

二、布局文件实现

1、抽取公共的吸顶布局

    <?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="match_parent">

        <TextView
            android:id="@+id/sticky_text"
            android:layout_width="match_parent"
            android:layout_height="@dimen/head_top"
            android:background="@color/bg_header"
            android:gravity="center_vertical"
            android:paddingLeft="@dimen/sticky_text_margin"/>

    </LinearLayout>

2、MainActivity

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        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="cn.com.stickyrecycleview.MainActivity">

        <!--内容栏-->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycleview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <!--吸顶栏-->
        <include layout="@layout/sticky_layout"/>

    </FrameLayout>

三、Adapter实现

1、布局文件

    <?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">

        <!--分组栏-->
        <include layout="@layout/sticky_layout"/>

        <!--内容栏-->
        <TextView
            android:id="@+id/tv_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="@string/app_name"/>
    </LinearLayout>

布局文件里面包含两个View,一个是分组的View,一个是内容item的View,需要注意的是分组的View一定要和吸顶的View一致,这里为了方便期间,都设置为一个TextView。当需要展示分组的是让分组的View为VISIBLE,否则GONE掉。

 2、onBindViewHolder

    //无吸顶
    public static final int NONE_STICKY_VIEW = 0;
    //有吸顶
    public static final int HAS_STICKY_VIEW = 1;
    //第一个
    public static final int FIRST_STICKY_VIEW = 2;

onBindViewHolder是核心处理方法,如果是第0个,肯定是吸顶,设置tag:FIRST_STICKY_VIEW。如果是其他的,当前的分组依据和上一个一致,则认为是同一组,不展示分组item,设置tag:NONE_STICKY_VIEW,否则是不同组,展示分组item,设置tag:HAS_STICKY_VIEW。最后通过ContentDescription方法来记录并获取要吸顶展示的信息。详细如下备注:

     @Override
     public void onBindViewHolder(ViewHolder holder, int position) {
         DataBean dataBean = mDataList.get(position);
         if (position == 0) {
             //第0个展示吸顶栏,设置tag:FIRST_STICKY_VIEW
             holder.stickyText.setVisibility(View.VISIBLE);
             holder.stickyText.setText(dataBean.data);
             holder.itemView.setTag(FIRST_STICKY_VIEW);
         } else {
             if (!TextUtils.equals(dataBean.data, mDataList.get(position - 1).data)) {
                 //和上一个分组的依据不同,展示吸顶栏,设置tag:HAS_STICKY_VIEW
                 holder.stickyText.setVisibility(View.VISIBLE);
                 holder.stickyText.setText(dataBean.data);
                 holder.itemView.setTag(HAS_STICKY_VIEW);
             } else {
                 //其他的,隐藏分组栏
                 holder.stickyText.setVisibility(View.GONE);
                 holder.itemView.setTag(NONE_STICKY_VIEW);
             }
         }
         holder.textView.setText(dataBean.des);
         // ContentDescription 用来记录并获取要吸顶展示的信息
         holder.itemView.setContentDescription(dataBean.data);
     }

四、滑动监听

最后需要通过addOnScrollListener方法监听Recycleview的滑动,来控制吸顶变化,原理看备注:

    recycleview.addOnScrollListener(new RecyclerView.OnScrollListener() {

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    //找到RecyclerView的item中,和RecyclerView的getTop 向下相距5个像素的那个item,
                    //该方法是根据坐标获取item的View,坐标点是以RecyclerView控件作为坐标轴,并不是以屏幕左上角作为坐标原点。
                    View stickyInfoView = recyclerView.findChildViewUnder(stickyText.getMeasuredWidth() / 2, 5);
                    if (stickyInfoView != null && stickyInfoView.getContentDescription() != null) {
                        //设置吸顶栏内容
                        stickyText.setText(String.valueOf(stickyInfoView.getContentDescription()));
                    }
                    //找到固定在顶部的View的下面一个item的View
                    View transInfoView = recyclerView.findChildViewUnder(stickyText.getMeasuredWidth() / 2, stickyText.getMeasuredHeight() + 1);
                    if (transInfoView != null && transInfoView.getTag() != null) {
                        //获取该View的tag
                        int transViewStatus = (int) transInfoView.getTag();
                        int dealtY = transInfoView.getTop() - stickyText.getMeasuredHeight();
                        if (transViewStatus == MyAdapter.HAS_STICKY_VIEW) {
                            if (transInfoView.getTop() > 0) {
                                //最上面的itemView没滑出屏幕,给顶部的View设置,
                                //注意setTranslationY移动的ViewGroup,而scrollTo()/scrollBy()移动的是View的内容,如文字、图片等
                                stickyText.setTranslationY(dealtY);
                            } else {
                                //最上面的itemView滑出屏幕,顶部的复位
                                stickyText.setTranslationY(0);
                            }
                        } else if (transViewStatus == MyAdapter.NONE_STICKY_VIEW) {
                            //如果是没有分组,即无吸顶的item,则设置顶部的View移动为0,保持原位置
                            stickyText.setTranslationY(0);
                        }
                    }
                }
            });

源码地址:https://github.com/yoonerloop/StickyViewLayout

 

 

猜你喜欢

转载自blog.csdn.net/yoonerloop/article/details/83351361