前言
RecycleView功能已经非常强大了,可以说它已经是ListView的替代品,而它的刷新XRecycleView也刚好是XListView的替代品,下面就是实现在Xutils框架下的XRecycleView的刷新,监听和下划线设置。
(对于Xutils不了解的可以参考:http://blog.youkuaiyun.com/qiaoshi96_bk/article/details/74613542)
依赖,权限
由于XRecycleView是v7的所以在使用该方法的时候我们必须导入依赖
compile 'com.jcodecraeer:xrecyclerview:1.3.2'
当然如果你需求里没有刷新的话,我们可以导入
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
还有Xutils的依赖
compile 'org.xutils:xutils:3.5.0'
因为是网络请求还得导入Gson解析的依赖
compile 'com.google.code.gson:gson:2.8.1'
在清单文件配置网络请求的权限
<uses-permission android:name="android.permission.INTERNET" />
到这里我们的准备工作就差不多完成了下面可以进行我们的功能操作了
XRecycleView的数据适配
注意点
由于我们是用Xutils框架的所以当创建App类时千万不要忘记在清单文件里加上引用如下:
在Application加上
android:name=".App"
布局
activity_main.xml里面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.ggrecycle.MainActivity">
<com.jcodecraeer.xrecyclerview.XRecyclerView
android:id="@+id/x_recyc"
android:layout_width="match_parent"
android:layout_height="match_parent"></com.jcodecraeer.xrecyclerview.XRecyclerView>
</LinearLayout>
子布局first_item 里
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/f_item"
android:layout_width="match_parent"
android:layout_height="160dp" />
<TextView
android:id="@+id/f_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
可见和ListView一样只是简单的布局。
代码
MainActivity中
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
private String path="http://app.u17.com/v3/appV3_3/android/phone/list/commonComicList?argValue=23&argName=sort&argCon=0&page=1&android_id=4058040115108878&v=3330110&model=GT-P5210&come_from=Tg002";
@ViewInject(R.id.x_recyc)
XRecyclerView recyclerView;
List<First_User.DataBean.ReturnDataBean.ComicsBean> list;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
x.view().inject(this);
list=new ArrayList<>();
// 指定RecycleView的布局方式
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
adapter = new MyAdapter(list);
recyclerView.setAdapter(adapter);
getDate();
}
private void getDate() {
RequestParams params = new RequestParams(path);
x.http().get(params, new Callback.CacheCallback<String>() {
@Override
public void onSuccess(String result) {
Gson gson = new Gson();
First_User user = gson.fromJson(result, First_User.class);
list.addAll(user.getData().getReturnData().getComics());
adapter.notifyDataSetChanged();
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
@Override
public boolean onCache(String result) {
return false;
}
});
}
}
可以看到这里面代码和ListView基本上一样唯一不同的是:
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
多了上面这两行代码,其实这两行就是用来指定RecycleView的布局方式,是必须得写的,这里写LinearLayoutManager就是和普通的ListView相似
适配器: MyAdapter
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<First_User.DataBean.ReturnDataBean.ComicsBean> list;
public MyAdapter(List<First_User.DataBean.ReturnDataBean.ComicsBean> list) {
this.list = list;
}
//初始化时
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 加载我们的子布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.first_item,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
//绑定成功
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyViewHolder){
MyViewHolder my= (MyViewHolder) holder;
my.title.setText(list.get(position).getName());
x.image().bind(my.imageView,list.get(position).getCover());
}
}
//返回集合里面的条目总数
@Override
public int getItemCount() {
return list.size();
}
// 创建自己的ViewHolder
static class MyViewHolder extends RecyclerView.ViewHolder{
@ViewInject(R.id.f_item)
ImageView imageView;
@ViewInject(R.id.f_title)
TextView title;
public MyViewHolder(View itemView) {
super(itemView);
x.view().inject(this,itemView);
}
}
}
可以看到RecycleView的适配器和ListView有很大的变化,其实只是RecycleView是把优化封装好的,也是必须要优化,所以我们才必须继承 RecyclerView.Adapter 里的RecyclerView.ViewHolder
然后重写里面的三个方法
- onCreateViewHolder(ViewGroup parent, int viewType)
- onCreateViewHolder:创建ViewHolder实例,把我们自己的MyViewHolder放入里面
- onBindViewHolder(RecyclerView.ViewHolder holder, int position)
- onBindViewHolde:这个方法就是对RecycleView里面的子布局进行赋值操作
- getItemCount()
- getItemCount():这个好理解就是返回list集合里面的条目总数
还有我们自定义的MyViewHolder
- getItemCount():这个好理解就是返回list集合里面的条目总数
static class MyViewHolder extends RecyclerView.ViewHolder{
@ViewInject(R.id.f_item)
ImageView imageView;
@ViewInject(R.id.f_title)
TextView title;
public MyViewHolder(View itemView) {
super(itemView);
x.view().inject(this,itemView);
}
}
这里是我们自己创建的MyViewHolder ,我们的子布局获取id都是在里面操作的。
到这里简单的RecycleView展示数据就完成了,效果如下
下拉刷新上拉加载
对于刷新控件XRecycleView已经帮我封装好了,所以我们只需要实现 XRecyclerView.LoadingListener
并且重写onRefresh(),onLoadMore()两个方法,
//刷新
@Override
public void onRefresh() {
//清空集合
list.clear();
page=1;
getDate();
adapter.notifyDataSetChanged();
}
//加载更多
@Override
public void onLoadMore() {
page++;
getDate();
adapter.notifyDataSetChanged();
}
同时要在onCreate里面设置
// 对XRecycleView设置可以加载和刷新
recyclerView.setLoadingListener(this);
recyclerView.setPullRefreshEnabled(true);
//设置刷新风格
recyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallPulseRise);
当然这里的刷新样式有很多种详情:
https://github.com/jianghejie/XRecyclerView
最后只需要在Xutils里的onfinish()里
recyclerView.loadMoreComplete();
recyclerView.refreshComplete();
到这里它的刷新和加载更多就基本实现了。
XrecycleView的监听
由于XUtils是没有事件的监听的,所以如果我们想要对我们的控件实现监听就必须得自己定义接口,并通过回调来实现。
所以在我们的MyAdapter里面需要写接口
/**
* 点击事件回掉接口
*/
public interface OnItemClickListener {
void onItemClick(View var2, int var3);
void onImageClick(View view, int pos);
}
然后在onBindViewHolder判断并调用接口
if (holder instanceof MyViewHolder){
MyViewHolder my= (MyViewHolder) holder;
my.title.setText(list.get(position).getName());
x.image().bind(my.imageView,list.get(position).getCover());
// 设置整根条目的监听
my.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener!=null){
listener.onItemClick(view,position);
}
}
});
// 设置单个监听
my.imageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (listener!=null){
listener.onImageClick(view,position);
}
return true;
}
});
}
}
最后千万不要忘记定义构造方法来设置监听:
OnItemClickListener listener;//定义监听事件
/**
* 设置监听事件
*
* @param listener
*/
public void setListener(OnItemClickListener listener) {
this.listener = listener;
}
在我们住方法里面
既然是通过接口来实现监听如何我们想要自定义我们的监听事先当然得实现接口,所以首先我们得
实现MyAdapter.OnItemClickListener,我们自己写的接口,并重写里面的两个方法
@Override
public void onItemClick(View var2, int var3) {
Toast.makeText(MainActivity.this,"点击了整个条目",Toast.LENGTH_SHORT).show();
}
@Override
public void onImageClick(View view, int pos) {
Toast.makeText(MainActivity.this,"长按了图片",Toast.LENGTH_SHORT).show();
}
最后千万不要忘记在我们等Oncreate里面加上:
adapter.setListener(this);
到这里我们的监听事件也就完全实现了。
设置下滑线
定义MyLine类
RecycleView为我们提供ItemDecoration方法,所以我们可以通过继承它来为我们的对我们RecycleView进行修饰:
public class MyLine extends RecyclerView.ItemDecoration {
Drawable drawable;
public MyLine(Context context, int resId) {
drawable=context.getResources().getDrawable(resId);
}
//设置item之间的边距
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(8,8,8,8);
}
//重写方法来实现自定义布局
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
// 绘制分割线
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for(int i=0;i<childCount;i++){
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
//以下计算主要用来确定绘制的位置
final int top = child.getBottom() + params.bottomMargin;
//注意这边drawable.getIntrinsicHeight()必须有高度
final int bottom = top + drawable.getIntrinsicHeight();
drawable.setBounds(left,top,right,bottom);
drawable.draw(c);
// 绘制虚线
// Paint paint = new Paint();
// paint.setStyle(Paint.Style.STROKE);
// paint.setColor(Color.RED);
// Path path = new Path();
// path.moveTo(left, top);
// path.lineTo(right,top);
// PathEffect effects = new DashPathEffect(new float[]{15,15,15,15},5);//此处单位是像素不是dp 注意 请自行转化为dp
// paint.setPathEffect(effects);
// c.drawPath(path, paint);
// drawable.setBounds(left,top,right,bottom);
// drawable.draw(c);
}
}
}
MainActivity中
其实在我们的MainActivity中只需要一步就可以实现我们的分割线了:
// 设置条目之间的下划线
recyclerView.addItemDecoration(new MyLine(this,R.drawable.item_line));
但是我们需要:R.drawable.item_line
很显然我们需要定义一个xml文件来写我们分割线的属性(颜色,宽度等):
所以我们在drawable下面定义item_line
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#66a92b"></solid>
<size android:height="2dp"></size>
</shape>
到这里我们的所有功能都实现了
最终效果如下:
代码
这里贴上MainActivity和MyAdapter里面的代码
MainActivity
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity implements XRecyclerView.LoadingListener,MyAdapter.OnItemClickListener{
int page=1;
private String path="http://app.u17.com/v3/appV3_3/android/phone/list/commonComicList?argValue=23&argName=sort&argCon=0&android_id=4058040115108878&v=3330110&model=GT-P5210&come_from=Tg002&page=";
@ViewInject(R.id.x_recyc)
XRecyclerView recyclerView;
List<First_User.DataBean.ReturnDataBean.ComicsBean> list;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
x.view().inject(this);
list=new ArrayList<>();
// 指定RecycleView的布局方式
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
adapter = new MyAdapter(list);
recyclerView.setAdapter(adapter);
recyclerView.setLoadingListener(this);
recyclerView.setLoadingMoreEnabled(true);
//设置刷新风格
recyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallPulseRise);
// 设置条目之间的下划线
recyclerView.addItemDecoration(new MyLine(this,R.drawable.item_line));
adapter.setListener(this);
getDate();
}
private void getDate() {
RequestParams params = new RequestParams(path+page);
x.http().get(params, new Callback.CacheCallback<String>() {
@Override
public void onSuccess(String result) {
Gson gson = new Gson();
First_User user = gson.fromJson(result, First_User.class);
list.addAll(user.getData().getReturnData().getComics());
adapter.notifyDataSetChanged();
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
recyclerView.loadMoreComplete();
recyclerView.refreshComplete();
}
@Override
public boolean onCache(String result) {
return false;
}
});
}
//刷新
@Override
public void onRefresh() {
list.clear();
page=1;
getDate();
adapter.notifyDataSetChanged();
}
//加载更多
@Override
public void onLoadMore() {
page++;
getDate();
adapter.notifyDataSetChanged();
}
@Override
public void onItemClick(View var2, int var3) {
Toast.makeText(MainActivity.this,"点击了整个条目",Toast.LENGTH_SHORT).show();
}
@Override
public void onImageClick(View view, int pos) {
Toast.makeText(MainActivity.this,"长按了图片",Toast.LENGTH_SHORT).show();
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<First_User.DataBean.ReturnDataBean.ComicsBean> list;
public MyAdapter(List<First_User.DataBean.ReturnDataBean.ComicsBean> list) {
this.list = list;
}
OnItemClickListener listener;//定义监听事件
/**
* 设置监听事件
*
* @param listener
*/
public void setListener(OnItemClickListener listener) {
this.listener = listener;
}
//初始化时
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 加载我们的子布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.first_item,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
//绑定成功
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof MyViewHolder){
MyViewHolder my= (MyViewHolder) holder;
my.title.setText(list.get(position).getName());
x.image().bind(my.imageView,list.get(position).getCover());
// 设置整根条目的监听
my.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener!=null){
listener.onItemClick(view,position);
}
}
});
// 设置单个监听
my.imageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (listener!=null){
listener.onImageClick(view,position);
}
return true;
}
});
}
}
//返回集合里面的条目总数
@Override
public int getItemCount() {
return list.size();
}
// 创建自己的ViewHolder
static class MyViewHolder extends RecyclerView.ViewHolder{
@ViewInject(R.id.f_item)
ImageView imageView;
@ViewInject(R.id.f_title)
TextView title;
public MyViewHolder(View itemView) {
super(itemView);
x.view().inject(this,itemView);
}
}
/**
* 点击事件回掉接口
*/
public interface OnItemClickListener {
void onItemClick(View var2, int var3);
void onImageClick(View view, int pos);
}
}