以下内容为原创,转载请注明:

来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4268097.html 

这次来使用RecyclerView实现PinnedListView的效果,效果很常见:

开发的代码建立在上一篇([Android]使用RecyclerView替代ListView(二)http://www.cnblogs.com/tiantianbyconan/p/4242541.html)基础之上。

修改布局如下:

 <?xml version="1.0" encoding="utf-8"?>

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <android.support.v7.widget.Toolbar
android:id="@+id/recycler_view_pinned_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
/>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/recycler_view_pinned_srl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
> <com.wangjie.androidbucket.support.recyclerview.pinnedlayout.PinnedRecyclerViewLayout
android:id="@+id/recycler_view_pinned_layout"
android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_pinned_rv"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#bbccaa"
/>
<Button
android:id="@+id/recycler_view_pinned_add_btn"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="#abcabc"
android:text="add"
/> </com.wangjie.androidbucket.support.recyclerview.pinnedlayout.PinnedRecyclerViewLayout> </android.support.v4.widget.SwipeRefreshLayout> </LinearLayout>

可以看到RecyclerView是被一个PinnedRecyclerViewLayouthttps://github.com/wangjiegulu/AndroidBucket/blob/master/src/com/wangjie/androidbucket/support/recyclerview/pinnedlayout/PinnedRecyclerViewLayout.java包含在里面的。这个在项目AndroidBuckethttps://github.com/wangjiegulu/AndroidBucket中。先看看代码中怎么使用吧,具体实现待会说。

 pinnedLayout.initRecyclerPinned(recyclerView, layoutManager, LayoutInflater.from(context).inflate(R.layout.recycler_view_item_float, null));
pinnedLayout.setOnRecyclerViewPinnedViewListener(this);

如上,使用方式很简单:

Line1:初始化绑定PinnedRecyclerViewLayout和RecyclerView,并设置需要被顶上去的pinnedView

Line2:设置OnRecyclerViewPinnedViewListener,作用是在顶部被顶上去替换掉的时候,会回调重新渲染数据,传入的OnRecyclerViewPinnedViewListener是this,显然,此Activity实现了这个接口,实现代码如下:

 // 渲染pinnedView数据
@Override
public void onPinnedViewRender(PinnedRecyclerViewLayout pinnedRecyclerViewLayout, View pinnedView, int position) {
switch (pinnedRecyclerViewLayout.getId()) {
case R.id.recycler_view_pinned_layout:
TextView nameTv = (TextView) pinnedView.findViewById(R.id.recycler_view_item_float_name_tv);
nameTv.setText(personList.get(position).getName());
TextView ageTv = (TextView) pinnedView.findViewById(R.id.recycler_view_item_float_age_tv);
ageTv.setText(personList.get(position).getAge() + "岁");
break;
}
}

然后,我们来看看PinnedRecyclerViewLayout是怎么实现的。

 /**
* Author: wangjie
* Email: tiantian.china.2@gmail.com
* Date: 2/2/15.
*/
public class PinnedRecyclerViewLayout extends RelativeLayout { private static final String TAG = PinnedRecyclerViewLayout.class.getSimpleName(); public static interface OnRecyclerViewPinnedViewListener {
void onPinnedViewRender(PinnedRecyclerViewLayout pinnedRecyclerViewLayout, View pinnedView, int position);
} private OnRecyclerViewPinnedViewListener onRecyclerViewPinnedViewListener; public void setOnRecyclerViewPinnedViewListener(OnRecyclerViewPinnedViewListener onRecyclerViewPinnedViewListener) {
this.onRecyclerViewPinnedViewListener = onRecyclerViewPinnedViewListener;
} public PinnedRecyclerViewLayout(Context context) {
super(context);
init(context);
} public PinnedRecyclerViewLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
} public PinnedRecyclerViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
} private void init(Context context) {
} private View pinnedView;
private ABaseLinearLayoutManager layoutManager; public void initRecyclerPinned(RecyclerView recyclerView, ABaseLinearLayoutManager layoutManager, View pinnedView) {
this.pinnedView = pinnedView;
this.layoutManager = layoutManager;
this.addView(this.pinnedView);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
this.pinnedView.setLayoutParams(lp);
layoutManager.getRecyclerViewScrollManager().addScrollListener(recyclerView, new OnRecyclerViewScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
} @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
refreshPinnedView();
}
});
pinnedView.setVisibility(GONE);
} // 保存上次的position
private int lastPosition = RecyclerView.NO_POSITION; public void refreshPinnedView() {
if (null == pinnedView || null == layoutManager) {
Logger.e(TAG, "Please init pinnedView and layoutManager with initRecyclerPinned method first!");
return;
}
if (VISIBLE != pinnedView.getVisibility()) {
pinnedView.setVisibility(VISIBLE);
}
int curPosition = layoutManager.findFirstVisibleItemPosition();
if (RecyclerView.NO_POSITION == curPosition) {
return;
}
View curItemView = layoutManager.findViewByPosition(curPosition);
if (null == curItemView) {
return;
}
// 如果当前的curPosition和上次的lastPosition不一样,则说明需要重新刷新数据,避免curPosition一样的情况下重复刷新相同数据
if (curPosition != lastPosition) {
if (null != onRecyclerViewPinnedViewListener) {
onRecyclerViewPinnedViewListener.onPinnedViewRender(this, pinnedView, curPosition);
}
lastPosition = curPosition;
} int displayTop;
int itemHeight = curItemView.getHeight();
int curTop = curItemView.getTop();
int floatHeight = pinnedView.getHeight();
if (curTop < floatHeight - itemHeight) {
displayTop = itemHeight + curTop - floatHeight;
} else {
displayTop = 0;
}
RelativeLayout.LayoutParams lp = (LayoutParams) pinnedView.getLayoutParams();
lp.topMargin = displayTop;
pinnedView.setLayoutParams(lp);
pinnedView.invalidate();
} }

