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

来自天天博客: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. JavaScript中,提取子字符串方法:Slice、Substring、Substr的比较。

    在JavaScript中,提取子字符串主要是通过 Slice.Substring.Substr 三个方法之一. // slice // 语法: string.slice(beginSlice [, e ...

  2. Azure Redis Cache (4) 配置和管理Redis Cache

    <Windows Azure Platform 系列文章目录> 我们在创建完Azure Redis Cache后,经常需要切换Redis Cache的服务级别,这里我简单介绍一下使用Azu ...

  3. 12套有用的免费 PSD 格式 Android UI 素材

    在这里,我们向大家呈现一些有用的和免费的 Android 用户界面 PSD 素材.由于 Android 市场迅速增长,设计人员和开发人员正在寻找一些快速和容易的方法来创建 Android 友好的应用和 ...

  4. SQL Server如何在变长列上存储索引

    这篇文章我想谈下SQL Server如何在变长列上存储索引.首先我们创建一个包含变长列的表,在上面定义主键,即在上面定义了聚集索引,然后往里面插入80000条记录: -- Create a new t ...

  5. 使用Python进行GUI操作自动化

    前言 本文介绍怎样使用Python进行跨平台的GUI操作的,其中使用的一个工具包是pyautogui,PyAutoGUI可以模拟鼠标的移动.点击.拖拽,键盘按键输入.按住操作,以及鼠标+键盘的热键同时 ...

  6. 30天C#基础巩固------读写流(StreamWrite/StreamReader)

    一:读写流的一些案例. --->关于StreamWrite       这里的一些常用的方法和我们之前的那个FileStream是一样的,参数很多都是一样的用法. Console.WriteLi ...

  7. Node.js系列基础学习-----回调函数,异步

    Node.js基础学习 Node.js回调函数 Node.js异步编程的直接体现就是回调,异步编程依托回调来实现,但不是异步.回调函数在完成任务后就会被调用,Node有很多的回调函数,其所有的API都 ...

  8. C语言学习003:Hello 指针

    在C中使用指针的原因 避免副本 在函数调用的时候,可以只传递数据的引用,而不用传递数据 数据共享 两段代码可以同时操作同一份数据,而不是两份独立的副本 使用指针读写数据 #include <st ...

  9. 呼叫外部js文件并使用其内部方法

    很久没有学习jQuery了,都快忘记了.今天学习一个小功能,使用jQuery的$.getScript()方法,是读取外部js文件,读取之后,并执行js文件内的一个方法. 首先我们创建这个js文件,如i ...

  10. SSH服务器与Android通信(3)--Android客户端发送数据

    Android客户端向SSH服务器发送数据主要有三种情况:通过客户端删除数据.添加数据和修改数据. 1.删除数据 先看看jsp文件里面是怎样删除数据的: <td align="cent ...