android andmore项目,安卓RecyclerView高阶使用详解(多套布局,加载更多,监听)

先来一张简单的效果图,实现了多套布局,以及滑到底部时的加载更多,内含监听自定义设置。

7385e2bbb365

效果图.gif

实现原理##

1.多套布局

利用RecyclerView的特性==》必须实现的ViewHolder类,在定义RecyclerView.Adapter时,在内部实现多个ViewHolder的类,根据不同需求的布局,获取到View后,分别在不同的ViewHolder中进行管理,处理数据时自动判断加载哪个布局。

2.加载更多

给RecyclerView设置滑动监听OnScrollListener,并重写里面的onScrollStateChanged和onScrolled方法,在RecyclerView的Item监听滑动到底部时,加载动画,并为Item添加数据,刷新适配器显示。

3.点击事件

在Adapter内部定义回调接口,onBindViewHolder中为需要设置监听的某个 view或者整条Item返回数据给调用者。

一,定义好RecyclerView

在Xml中文件使用

android:id="@+id/myRecycler"

android:layout_width="match_parent"

android:layout_height="match_parent">

如果发现报错,找不到该View的话,需要在依赖中引入RecyclerView,以及待会用到的进度条。

compile 'com.android.support:support-v4:25.0.1'

compile 'com.android.support:design:25.0.1'

compile 'com.android.support:recyclerview-v7:25.0.1'

compile 'com.android.support:cardview-v7:25.0.1'

compile 'com.pnikosis:materialish-progress:1.7'

在Activity中找到该RecyclerView后,需要设置如下属性

public class MainActivity extends AppCompatActivity {

private RecyclerView myRecyclerView;

private LinearLayoutManager mLayoutManager;

private MyRecyclerAdapter adapter;

private boolean isLoading;

private Handler handler = new Handler();

private List mEntity = new ArrayList<>();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

myRecyclerView = (RecyclerView) findViewById(R.id.myRecycler);

mLayoutManager = new LinearLayoutManager(this);

myRecyclerView.setLayoutManager(mLayoutManager);

setMyAdapter();

loading();

}

这里我为RecyclerView 设置了一个setLayoutManager的参数传入了LinearLayoutManager 的一个对象,这个参数是设置RecyclerView应该以什么样的形态出现,有三种形式:

LinearLayoutManager==》普通列表型Item布局

GridLayoutManager==》Grid图片浏览型Item布局

StaggredGridLayoutManager==》瀑布流型Item布局

这里主要演示LinearLayoutManager,在XML中写好自己需要的布局。代码就不一一展示了,如图效果中一样,共三种布局。这里就有一个新型的进度条显示的Xml介绍给大家,我用于最底部的加载更多显示。

android:layout_width="match_parent"

android:layout_height="40dp"

android:gravity="center"

android:orientation="horizontal">

android:layout_marginRight="10dp"

android:id="@+id/rcv_load_more"

android:layout_width="30dp"

android:layout_height="30dp"

android:layout_gravity="center"

wheel:matProg_barColor="#039ae4"

wheel:matProg_progressIndeterminate="true" />

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center"

android:text="正在加载更多..."

android:textColor="@android:color/darker_gray" />

二,创建Adapter

因为分开写怕大家看不懂,所以直接贴上源码,详细介绍在里面的备注中可以看到。

public class MyRecyclerAdapter extends RecyclerView.Adapter implements View.OnClickListener {

public final static int TYPE_FOOTER = 2;//加载更多的布局,进度条显示

public final static int TYPE_NORMAL = 1;//Item的第一种布局

public final static int TYPE_NORTWO = 3;//Item的第二种布局

private Context mContext;

private List mEntity;

private MyRecyclerAdapter.OnRecyclerViewItemClickListener mOnItemClickListener = null;

public interface OnRecyclerViewItemClickListener {

void onItemClick(View view, int position);

}

public MyRecyclerAdapter(Context mContext) {

this.mContext = mContext;

}

//构造函数,用于接收Context和传进来的数据

public MyRecyclerAdapter(Context mContext, List mEntity_WenTiList) {

this.mContext = mContext;

this.mEntity = mEntity_WenTiList;

}

//这里的监听是为了接收外面传递点击事件的数据

public void onClick(View v) {

if (mOnItemClickListener != null) {

//注意这里使用getTag方法获取数据

mOnItemClickListener.onItemClick(v, (int) v.getTag());

}

}

//自定义的Item响应事件需要接收OnRecyclerViewItemClickListener接口的函数

public void setOnItemClickListener(MyRecyclerAdapter.OnRecyclerViewItemClickListener listener) {

this.mOnItemClickListener = listener;

}

//重写getItemViewType方法,接收不同的position信息,根据自己数据,判断来返回给onCreateViewHolder,选择加载的View布局

@Override

public int getItemViewType(int position) {

if (mEntity.get(position) == null) {

//这个Null是在第一波数据完结时,添加进来的,作为判断加载更多的条件

return TYPE_FOOTER;

} else if (position == 3 || position == 5 || position == 9 || position == 13 || position == 14 || position == 19) {

return TYPE_NORTWO;

} else {

return TYPE_NORMAL;

}

}

//根据不同的需求返回View布局

@Override

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

RecyclerView.ViewHolder vh;

View view;

switch (viewType) {

default:

case TYPE_NORMAL:

view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_wenti_recycler, parent, false);

vh = new MyRecyclerAdapter.WenTiHolder(view);

return vh;

case TYPE_NORTWO:

view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image_recycler, parent, false);

