顶部粘性的列表

简介: 先看效果 源码Paste_Image.png002.gif为什么写这个控件?之前有朋友问我,会不会手写这种效果,不是借助于第三方,卧槽,懵逼了。

先看效果 源码

Paste_Image.png
002.gif

为什么写这个控件?

之前有朋友问我,会不会手写这种效果,不是借助于第三方,卧槽,懵逼了。。。
网上搜罗了几个这种实现效果,感觉代码写的比较复杂 或者 实现效果不佳,还是自己动手实现一下吧。

首先需要一个 自定义接口 OnStickyViewChangeListener

<pre>
package org.alex.sectionrecyclerlayout;

import android.view.View;

/**
* 作者:Alex
* 时间:2016/11/14 14:31
* 简述:只要你的adapter实现了这接口,基本上就能做到这种效果了,自觉思路挺好的
*/
public interface OnStickyViewChangeListener {
int none = -99;
int title = 1;
int item = 2;

int getStickyViewType(int position);

int getHeadViewCount();

/\*\*
 \* @param position
 \* 在 RecyclerView 中 的下标
 \*/
void onStickyViewTypeChange(View view, int position);

}

</pre>

组合一个控件,将 stickView 和 RecyclerView 包裹起来

<pre>
package org.alex.sectionrecyclerlayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;

/**
* 作者:Alex
* 时间:2016/11/14 11:22
* 简述:
*
* @link
*/
public class StickyRecyclerLayout extends RelativeLayout {
private RecyclerView recyclerView;
private View stickyView;
private LinearLayoutManager linearLayoutManager;
private int stickyViewHeight;
private OnStickyViewChangeListener onStickyViewChangeListener;

private int currItemViewType;

public StickyRecyclerLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView(context, attrs);
}

private void initView(Context context, AttributeSet attrs) {
    currItemViewType = OnStickyViewChangeListener.none;
    recyclerView = new RecyclerView(context);
    RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    recyclerView.setLayoutParams(params);
    linearLayoutManager = new LinearLayoutManager(context);
    linearLayoutManager.setOrientation(OrientationHelper.VERTICAL);
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.addOnScrollListener(new MyOnScrollListener());
    addView(recyclerView);
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StickyRecyclerLayout);
    int layoutId = typedArray.getResourceId(R.styleable.StickyRecyclerLayout_srl_sticky_view_layoutRes, -1);
    if (layoutId != -1) {
        stickyView = LayoutInflater.from(context).inflate(layoutId, null);
        addView(stickyView);
    }
    typedArray.recycle();
}

public RecyclerView getRecyclerView() {
    return recyclerView;
}

private final class MyOnScrollListener extends RecyclerView.OnScrollListener {

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if (stickyView == null) {
            return;
        }
        stickyViewHeight = stickyView.getMeasuredHeight();
        onStickyViewChangeListener = (onStickyViewChangeListener == null) ? (OnStickyViewChangeListener) recyclerView.getAdapter() : onStickyViewChangeListener;
        int headViewCount = onStickyViewChangeListener.getHeadViewCount();
        int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
        //LogUtil.e("firstVisibleItemPosition == " + firstVisibleItemPosition);

        /\*参照物的 视图 \*/
        View referenceView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition + 1);

        /\*TODO:参照物的 视图 类型
        \*
        \* 如果  你用到了 https://github.com/CymChad/BaseRecyclerViewAdapterHelper
        \* 同时使用了 adapter.addHeaderView(headView);
        \*  int referenceItemViewType = onStickyViewChangeListener.getStickyViewType(firstVisibleItemPosition);
        \*
        \*  否则
        \*  int referenceItemViewType = onStickyViewChangeListener.getStickyViewType(firstVisibleItemPosition + 1 );
        \* \*/
        int referenceItemViewType = onStickyViewChangeListener.getStickyViewType(firstVisibleItemPosition + 1);

        if (firstVisibleItemPosition < headViewCount) {
            stickyView.setVisibility(View.GONE);
        } else {
            stickyView.setVisibility(View.VISIBLE);
        }
        //LogUtil.e(firstVisibleItemPosition + " referenceViewHeight = " + referenceView.getMeasuredHeight() + " nextViewTop = " + referenceView.getTop() + " viewType = " + ((referenceItemViewType == OnStickyViewChangeListener.title) ? "title" : "item"));
        if (referenceItemViewType == OnStickyViewChangeListener.title) {
            int nextViewTop = referenceView.getTop();
            if (nextViewTop - stickyViewHeight < 0) {
                //LogUtil.e(firstVisibleItemPosition + " ######### nextViewTop - stickyViewHeight = " + (nextViewTop - stickyViewHeight));
                stickyView.setTranslationY(nextViewTop - stickyViewHeight);
            } else {
                stickyView.setTranslationY(0);
            }
        } else {
            stickyView.setTranslationY(0);
        }
        /\* TODO: 响应 回调
        \* 如果  你用到了 https://github.com/CymChad/BaseRecyclerViewAdapterHelper
        \* 同时使用了 adapter.addHeaderView(headView);
        \*  int tmpPosition = (firstVisibleItemPosition >= 1) ? firstVisibleItemPosition - 1 : firstVisibleItemPosition;
        \*
        \*  否则
        \*  int tmpPosition = firstVisibleItemPosition;
        \* \*/
        int tmpPosition = firstVisibleItemPosition;
        int tmpCurrentItemViewType = onStickyViewChangeListener.getStickyViewType(tmpPosition);
        if (currItemViewType != tmpCurrentItemViewType) {
            currItemViewType = tmpCurrentItemViewType;
            onStickyViewChangeListener.onStickyViewTypeChange(stickyView, tmpPosition);
        }
    }
}

}

