回顾ListView
概述
一句话:在有限的空间中显示大量的列表集合的控件ListView的使用步骤(question)
1.数据集2.适配器Adapter备注:其实ListView是一个MVC的模式,
M--Model 数据集V--View ListViewC--Controller 适配器RecyclerView的介绍
概述
官方的介绍,该控件用于在有限的窗口中展示大量数据集。正如我们刚才介绍ListView和之前所学过的ListView
Google在2014年I/O大会上提出新的用于取代ListView的组件,相比ListView而言,它更加强大,而且非常灵活
原理以及结构图
官方结构图RecyclerView描述
与其它的View不一样的地方是RecyclerView不负责子view的展现和布局工作。即子view的位置、大小等都不由RecyclerView自己负责。它所关注的是子view的回收与复用,专注于性能的提升。而其它的工作如布局、子view的布局、子view的装饰、子view的动画都交给了其内部类来负责,下表展示了几个关键的内部类和它们的用途。RecyclerView的相关类
RecyclerView的初体验
3.设置适配器
(1) 准备适配器继承RecyclerView.Adapter(2)RecyclerView.Adapter中默认必须有ViewHolder,需要在Adapter中写一个内部类继承RecyclerView.ViewHolder示例代码如下:
* step: * 1. 继承RecyclerView.Adapter<VH extends ViewHolder> * 2. 在这个Adapter中写一个类继承RecyclerView.ViewHolder,并且传入Adapter的泛型 * 3. 实现 三个抽象方法 * getItemCount * onCreateViewHolder * onBindViewHolder * 4. 重写构造方法,参数传入 上下文Context 数据集 * ************************************************************* */public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.MyViewHolder> { PRivate List<String> mDatas = new ArrayList<>(); private Context mContext; private LayoutInflater mInflater; public LikeListAdapter(Context context, List<String> datas) { this.mInflater = LayoutInflater.from(context); mDatas = datas; this.mContext = context; } //返回RecyclerView总共有多少条 @Override public int getItemCount() { return mDatas == null ? 0 : mDatas.size(); } //初始化布局,创建ViewHolder @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //1. 初始化item的布局 View view = mInflater.inflate(R.layout.item_likelist, parent, false); //2. 创建出来ViewHolder对象 MyViewHolder myViewHolder = new MyViewHolder(view); return myViewHolder; } //绑定ViewHolder中的控件的数据 @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { String str = mDatas.get(position); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {// Toast.makeText(mContext, "pos:" + position, Toast.LENGTH_SHORT).show(); if (mListener != null) { mListener.onItemClick(position, holder.itemView); } } }); //瀑布流展示// Random random = new Random();// int height = random.nextInt(100) + 100;// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);// ViewGroup.LayoutParams layoutParams = holder.tv_test.getLayoutParams();// layoutParams.height = height;// holder.tv_test.setLayoutParams(layoutParams); holder.tv_test.setText(str); } public class MyViewHolder extends RecyclerView.ViewHolder { private TextView tv_test; public MyViewHolder(View itemView) { super(itemView); tv_test = (TextView) itemView.findViewById(R.id.tv_test); } } //增加一条数据 public void insertData(int pos, String data) { mDatas.add(pos, data); notifyItemInserted(pos); } //删除一条数据 public void removeData(int pos) { mDatas.remove(pos); notifyItemRemoved(pos); } public interface OnItemClickListener { void onItemClick(int pos, View view); } private OnItemClickListener mListener; public void setOnItemClickListener(OnItemClickListener listener) { this.mListener = listener; }}(4)设置布局管理器LayoutManager
LinearLayoutManager线性布局GridLayoutManager网格布局StaggeredGridLayoutManager瀑布流布局public class LikeListActivity extends AppCompatActivity { private List<String> mDatas = new ArrayList<>(); private RecyclerView mRecyclerView; private Button btn_add; private Button btn_remove; private LikeListAdapter mAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_likelist); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); btn_add = (Button) findViewById(R.id.btn_add); btn_remove = (Button) findViewById(R.id.btn_remove); //1.准备数据集 for (int i = 0; i < 50; i++) { mDatas.add("data:" + i); } //2.初始化Adapter mAdapter = new LikeListAdapter(this, mDatas); mRecyclerView.setAdapter(mAdapter); //3.创建出来LayoutManager //3.1 线性布局: 第二个参数是 列表展现的方向,有竖直的LinearLayoutManager.VERTICAL 和 水平的LinearLayoutManager.HORIZONTAL // 第三个参数: 是否 从最后展示 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); //3.2 网格布局: 参数2是 表示这个网格布局的列数 或者行数 GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false); //3.3 瀑布流布局 StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(linearLayoutManager); //给RecyclerView增加一些动画效果// mRecyclerView.setItemAnimator(new DefaultItemAnimator()); //1. build.gradle中引入 : compile 'jp.wasabeef:recyclerview-animators:2.2.5' //2. 添加动画效果 : setItemAnimator(动画效果的类例如: SlideInLeftAnimator, SlideInRightAnimator); mRecyclerView.setItemAnimator(new LandingAnimator()); //3. 改变动画的时长: 有四个: // recyclerView.getItemAnimator().setAddDuration(1000); //recyclerView.getItemAnimator().setRemoveDuration(1000); //recyclerView.getItemAnimator().setMoveDuration(1000); //recyclerView.getItemAnimator().setChangeDuration(1000); mRecyclerView.getItemAnimator().setAddDuration(3000); //增加一条数据 btn_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mAdapter.insertData(1, "新增加的数据"); } }); //删除一条数据 btn_remove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mAdapter.removeData(1); } });// mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); mAdapter.setOnItemClickListener(new LikeListAdapter.OnItemClickListener() { @Override public void onItemClick(int pos, View view) { Toast.makeText(LikeListActivity.this, "pos::" + pos, Toast.LENGTH_SHORT).show(); } }); }}三方地址
https://github.com/gabrielemariotti/RecyclerViewItemAnimators
具体操作如下:
//给RecyclerView增加一些动画效果// mRecyclerView.setItemAnimator(new DefaultItemAnimator()); //1. build.gradle中引入 : compile 'jp.wasabeef:recyclerview-animators:2.2.5' //2. 添加动画效果 : setItemAnimator(动画效果的类例如: SlideInLeftAnimator, SlideInRightAnimator); mRecyclerView.setItemAnimator(new LandingAnimator()); //3. 改变动画的时长: 有四个: // recyclerView.getItemAnimator().setAddDuration(1000); //recyclerView.getItemAnimator().setRemoveDuration(1000); //recyclerView.getItemAnimator().setMoveDuration(1000); //recyclerView.getItemAnimator().setChangeDuration(1000);具体操作如下:
public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.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) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { 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; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); 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 left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } }}MultiAdapter写法如下
* step: * 1. 有几种类型,就写几个ViewHolder, Adapter中的泛型传入RecyclerView.ViewHolder * 2. 有几种类型,就写几种int 类型常量, 一般从0开始 * 3. 覆写方法getItemViewType(int pos) , 返回当前位置到底是那种类型 * 4. 通过onCreateViewHolder(ViewGroup parent, int viewType) 中的 第二个参数 viewType 去创建不同的ViewHolder对象 * ************************************************************* */public class MultiAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public Context mContext; public LayoutInflater mInflater; public List<HouseBean.DataBean> mDatas; //有几种类型 就写一个常量去标记 private static final int TYPE_SPECIAL = 0; private static final int TYPE_NORMAL = 1; private static final int TYPE_BIG = 2; public MultiAdapter(Context context, List<HouseBean.DataBean> datas) { this.mContext = context; this.mInflater = LayoutInflater.from(context); this.mDatas = datas; } @Override public int getItemCount() { return mDatas == null ? 0 : mDatas.size(); } //返回当前位置的类型 @Override public int getItemViewType(int position) { String type = mDatas.get(position).type; if ("100".equals(type)) { return TYPE_SPECIAL; } else if ("0".equals(type)) { return TYPE_NORMAL; } else { return TYPE_BIG; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case TYPE_SPECIAL:// View view = mInflater.inflate(R.layout.item_multi_special, parent, false);// return new SpecialHolder(view); return new SpecialHolder(mInflater.inflate(R.layout.item_multi_special, parent, false)); case TYPE_NORMAL: return new NormalHolder(mInflater.inflate(R.layout.item_multi_normal, parent, false)); case TYPE_BIG: return new BigImgHolder(mInflater.inflate(R.layout.item_multi_big, parent, false)); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int itemViewType = getItemViewType(position); HouseBean.DataBean bean = mDatas.get(position); switch (itemViewType) { case TYPE_SPECIAL: SpecialHolder specialHolder = (SpecialHolder) holder; specialHolder.tv_title.setText(bean.title); specialHolder.tv_desc.setText(bean.summary); Picasso.with(mContext) .load(bean.groupthumbnail) .placeholder(R.mipmap.ic_launcher) .error(R.mipmap.ic_launcher) .into(specialHolder.iv_special); break; case TYPE_NORMAL: NormalHolder normalHolder = (NormalHolder) holder; normalHolder.tv_title.setText(bean.title); normalHolder.tv_desc.setText(bean.summary); Picasso.with(mContext) .load(bean.groupthumbnail) .placeholder(R.mipmap.ic_launcher) .error(R.mipmap.ic_launcher) .into(normalHolder.iv_normal); break; case TYPE_BIG: BigImgHolder bigImgHolder = (BigImgHolder) holder; bigImgHolder.tv_title.setText(bean.title); Picasso.with(mContext) .load(bean.groupthumbnail) .placeholder(R.mipmap.ic_launcher) .error(R.mipmap.ic_launcher) .into(bigImgHolder.iv_big); break; } } class SpecialHolder extends RecyclerView.ViewHolder { private ImageView iv_special; private TextView tv_title; private TextView tv_desc; public SpecialHolder(View itemView) { super(itemView); iv_special = (ImageView) itemView.findViewById(R.id.iv_show); tv_title = (TextView) itemView.findViewById(R.id.tv_title); tv_desc = (TextView) itemView.findViewById(R.id.tv_desc); } } class NormalHolder extends RecyclerView.ViewHolder { private ImageView iv_normal; private TextView tv_title; private TextView tv_desc; public NormalHolder(View itemView) { super(itemView); iv_normal = (ImageView) itemView.findViewById(R.id.iv_show); tv_title = (TextView) itemView.findViewById(R.id.tv_title); tv_desc = (TextView) itemView.findViewById(R.id.tv_desc); } } class BigImgHolder extends RecyclerView.ViewHolder { private ImageView iv_big; private TextView tv_title; public BigImgHolder(View itemView) { super(itemView); iv_big = (ImageView) itemView.findViewById(R.id.iv_big); tv_title = (TextView) itemView.findViewById(R.id.tv_title); } }}MultiActivity写法如下:
* step: * 1. 从网络获得到数据源 * <p> * 2. 准备适配器 * <p> * 3. 布局管理器 * ************************************************************* */public class MultiActivity extends AppCompatActivity { private RecyclerView mRecyclerView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_multi); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); RequestQueue requestQueue = Volley.newRequestQueue(this); StringRequest request = new StringRequest(Request.Method.GET, UrlString.URL_SEEHOUSE, new Response.Listener<String>() { @Override public void onResponse(String response) { //TODO 得到数据 解析 显示到RecyclerView HouseBean houseBean = new Gson().fromJson(response, HouseBean.class); mRecyclerView.setAdapter(new MultiAdapter(MultiActivity.this, houseBean.data)); mRecyclerView.setLayoutManager(new LinearLayoutManager(MultiActivity.this)); } }, null); requestQueue.add(request); }}新闻热点
疑难解答