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

来自天天博客: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. 每日学习总结<一> 2015-8-31

      Java : 抽象类的简单概念和意义: 包名:域名相反.例: com.eric.test; 访问权限: (public/default/private/protected) public: 可以修 ...

  2. Azure ARM (7) ARM Template - 使用Visual Studio编辑

    <Windows Azure Platform 系列文章目录> 之前介绍的ARM Template,都是使用文本编辑器来编辑JSON文件的. 文本讲介绍如何使用Visual Studio, ...

  3. Javascript动画效果(一)

    Javascript动画效果(一) 前面我们介绍了Javascript的回到顶部效果,今天呢,我们对Javascript动画做进一步的研究.在这篇博文中我们只介绍简单的匀速运动.简单的缓冲运动和简单的 ...

  4. 如何在Winform界面中设计图文并茂的界面

    在Winform里面,很多控件元素都是标准的,如图标.按钮.工具栏等等,所以一般设计标准的Winform界面比较快捷,但是往往这样的界面相对单调一些,特别在界面控件比较少的情况下,我们往往需要加入一些 ...

  5. Castle ActiveRecord相关错误

    1.Could not compile the mapping document: (string)错误? 如果确保配置文件没有错误,那请检查用户身份,必须是Administrator才行,即使有管理 ...

  6. 介绍开源的.net通信框架NetworkComms框架 源码分析(四)Packet

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  7. Mysql高并发优化

    一.数据库结构的设计 1.数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率. 2.能够用数字类型的字段尽量选择数字类型而不用字符串类型的 ...

  8. Quartz中的时间表达式介绍和常用表达式

    Quartz.NET是一个开源的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不 ...

  9. hibernate 注释说明

    * @Entity -- 将一个类声明为一个实体 bean(即一个持久化 POJO 类) * @Id -- 注解声明了该实体 bean 的标识属性(对应表中的主 键). * @Table -- 注解声 ...

  10. 【算法和数据结构】_12_小算法_abs_fabsf_fabsd_大端小端判断

    最近学习要用到求绝对值函数,看了一下有很多种的abs函数,因此想自己实现这些代码. 下面是我进行测试的代码: #include <stdio.h> typedef unsigned int ...