recyclerview怎么添加头部和尾部以及上啦刷新

recyclerview怎么添加头部和尾部以及上啦刷新,第1张

有两种使用RecyclerViewHeader的方法

普通方法

(使用起来非常简单,但是它会添加额外的布局,因此效率略低于第二种方法):

为header创建一个xml布局(可以包括任意view或者ViewGroup)

<FrameLayout

android:layout_width="match_parent"

android:layout_height="100dp">

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:text="header"/>

</FrameLayout>

使用静态初始方法从xml中创建RecyclerViewHeader

RecyclerViewHeader header = RecyclerViewHeader.fromXml(context, R.layout.header)

将RecyclerViewHeader Attach 到RecyclerView,搞定!

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view)

// set LayoutManager for your RecyclerView

header.attachTo(recyclerView)

Header-already-aligned approach (不会引入任何额外布局):

将RecyclerViewHeader布局放在RecyclerView的上层。

<FrameLayout

android:layout_width="match_parent"

android:layout_height="wrap_content">

<android.support.v7.widget.RecyclerView

android:id="@+id/recycler"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal|top" />

<com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader

android:id="@+id/header"

android:layout_width="match_parent"

android:layout_height="100dp"

android:layout_gravity="center_horizontal|top">

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:text="header"/>

</com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader>

</FrameLayout>

获得RecyclerViewHeader对象:

RecyclerViewHeader header = (RecyclerViewHeader) findViewById(R.id.header)

把RecyclerViewHeader赋予RecyclerView

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view)

// set LayoutManager for your RecyclerView

header.attachTo(recyclerView, true)

注意事项

RecyclerViewHeader必须在RecyclerView设置了LayoutManager之后调用。

目前该库适用于LinearLayoutManager,GridLayoutManager和StaggeredGridLayoutManager布局的RecyclerViews。

只支持垂直布局LayoutManager

RecyclerView 出来有很长一段时间了,相信大家对它已经很熟悉了,使用过它的朋友可能都会发现一点,就是 RecyclerView 不能添加 headerView 和 footView,这就让我们有点蛋疼了,也许你会说,没事啊,我们可以重写getItemViewType(int position)这个方法,让他实现多个布局,具体实现如下:

@Override

public int getItemViewType(int position) {

if (position == 0) {

return HEAD_VIEW

}else{

return BODY_VIEW

}

}

123456789

下面的 *** 作就不多讲了,这种方法相信大家在使用 ListView 的时候就非常熟练; 那既然可以通过以上方法实现,为什么还要写一个可以添加 HeaderView 和 FootView 的 RecyclerView ?其实这个问题不用回答,因为 ListView 也可以通过以上方法实现,但它还是有 addHeaderView和 addFootView 的方法,不过话说回来,通过 addHeaderView 实现的添加头部布局确实有不可代替的功能,比如,ListView 头部图片下拉放大动画;在调用 adapter.notifyDataSetChanged()头部数据是不会重新刷新的等等。

好了,接下来才是本文的主题内容,如何实现 RecyclerView 添加 HeaderView 和 FootView?

无从下手?没关系!ListView 不是已经帮我们实现了这样的功能吗,我们可以先看看 ListView 是如何实现的,

public void addHeaderView(View v, Object data, boolean isSelectable) {

final FixedViewInfo info = new FixedViewInfo()

info.view = v

info.data = data

info.isSelectable = isSelectable

mHeaderViewInfos.add(info)

mAreAllItemsSelectable &= isSelectable

// Wrap the adapter if it wasn't already wrapped.

if (mAdapter != null) {

if (!(mAdapter instanceof HeaderViewListAdapter)) {

mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter)

}

// In the case of re-adding a header view, or adding one later on,

// we need to notify the observer.

if (mDataSetObserver != null) {

mDataSetObserver.onChanged()

}

}

}

12345678910111213141516171819202122

以上方法核心代码就是

mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter)1

其他可以忽略不看;这里其实用到了一种设计模式的概念,好像是叫什么装饰模式吧,意思就是把原有的 Adapter 通过HeaderViewListAdapter这个包装类重新包装一次,把改增的地方增一增,该减的地方减一点;所以我们要关注的是HeaderViewListAdapter类是如何实现的,然后再依葫芦画瓢画一个包装 RecyclerView.Adapter的包装类!

解密HeaderViewListAdapter

这个包装类代码本来就不长,相信大家都能够理解的,这里就挑点重点讲一下

1、对Adapter 的 count 进行了重新计算,这个不用多解释吧!

public int getCount() {

if (mAdapter != null) {

return getFootersCount() + getHeadersCount() + mAdapter.getCount()

} else {

return getFootersCount() + getHeadersCount()

}

}

12345678

2、就是getView方法,这个方法是重点,如果当前 position 的位置比 HeaderView 的数量小,那么返回的就是 HeaderView 的 对应的 View,否则再判断 原 Adapter 的 count 与当前 position 的差值来比较,是调用原 Adapter 的 getView 方法,还是获取 footView 的 view;说白了这个方法的目的就是添加了头部和尾部 View。

public View getView(int position, View convertView, ViewGroup parent) {

// Header (negative positions will throw an IndexOutOfBoundsException)

int numHeaders = getHeadersCount()

if (position <numHeaders) {

return mHeaderViewInfos.get(position).view

}

// Adapter

final int adjPosition = position - numHeaders

int adapterCount = 0

if (mAdapter != null) {

adapterCount = mAdapter.getCount()

if (adjPosition <adapterCount) {

return mAdapter.getView(adjPosition, convertView, parent)

}

}

// Footer (off-limits positions will throw an IndexOutOfBoundsException)

return mFooterViewInfos.get(adjPosition - adapterCount).view

}1234567891011121314151617181920

