RecyclerView
出现在Android 5中 需要引进support-v7
包内
一个RecyclerView
由六个成分
Adapter
:提供数据,为每个Item创建视图(相似于ListView)ItemAnimator
:负责添加、移动、移除的动画效果ItemDecoration
:为每个Item视图添加子视图(e.g. 添加分割线)LayoutManager
:负责Item视图的布局管理器(一个线性布局,类似于ListView;一个网格布局;一个瀑布流式布局)ViewHolder
:承载Item视图的子视图RecyclerView本身
:一起绑定任何事务compile 'com.android.support:recyclerview-v7:25.1.0'
CardView
同样添加依赖 compile 'com.android.support:cardview-v7:25.1.0'
ViewHolder
类,它必须继承 RecyclerView.ViewHolder
,在这里有两个TextView
(ViewHolder不了解,阅读Hold View Objects in a View Holder)public static class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
TextView subtitle;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
subtitle = (TextView) itemView.findViewById(R.id.subtitle);
}
}
Adapter
负责扮演两个角色,不仅为底部数据提供支持而且还负责为数据创建合适的视图。 RecyclerView.Adapter
需要实现以下三个方法 public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
:创建一个视图然后返回一个正在匹配的ViewHolderpublic void onBindViewHolder(ViewHolder holder,int position)
: 绑定View,根据返回的position类型,从而进行绑定到ViewHolder
上public int getItemCount()
:返回View中Item的个数public int getItemViewType(int position)
:判断item的类型,从而绑定不同的view public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List mDatas;
public MyAdapter(List list) {
this.mDatas = list;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ListHolder(layout);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((ListHolder) holder).tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class ListHolder extends RecyclerView.ViewHolder {
TextView tv;
public ListHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.item);
}
}
}
LinearLayout.VERTICAL
findFirstVisibleItemPosition()
findFirstCompletelyVisibleItemPosition()
findLastVisibleItemPosition()
findLastCompletelyVisibleItemPosition()
通过ItemDecoration
可以使各个Item在视觉上相互分开,其实和ListView的Divider很像。ItemDecoration
并不是RecyclerView必须设置的,开发者可以不设置或者设置多个Decoration。RecyclerView会遍历所有的ItemDecoration
并调用各自的绘图方法。
继承RecyclerView.ItemDecoration需要实现以下方法:
public void onDraw(Canvas c,RecyclerView parent,RecyclerView.State state)
public void getItemOffset(Rect outRect,int itemPosition,RecyclerView parent)
:调用getItemOffset方法来计算每个Item的Decoration合适的尺寸。当Item有以下三种操作时RecyclerView所提供的动画效果:删除
、添加
、移动
。
Google提供了一个名为DefaultItemAnimator
的默认ItemAnimator供开发者使用。如果开发者不为RecyclerView设置ItemAnimator,RecyclerView也会使用默认的DefaultItemAnimator。
显然,为了让动画效果起效,开发者必须通知Adapter数据有改变。之前我们使用Adapter时会调用notifyDataSetChanged()来通知Adapter数据改变并更新视图,现在RecyclerView,Adapter提供了许多notifyItemXXX()方法:
notifyItemChanged(int position)
notifyItemInserted(int position)
notifyItemRemoved(int position)
notifyItemMoved(int fromPosition, int toPosition)
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeInserted(int positionStart, int itemCount)
notifyItemRangeRemoved(int positionStart, int itemCount)
notifyDataSetChanged()
RecyclerView
"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=".MainActivity" >
.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
//设置布局mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//设置动画(非必需)mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
//设置分割线(非必需)mRecyclerView.setAdapter(mAdapter = new MyAdapter(mDatas));
//设置Adapterpublic class demo2 extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MyAdapter mMyAdapter;
private List mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo2);
//RecyclerView三部曲+LayoutManager
mRecyclerView = (RecyclerView)findViewById(R.id.rv_demo2);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
initData();
mMyAdapter = new MyAdapter(mList);
mRecyclerView.setAdapter(mMyAdapter);
}
//初始化RecyclerView中每个item的数据
private void initData(){
mList = new ArrayList();
for (int i = 0; i < 20; i++){
mList.add("item" + i);
}
}
public interface OnItemClickListener{
void onItemClick(View view, int position);
}
public interface OnItemLongClickListener{
void onItemLongClick(View view, int position);
}
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
//设置Item点击监听
public void setOnItemClickListener(OnItemClickListener mOnItemClickListener){
this.mOnItemClickListener = mOnItemClickListener;
}
public void setOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
this.mOnItemLongClickListener = mOnItemLongClickListener;
}
public MyAdapter(List data) {
this.mDatas = data;
}
//创建Item视图,并返回相应的ViewHolder
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder myViewHolder = new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_single_textview,parent,false));
return myViewHolder;
}
//绑定数据到正确的Item视图上
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.textView.setText(mDatas.get(position));
// 如果设置了回调,则设置点击事件
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getLayoutPosition();
mOnItemClickListener.onItemClick(holder.itemView,position);
}
});
}
holder.itemView.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
int position = holder.getLayoutPosition();
mOnItemLongClickListener.onItemLongClick(holder.itemView,position);
//返回true 表示消耗了事件 事件不会继续传递
return true;
}
});
}
ViewHolder
应用View.OnClickListener
和View.OnLongClickListener
public class Adapter extends SelectableAdapter<Adapter.ViewHolder> {
// …
private ViewHolder.ClickListener clickListener;
public Adapter(ViewHolder.ClickListener clickListener) {
super();
this.clickListener = clickListener;
}
/**
* public void setOnItemClickListener(MyItemClickListener listener){
this.mItemClickListener = listener;
}
* 有此方法 Activity中onCreate内需要初始化下面已给出
**/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final int layout = viewType == TYPE_INACTIVE ? R.layout.item : R.layout.item_active;
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ViewHolder(v, clickListener);
}
// …
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnLongClickListener {
TextView title;
TextView subtitle;
View selectedOverlay;
private ClickListener listener;
public ViewHolder(View itemView, ClickListener listener) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
subtitle = (TextView) itemView.findViewById(R.id.subtitle);
selectedOverlay = itemView.findViewById(R.id.selected_overlay);
this.listener = listener;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClicked(getPosition());
}
}
@Override
public boolean onLongClick(View v) {
if (listener != null) {
return listener.onItemLongClicked(getPosition());
}
return false;
}
public interface ClickListener {
public void onItemClicked(int position);
public boolean onItemLongClicked(int position);
}
}
}
Activity
内(继承ViewHolder
的ClickListener
) this.mAdapter.setOnItemClickListener(this);
this.mAdapter.setOnItemLongClickListener(this);
@Override
public void onItemClick(View view, int postion) {
MyItemBean bean = mData.get(postion);
if(bean != null){
Toast.makeText(this, bean.tv, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onItemLongClick(View view, int postion) {
MyItemBean bean = mData.get(postion);
if(bean != null){
Toast.makeText(this, "LongClick "+bean.tv, Toast.LENGTH_SHORT).show();
}
}
=========================更新中
RecyclerView basics
Android RecyclerView 使用完全解析 体验艺术般的控件
Android-RecylerView初识