这个PinnedRecyclerViewLayout 是继承RelativeLayout的,因为我们需要在里面添加一个被顶上去的pinnedView,需要覆盖在RecyclerView上面。

Line44:把传进来的pinnedView增加到PinnedRecyclerViewLayout 里面

Line47~56:在ABaseLinearLayoutManager中增加一个滚动的监听器,因为我们需要在滚动的时候动态的改变pinnedView的位置,这样才能模拟顶上去的效果。并滚动时调用refreshPinnedView来刷新pinnedView的位置。

Line57:因为在调用initRecyclerPinned方法时,RecyclerView可能还没有数据源,所以不需要显示这个pinnedView,等到真正滚动的时候再显示就可以了。

refreshPinnedView()方法的作用是在滚动的同时用来刷新pinnedView的位置和显示的数据:

Line71~78:通过layoutManager获取当前第一个显示的数据position,然后根据position获取当前第一个显示的View。

Line79~85:如果当前的curPosition和上次的lastPosition不一样,则说明需要重新刷新数据,避免curPosition一样的情况下重复刷新相同数据。

Line87~95:根据当前第一个显示的View,根据它的top、它的高度和pinnedView的高度计算出pinnedView需要往上移动的距离(画个几何图一目了然了)。

Line96~99:刷新pinnedView的位置

示例代码:

https://github.com/wangjiegulu/RecyclerViewSample

[Android]使用RecyclerView替代ListView(一)

http://www.cnblogs.com/tiantianbyconan/p/4232560.html

[Android]使用RecyclerView替代ListView(二)

http://www.cnblogs.com/tiantianbyconan/p/4242541.html

[Android]使用RecyclerView替代ListView(三)的更多相关文章

  1. [Android]使用RecyclerView替代ListView(二)

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4242541.html 以前写过一篇“[Android]使用Adapte ...

  2. [Android]使用RecyclerView替代ListView(一)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4232560.html RecyclerView是一个比List ...

  3. [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:<> [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView) 在RecyclerV ...

  4. Android笔记——RecyclerView替代ListView

    ListView是常用列表控件,但设置Adapter时自定义代码较为复杂,因此Android3.0后,增加RecyclerView替代ListView RecyclerView没有提供OnItemCl ...

  5. Android之RecyclerView简单使用(三)

    使用过ListView滴小伙伴都知道.ListView有这样一个属性android:divider,用来设置每一个item之间切割线滴属性.问题来了,那么RecyclerView这个控件有没有这个属性 ...

  6. Android最新组件RecyclerView,替代ListView

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40379159 万众瞩目的android最新5.0版本号不久前已经正式公布了,对于我 ...

  7. 浅谈RecyclerView(完美替代ListView,GridView)

    Android RecyclerView 是Android5.0推出来的,导入support-v7包即可使用. 个人体验来说,RecyclerView绝对是一款功能强大的控件. 首先总结下Recycl ...

  8. Android控件RecyclerView与ListView的异同

    在我的一篇介绍Android新控件RecyclerView的博客(Android L新控件RecyclerView简介)中,一个读者留言说RecyclerView跟ListView之间好像没有什么不同 ...

  9. Android RecyclerView与ListView比较

    RecyclerView 概述 RecyclerView 集成自 ViewGroup .RecyclerView是Android-support-V7版本中新增的一个Widgets,官方对于它的介绍是 ...

随机推荐

  1. html/css基础篇——iframe和frame的区别【转】

    转自共享圈的使用iframe的优缺点,为什么少用iframe以及iframe和frame的区别.其中本人不认同的地方有做小修改 注:HTML5不再支持使用frame,iframe只有src 属性 一. ...

  2. react路由深度解析

    先看一段代码能否秒懂很重要 这是app.js  全局js的入口 import React from 'react' import { render } from 'react-dom' import ...

  3. JAVA - IDEA快捷键(精简版)

    快捷键 功能 Ctrl + Alt + V 对应eclipse ctrl + l + 2 自动补全 Ctrl + Alt + L 对应eclipse ctrl + shift + o 代码格式化 Ct ...

  4. LeetCode - Flatten Binary Tree to Linked List

    题目: Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 ...

  5. WPF系列:无边框窗口

    <Window x:Class="Ares.Animations.Window3" xmlns="http://schemas.microsoft.com/winf ...

  6. Web API Filter ActionFilterAttribute 使用

    WebApi 提供两种过滤器的类型: 1.ActionFilterAttribute 2.exceptionFilterAttribute 两个类都是抽象类,ActionFilter 主要实现执行请求 ...

  7. Android使用SQLite数据库(2)

    打开SQLite数据库,首先要建立一个DatabaseHelper类的实例,然后,再获得数据库: DatabaseHelper mDBH; SQLiteDatabase db; mDBH = new ...

  8. MVC-自定义HttpModule处理

    HttpModule是向实现类提供模块初始化和处置事件. 当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于 ...

  9. 算法:求幂(python版)

    分别用迭代方法和递归方法实现求幂迭代方法的时间复杂度为O(n),空间复杂度为O(1)递归方法1的时间复杂度为O(logn),空间复杂度为O(logn)递归方法2的时间复杂度为O(n),空间复杂度为O( ...

  10. 阿里巴巴笔试整理系列 Session2 中级篇

    1知识点储备-----2笔试题总结-----3面试经验总结 知识点储备 2014年8月29日在线笔试题:20单选(40分钟内完成)+附加题(2道编程+1道问答) 1. 通过算法生成的随机数是“伪随机” ...