介绍
RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:
-
使用LayoutManager来确定每一个item的排列方式。
-
为增加和删除项目提供默认的动画效果。
你也可以定义你自己的LayoutManager和添加删除动画
-
Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。
-
LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。
目前SDK中提供了三种自带的LayoutManager:
-
LinearLayoutManager
-
GridLayoutManager
-
StaggeredGridLayoutManager
第一节、简单的RecyclerView使用方法
1、添加依赖
在AS的build.gradle
中添加依赖,然后同步一下就可以引入依赖包:
compile 'com.jcodecraeer:xrecyclerview:1.3.2'
2、编写代码
添加完依赖之后,就开始写代码了,与ListView用法类似,也是先在xml布局文件中创建一个RecyclerView的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.bwie.day06_recyclerview.MainActivity">
<com.jcodecraeer.xrecyclerview.XRecyclerView
android:id="@+id/re"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"></com.jcodecraeer.xrecyclerview.XRecyclerView>
</RelativeLayout>创建适配器
public class Adaper extends RecyclerView.Adapter <Adaper.MyViewHolder>{
Context con;
List<User> list=new ArrayList<>();
private Ondianji ondianji;
public Adaper(Context con, List<User> list) {
this.con = con;
this.list = list;
}
//创建ViewHolder的时候
//实例化ViewHolder
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//条目布局
View view = LayoutInflater.from(con).inflate(R.layout.aa, null);
//实例化ViewHolder ,将布局传入
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
//当绑定ViewHolder的时候
//给控件设置数据
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.getIv().setImageResource(list.get(position).getTu());
holder.getTv().setText(list.get(position).getName());
if(ondianji!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//调用接口里面的方法
//传入的条目位置索引应该使用getLayoutPosition()(getPosition()被抛弃)方法来获取,
//这样就不会出现条目紊乱。
//获取真正的下标
int i=holder.getLayoutPosition;
ondianji.diji(holder.itemView,i);
}
});
}
}
@Override
public int getItemCount() {
return list.size();
}
//ViewHolder 用于优化
class MyViewHolder extends RecyclerView.ViewHolder{
private ImageView iv;
private TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
this.iv=itemView.findViewById(R.id.iv);
this.tv=itemView.findViewById(R.id.tv);
}
public ImageView getIv() {
return iv;
}
public void setIv(ImageView iv) {
this.iv = iv;
}
public TextView getTv() {
return tv;
}
public void setTv(TextView tv) {
this.tv = tv;
}
}
//定义接口,实现条目点击事件
public interface Ondianji{
void diji(View view,int position);
}
//定义方法,供外部访问
public void diao(Ondianji ondianji){
this.ondianji=ondianji;
}
//定义添加的方法
public void addUser(User u,int position){
list.add(position,u);
//更新适配器
notifyItemInserted(position);//参数,位置,在那里插入了数据
}
//定义删除的方法
public void deleUser(int position){
list.remove(position);
notifyItemRemoved(position);
}
}
//在activity
public class MainActivity extends AppCompatActivity{ private RecyclerView re; int[] img={R.drawable.b_05,R.drawable.b_07,R.drawable.b_09,R.drawable.b_11,R.drawable.mqq}; private Adaper m; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建集合 List<User> list=new ArrayList<>(); //通过ID获取控件 re = findViewById(R.id.recyclerView); //初始化数据 for (int i = 0; i <36 ; i++) { User user = new User("小美妞" + i, img[i % img.length]); list.add(user); } //设置布局管理器 re.setLayoutManager(new LinearLayoutManager(MainActivity.this)); //自条目分割线
//设置动画re.addItemDecoration(new MyDecoration(this, MyDecoration.VERTICAL_LIST)); re.setPullRefreshEnabled(true);//下拉刷新 re.setLoadingMoreEnabled(true);//上拉加载
re.setItemAnimator(new DefaultItemAnimator());
//设置适配器 m = new Adaper(this,list);
re.setAdapter(m);
re.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
//上拉刷新
page=1;
pre.goodszhongjianren(goods_url,Goods.this,new ShixianiModel(),Goods.this);
re.refreshComplete(); }
//下拉加载更多
@Override
public void onLoadMore() {
++page;
Log.e("TAG",""+page);
pre.goodszhongjianren(goods_url,Goods.this,new ShixianiModel(),Goods.this);
re.loadMoreComplete(); }});
//设置条目点击事件
m.diao(new Adaper.Ondianji() {
@Override
public void diji(View view, int position) {
Toast.makeText(MainActivity.this,"??!!!"+position,Toast.LENGTH_SHORT).show();
//新建一个对象 User u=new User("赵子龙",R.mipmap.ic_launcher);
//直接调用适配器自己定义的添加方法
//m.addUser(u,position);
//调用删除的方法
m.deleUser(position);
}
});
}}
//自条目分割线自定义类
public class MyDecoration extends RecyclerView.ItemDecoration {
private Context mContext;
private Drawable mDivider;
private int mOrientation;
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
//我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置
public static final int[] ATRRS = new int[]{
android.R.attr.listDivider
};
public MyDecoration(Context context, int orientation) {
this.mContext = context;
final TypedArray ta = context.obtainStyledAttributes(ATRRS);
this.mDivider = ta.getDrawable(0);
ta.recycle();
setOrientation(orientation);
}
//设置屏幕的方向
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == HORIZONTAL_LIST) {
drawVerticalLine(c, parent, state);
} else {
drawHorizontalLine(c, parent, state);
}
}
//画横线, 这里的parent其实是显示在屏幕显示的这部分
public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
//获得child的布局信息
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
//Log.d("wnw", left + " " + top + " "+right+" "+bottom+" "+i);
}
}
//画竖线
public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state) {
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
//获得child的布局信息
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
//由于Divider也有长宽高,每一个Item需要向下或者向右偏移
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == HORIZONTAL_LIST) {
//画横线,就是往下偏移一个分割线的高度
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
//画竖线,就是往右偏移一个分割线的宽度
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
//3种布局方式
//一行
1.LinearLayout
recyclerView .setLayoutManager(newLinearLayoutManager(FirstActivity.this,LinearLayoutManager.HORIZONTAL,false));2.GridLayout
re.setLayoutManager(new GridLayoutManager(FirstActivity.this,3, OrientationHelper.HORIZONTAL,false));3.瀑布流
re.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.HORIZONTAL));
//子布局
<?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="150dp"> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="110dp" /> <TextView android:id="@+id/l_tv" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>