vh = new MyRecyclerAdapter.TwoHolder(view);

return vh;

case TYPE_FOOTER:

view = LayoutInflater.from(parent.getContext()).inflate( R.layout.recyclerview_footer, parent, false);

vh = new FooterViewHolder(view);

return vh;

}

}

//这里需要注意的是因为接收的ViewHolder 有三种不同的类型,所以应该分开来处理。

@Override

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

if (holder instanceof FooterViewHolder) {

((FooterViewHolder) holder).rcvLoadMore.spin();

return;

}

if (holder instanceof WenTiHolder) {

WenTiHolder newHolder = (WenTiHolder) holder;

//给整条Item添加点击事件,因为是自定义的,可以写多种点击事件,或者点击限制等。

newHolder.itemView.setTag(position);

newHolder.itemView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//接收到点击事件后,返回给外部数据回调

mOnItemClickListener.onItemClick(v, position);

}

});

}

if (holder instanceof TwoHolder) {

TwoHolder newHolder = (TwoHolder) holder;

newHolder.itemView.setTag(position);

newHolder.itemView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mOnItemClickListener.onItemClick(v, position);

}

});

}

}

//获取数据长度Item的个数

@Override

public int getItemCount() {

if (mEntity != null) {

return mEntity.size();

} else {

return 0;

}

}

/** * 第一种布局 */

class WenTiHolder extends RecyclerView.ViewHolder {

public WenTiHolder(View itemView) {

super(itemView);

}

}

/** * 第二种布局 */

class TwoHolder extends RecyclerView.ViewHolder {

public TwoHolder(View itemView) {

super(itemView);

}

}

/** * 底部加载更多 */

class FooterViewHolder extends RecyclerView.ViewHolder {

private ProgressWheel rcvLoadMore;

public FooterViewHolder(View itemView) {

super(itemView);

rcvLoadMore = (ProgressWheel) itemView.findViewById(R.id.rcv_load_more);

}

}

}

三,绑定适配器设置加载更多

因为没写网络请求,就随意添加一堆数据,需要注意的是在结尾时,我添加了一个Null,在前面适配器中判断是否是加载更多布局的时候是判断Null值,所以我直接手动添加一个,不得省略。

public List iniData() {

Info info = new Info();

for (int i = 0; i < 10; i++) {

info.setBq(i + 1 + "");

info.setContext("aa");

info.setTime("14:11");

info.setTitle("bjnsdkjas");

mEntity.add(info);

} mEntity.add(null);

return mEntity;

}

在Activity中,添加设配器设置,这里回调了我们自定义的监听设置,在接口中只返回了点击的Item,但也足够我们拿到所有的List数据了,可以在Click中进行自己需要的操作。

//添加适配器设置

private void setMyAdapter(){

adapter = new MyRecyclerAdapter(this, iniData());

adapter.setOnItemClickListener(new MyRecyclerAdapter.OnRecyclerViewItemClickListener() {

@Override

public void onItemClick(View view, int position) {

}

});

myRecyclerView.setAdapter(adapter);

}

下面是加载更多的代码

//加载更多,每次10条

private void loading() {

myRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

@Override

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

}

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

int lastVisibleItemPosition = mLayoutManager.findLastVisibleItemPosition();

if (lastVisibleItemPosition + 1 == adapter.getItemCount()) {

if (!isLoading) {

isLoading = true;

handler.postDelayed(new Runnable() {

@Override

public void run() {

mEntity.remove(mEntity.size() - 1);

iniData();

adapter.notifyDataSetChanged();

isLoading = false;

}

}, 3000);

}

}

}

});

}

直接给RecyclerView添加滑动的状态监听,里面实现了滑动状态,以及滑动到底部时的状态,判断适配器中数据的长度,再进行对当前最底部的Item比较,如果是最后一条,则会在3秒内收到消息,可以在子线程中重新加载数据,我是直接为Info类Add了10条数据,注意添加前,要把以前添加的Null值删除。然后刷新适配器。完成加载更多,重置布尔值,下次滑动到底部重复以上操作。

结语

因为RecyclerView中自带了一种下拉刷新的控件,比较简单,我就不介绍在项目中。

花了一整下午的时间写的Damo,手打简书。觉得有用,喜欢的请点个赞!想看更多安卓知识请关注我。因为才开始写文章不久,如有不理解和不足之处,欢迎评论留言,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值