</pre>

如果 你用多种布局写的 headView 下面的不用看了
你用到了 BaseRecyclerViewAdapterHelper .addHeadView 需要单独处理一下,别问我为啥

<pre>

/*TODO:参照物的 视图 类型
*
* 如果 你用到了 https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 同时使用了 adapter.addHeaderView(headView);
* int referenceItemViewType = onStickyViewChangeListener.getStickyViewType(firstVisibleItemPosition);
*
* 否则
* int referenceItemViewType = onStickyViewChangeListener.getStickyViewType(firstVisibleItemPosition + 1 );
* */


/* TODO: 响应 回调
* 如果 你用到了 https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 同时使用了 adapter.addHeaderView(headView);
* int tmpPosition = (firstVisibleItemPosition >= 1) ? firstVisibleItemPosition - 1 : firstVisibleItemPosition;
*
* 否则
* int tmpPosition = firstVisibleItemPosition;
* */


/*TODO: 设置 headview 个数
* 如果 你用到了 https://github.com/CymChad/BaseRecyclerViewAdapterHelper
* 同时使用了 adapter.addHeaderView(headView);
* adapter.setHeadViewCount(1);
* */
</pre>

目录
相关文章
|
8月前
ios15从隐藏系统导航栏页面进入显示系统导航栏页面后,期望系统导航栏背景色为白色,但是导航栏背景变成黑色问题
ios15从隐藏系统导航栏页面进入显示系统导航栏页面后,期望系统导航栏背景色为白色,但是导航栏背景变成黑色问题
79 0
|
8月前
|
Android开发
热点共享蓝条下压,导致页面底部按钮显示不全的完美解决方案
热点共享蓝条下压,导致页面底部按钮显示不全的完美解决方案
54 0
|
8月前
|
前端开发 JavaScript
uniapp联动左侧导航栏分类?
uniapp联动左侧导航栏分类?
|
8月前
uniapp项目怎么删除顶部导航栏
uniapp项目怎么删除顶部导航栏
367 0
|
小程序 JavaScript 数据库
小程序分类页实现三级分类,顶部导航栏,左侧分类栏,右侧数据列表
小程序分类页实现三级分类,顶部导航栏,左侧分类栏,右侧数据列表
220 0
|
小程序 JavaScript
小程序顶部导航栏,可滑动,可动态选中放大
小程序顶部导航栏,可滑动,可动态选中放大
207 0
|
JavaScript
uniapp制作app顶部原生导航栏输入框的内容自动变化
uniapp制作app顶部原生导航栏输入框的内容自动变化
314 0
uniapp制作app顶部原生导航栏输入框的内容自动变化
利用offsetTop和scrollTop实现移动端常见的当分类栏移动到顶部时固定位置效果
利用offsetTop和scrollTop实现移动端常见的当分类栏移动到顶部时固定位置效果
206 0
|
前端开发 开发者 容器
页面-顶部通栏 |学习笔记
快速学习 页面-顶部通栏
211 0
页面-顶部通栏 |学习笔记
通过HTML+CSS+JavaScript实现鼠标移动到页面顶部导航栏出现,如果移出导航栏3秒又隐藏起来,而且不受滚动条影响(二)...
通过HTML+CSS+JavaScript实现鼠标移动到页面顶部导航栏出现,如果移出导航栏3秒又隐藏起来,而且不受滚动条影响(二)...