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

来自天天博客: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. Hibernate的session一级缓存

    一级缓存是Session周期的,当session创建的时候就有,当session结束的时候,缓存被清空 当缓存存在的时候,每次查询的数据,都会放在缓存中,如果再次查询相同的数据,则不会再次查询数据库, ...

  2. nagios监控流量脚本

    需求是我们需要对服务器上的流量进行监控,网络上有个流传的check_traffic.sh,它需要被监控机开启snmp.但是感觉都使用上了nagios还要开snmp...有点斧子剪刀一起用的感觉,所以就 ...

  3. .NET 2.0 检测

    #include <stdio.h>#include <stdlib.h>#include<windows.h> char GetSystemDisk(){    ...

  4. JavaScript资源大全

    目录 前端MVC 框架和库 包管理器 加载器 打包工具 测试框架 框架 断言 覆盖率 运行器 QA 工具 基于 Node 的 CMS 框架 模板引擎 数据可视化 编辑器 UI 输入 日历 选择 文件上 ...

  5. LINUX总结

    LINUX总结 crazyacking 2016-02-26 主要对socket编程,多线程,定时器,条件变量总结 多线程篇 概念: 多线程就是允许一个进程内存存在多个控制权,实现多个线程并发执行. ...

  6. 使用MVVM-Sidekick开发Universal App(一)

    终于要迈进Universal的大坑了,还有点小激动呢. CurrencyExchanger 掌中汇率是我前几年发布在Windows Phone商店中的一个应用,当时是WP7版本,下载链接:http:/ ...

  7. 用python生成一个导出数据库的bat脚本文件

    # 环境: python3.x def getExportDbSql(db, index): # 获取导出一个数据库实例的sql语句 sql = 'mysqldump -u%s -p%s -h%s - ...

  8. What Can Java Technology Do?

    What Can Java Technology Do? The general-purpose(多用途的), high-level Java programming language is a po ...

  9. WPS添加页码不是从首页开始

    A.页码从第二页开始 "插入"--"页码"--"格式"--不选"续前页"--"起始页码"设为0 &q ...

  10. js中获取URL中指定的查询字符串

    js中获取URL中指定的搜索字符串,主要利用location对象实现,废话少说,上代码. function getSearchString(key) { // 获取URL中?之后的字符 var str ...