对于这个包装类的其他方法只要注意一下就 没问题了,那么接下来,就是我们模仿的时刻了!

代码非常简单,这里就直接上了

1、包装类 RecyclerWrapAdapter

package moon.myapplication

import android.support.v7.widget.RecyclerView

import android.view.View

import android.view.ViewGroup

import java.util.ArrayList

/**

* Created by moon.zhong on 2015/7/20.

* time : 14:10

*/

public class RecyclerWrapAdapter extends RecyclerView.Adapter implements WrapperAdapter {

private RecyclerView.Adapter mAdapter

private ArrayList<View>mHeaderViews

private ArrayList<View>mFootViews

static final ArrayList<View>EMPTY_INFO_LIST =

new ArrayList<View>()

private int mCurrentPosition

public RecyclerWrapAdapter(ArrayList<View>mHeaderViews, ArrayList<View>mFootViews, RecyclerView.Adapter mAdapter) {

this.mAdapter = mAdapter

if (mHeaderViews == null) {

this.mHeaderViews = EMPTY_INFO_LIST

} else {

this.mHeaderViews = mHeaderViews

}

if (mHeaderViews == null) {

this.mFootViews = EMPTY_INFO_LIST

} else {

this.mFootViews = mFootViews

}

}

public int getHeadersCount() {

return mHeaderViews.size()

}

public int getFootersCount() {

return mFootViews.size()

}

@Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

if (viewType == RecyclerView.INVALID_TYPE) {

return new HeaderViewHolder(mHeaderViews.get(0))

} else if (viewType == RecyclerView.INVALID_TYPE - 1) {

return new HeaderViewHolder(mFootViews.get(0))

}

return mAdapter.onCreateViewHolder(parent, viewType)

}

@Override

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

int numHeaders = getHeadersCount()

if (position <numHeaders) {

return

}

int adjPosition = position - numHeaders

int adapterCount = 0

if (mAdapter != null) {

adapterCount = mAdapter.getItemCount()

if (adjPosition <adapterCount) {

mAdapter.onBindViewHolder(holder, adjPosition)

return

}

}

}

@Override

public int getItemCount() {

if (mAdapter != null) {

return getHeadersCount() + getFootersCount() + mAdapter.getItemCount()

} else {

return getHeadersCount() + getFootersCount()

}

}

@Override

public int getItemViewType(int position) {

mCurrentPosition = position

int numHeaders = getHeadersCount()

if (position <numHeaders) {

return RecyclerView.INVALID_TYPE

}

int adjPosition = position - numHeaders

int adapterCount = 0

if (mAdapter != null) {

adapterCount = mAdapter.getItemCount()

if (adjPosition <adapterCount) {

return mAdapter.getItemViewType(adjPosition)

}

}

return RecyclerView.INVALID_TYPE - 1

}

@Override

public long getItemId(int position) {

int numHeaders = getHeadersCount()

if (mAdapter != null &&position >= numHeaders) {

int adjPosition = position - numHeaders

int adapterCount = mAdapter.getItemCount()

if (adjPosition <adapterCount) {

return mAdapter.getItemId(adjPosition)

}

}

return -1

}

@Override

public RecyclerView.Adapter getWrappedAdapter() {

return mAdapter

}

private static class HeaderViewHolder extends RecyclerView.ViewHolder {

public HeaderViewHolder(View itemView) {

super(itemView)

}

}

}

2、为 RecyclerView 添加 AddHeaderView 和 addFootView 方法,重写 RecyclerView

package moon.myapplication

import android.content.Context

import android.support.v7.widget.RecyclerView

import android.util.AttributeSet

import android.view.View

import java.util.ArrayList

/**

* Created by moon.zhong on 2015/7/20.

* time : 15:14

*/

public class WrapRecyclerView extends RecyclerView {

private ArrayList<View>mHeaderViews = new ArrayList<>()

private ArrayList<View>mFootViews = new ArrayList<>()

private Adapter mAdapter

public WrapRecyclerView(Context context) {

super(context)

}

public WrapRecyclerView(Context context, AttributeSet attrs) {

super(context, attrs)

}

public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle)

}

public void addHeaderView(View view){

mHeaderViews.clear()

mHeaderViews.add(view)

if (mAdapter != null){

if (!(mAdapter instanceof RecyclerWrapAdapter)){

mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter)

//mAdapter.notifyDataSetChanged()

}

}

}

public void addFootView(View view){

mFootViews.clear()

mFootViews.add(view)

if (mAdapter != null){

if (!(mAdapter instanceof RecyclerWrapAdapter)){

mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter)

//mAdapter.notifyDataSetChanged()

}

}

}

@Override

public void setAdapter(Adapter adapter) {

if (mHeaderViews.isEmpty()&&mFootViews.isEmpty()){

super.setAdapter(adapter)

}else {

adapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,adapter)

super.setAdapter(adapter)

}

mAdapter = adapter

}

}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

到这里就实现了 RecyclerView 添加头部和尾部布局 ,用法很简单,其他步骤都不变,只需把 RecyclerView 换成WrapRecyclerView即可。

看看效果图

这篇文章没有什么创新的技术点,但却给广大程序员一个很好的思路:那就是模仿,最好是能自己动手,也许你看一遍就能理解,但是真正动手实践的时候你会发现很多问题!


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/bake/7985500.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-12
下一篇 2023-04-12

发表评论

登录后才能评论

评论列表(0条)

保存