先看效果图,有波浪纹的是我点击的~~~:

RecyclerView滑动置顶点击置顶的实现_置顶

可以看出,这个 RcyclerView 我想让它滑动置顶它就会到顶部,想点击置顶也可以到顶部。那么如何实现的呢,具体看下面,因为下面内容太多。如果不想了解,可以直接下载下面的例子,下面是下载地址:

GitHub 下载地址:https://github.com/wuqingsen/RecyclerViewTop

下面是讲的主要内容:

  • MainActivity 和 activity_main 主要代码
  • MainAdapter

1. MainActivity 和 activity_main 主要代码

public class MainActivity extends AppCompatActivity {
    private MainAdapter adapter;
    private RecyclerView recyclerView;
    private List<String> mDatas;
    private View include;
    private String str;
    //目标项是否在最后一个可见项之后
    private boolean mShouldScroll;
    //记录目标项位置
    private int mToPosition;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        include = findViewById(R.id.include);
        recyclerView = findViewById(R.id.recyclerView);

        //添加数据
        addData();
        adapter = new MainAdapter(MainActivity.this, mDatas);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
        //滑动监听
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //定位初始点坐标
                View stickyInfoView = recyclerView.findChildViewUnder(recyclerView.getMeasuredWidth() / 2, 1);
                if (stickyInfoView != null) {
                    TextView typeName = stickyInfoView.findViewById(R.id.typeName);
                    if (typeName != null) {
                        str = typeName.getText().toString();
                    }
                    //标题为聊天室榜单部分的标识、筛选为筛选部分的标识,内容为数据内容的标识
                    if (str.equals("标题")) {
                        include.setVisibility(View.GONE);
                    } else if (str.equals("筛选")) {
                        include.setVisibility(View.VISIBLE);
                    } else if (str.equals("内容")) {
                        include.setVisibility(View.VISIBLE);
                    }
                }
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (mShouldScroll && RecyclerView.SCROLL_STATE_IDLE == newState) {
                    mShouldScroll = false;
                    smoothMoveToPosition(recyclerView, mToPosition);
                }
            }
        });

        //点击置顶
        adapter.setmOnItemClickListerer(new MainAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                if (position != -1) {
                    smoothMoveToPosition(recyclerView, position);
                }
            }
        });
    }

    private void addData() {
        mDatas = new ArrayList<>();
        //手动添加两条数据,adapter判断的依据
        mDatas.add("0");
        mDatas.add("1");
        //for循环加入30条数据
        for (int i = 1; i <= 30; i++) {
            mDatas.add("这是第" + i + "条数据");
        }
    }

    /**
     * 平滑的滑动到指定位置
     */
    private void smoothMoveToPosition(RecyclerView mRecyclerView, final int position) {
        // 第一个可见位置
        int firstItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(0));
        // 最后一个可见位置
        int lastItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1));
        if (position < firstItem) {
            // 第一种可能:跳转位置在第一个可见位置之前
            mRecyclerView.smoothScrollToPosition(position);
        } else if (position <= lastItem) {
            // 第二种可能:跳转位置在第一个可见位置之后
            int movePosition = position - firstItem;
            if (movePosition >= 0 && movePosition < mRecyclerView.getChildCount()) {
                int top = mRecyclerView.getChildAt(movePosition).getTop();
                mRecyclerView.smoothScrollBy(0, top);
            }
        } else {
            // 第三种可能:跳转位置在最后可见项之后
            mRecyclerView.smoothScrollToPosition(position);
            mToPosition = position;
            mShouldScroll = true;
        }
    }
}

看一下上面的注释,其实很好理解,不明白回复我~~。下面是 activity_main 的代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- 这是筛选布局 -->
    <include
        android:id="@+id/include"
        layout="@layout/adapter_one"
        android:visibility="gone" />

</RelativeLayout>

代码内只有一个 RecyclerView 和一个筛选布局。

2. MainAdapter 和布局文件

public class MainAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private final int type_zero = 0;
    private final int type_one = 1;
    private final int type_two = 2;
    private List<String> mDatas;

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    public MainAdapter.OnItemClickListener mOnItemClickListerer;

    public void setmOnItemClickListerer(MainAdapter.OnItemClickListener listerer) {
        this.mOnItemClickListerer = listerer;
    }

    public MainAdapter(Context context, List<String> mDatas) {
        this.context = context;
        this.mDatas = mDatas;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        if (viewType == type_zero) {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_zero, parent, false);
            return new ZeroViewHolder(view);
        } else if (viewType == type_one) {
            //排序
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_one, parent, false);
            return new OneViewHolder(view);
        } else {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_other, parent, false);
        }
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        switch (holder.getItemViewType()) {
            case type_zero:
                ZeroViewHolder zeroViewHolder = (ZeroViewHolder) holder;
                //聊天室榜单,逻辑

                break;
            case type_one:
                OneViewHolder oneViewHolder = (OneViewHolder) holder;
                //筛选,adapter点击置顶
                oneViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        mOnItemClickListerer.onItemClick(view,position);
                    }
                });
                break;
            default:
                MyViewHolder myViewHolder = (MyViewHolder) holder;
                //内容,写逻辑
                myViewHolder.tv_text.setText(mDatas.get(position));
                break;
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return type_zero;
        } else if (position == 1) {
            return type_one;
        } else {
            return type_two;
        }
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    class ZeroViewHolder extends RecyclerView.ViewHolder {

        public ZeroViewHolder(View itemView) {
            super(itemView);
        }
    }

    public class OneViewHolder extends RecyclerView.ViewHolder {

        public OneViewHolder(View itemView) {
            super(itemView);
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tv_text;

        public MyViewHolder(View itemView) {
            super(itemView);
            tv_text = itemView.findViewById(R.id.tv_text);
        }
    }
}

Adapter 中主要判断为 position == 0 是聊天室榜单, position == 1 是筛选,其他的为显示的数据。

欢迎提出意见~~~