RecyclerView使用要点
RecyclerView是一种列表容器, 发布很久了, 才想起来写点什么.
RecyclerView相比于ListView, 在回收重用时更具有灵活性, 也就是低耦合, 并且提供了扩展. 加载多个视图时, 应该多用RecyclerView代替ListView.
那么我们来看看这东西应该怎么用? 比如生成一个瀑布流的视图.
首先我们从一个HelloWorld写起, 看看如何构建一个RecyclerView.
1. 依赖库Gradle配置, 添加Recycler库
compile 'com.android.support:recyclerview-v7:+'
资源文件
<androidandroid:id="@+id/test_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> 3. 代码LayoutManager: 管理RecyclerView的结构.
Adapter: 处理每个Item的显示.
ItemDecoration: 添加每个Item的装饰.
ItemAnimator: 负责添加\移除\重排序时的动画效果.
LayoutManager\Adapter是必须, ItemDecoration\ItemAnimator是可选.
/** * 初始化RecyclerView * * @param recyclerView 主控件 */ (RecyclerView recyclerView) { recyclerView.setHasFixedSize(true); // 设置固定大小 initRecyclerLayoutManager(recyclerView); // 初始化布局 initRecyclerAdapter(recyclerView); // 初始化适配器 initItemDecoration(recyclerView); // 初始化装饰 initItemAnimator(recyclerView); // 初始化动画效果 } 4. LayoutManager管理RecyclerView的布局结构.
(RecyclerView recyclerView) { // 错列网格布局 recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL)); }提供了多种LayoutManager, 瀑布流使用错列网格布局.
5. Adapter适配器, 处理RecyclerView的Item事务.
(RecyclerView recyclerView) { mAdapter = new MyAdapter(getData()); recyclerView.setAdapter(mAdapter); }对于Adapter, 我们需要展开来说, 先看看类.
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { private List<DataModel> mDataModels; private List<Integer> mHeights; MyAdapter(List<DataModel> dataModels) { if (dataModels == null) { throw new IllegalArgumentException("DataModel must not be null"); } mDataModels = dataModels; mHeights = new ArrayList<>(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_recycler_view, parent, false); return new MyViewHolder(itemView); } @Override (MyViewHolder holder, int position) { DataModel dataModel = mDataModels.get(position); // 随机高度, 模拟瀑布效果. if (mHeights.size() <= position) { mHeights.add((int) (100 + Math.random() * 300)); } ViewGroup.LayoutParams lp = holder.getTvLabel().getLayoutParams(); lp.height = mHeights.get(position); holder.getTvLabel().setLayoutParams(lp); holder.getTvLabel().setText(dataModel.getLabel()); holder.getTvDateTime().setText(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) .format(dataModel.getDateTime())); } @Override () { return mDataModels.size(); } (int position) { DataModel model = new DataModel(); model.setDateTime(getBeforeDay(new Date(), position)); model.setLabel("No. " + (int) (new Random().nextDouble() * 20.0f)); mDataModels.add(position, model); notifyItemInserted(position); } (int position) { mDataModels.remove(position); notifyItemRemoved(position); } /** * 获取日期的前一天 * * @param date 日期 * @param i 偏离 * @return 新的日期 */ private static Date getBeforeDay(Date date, int i) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_YEAR, i * (-1)); return calendar.getTime(); } }onCreateViewHolder创建ViewHolder.
onBindViewHolder绑定每一项数据.
getItemCount返回列表长度.
RecyclerView强制使用ViewHolder.
.TextView mTvDateTime; (View itemView) { super(itemView); mTvLabel = (TextView) itemView.findViewById(R.id.item_text); mTvDateTime = (TextView) itemView.findViewById(R.id.item_date); } public TextView getTvLabel() { return mTvLabel; } public TextView getTvDateTime() { return mTvDateTime; } }在onCreateViewHolder方法, 创建类; 在onBindViewHolder方法, 绑定数据.
DataModel
public class DataModel { private String mLabel; private Date mDateTime; public String getLabel() { return mLabel; } (String label) { mLabel = label; } public Date getDateTime() { return mDateTime; } (Date dateTime) { mDateTime = dateTime; } } 6. ItemDecoration项的装饰, 比如ListView中的分割线, 在本例中, 左右两条粉线.
(RecyclerView recyclerView) { recyclerView.addItemDecoration(new MyItemDecoration(this)); }