在support-V7包中引入了很多新的M 控件,其中RccyclerView也是其中一员,它的名字来源于它的工作方式:当一个Item被隐藏起来时候并没有被销毁,当建立新的item时候,组件自动复用item。但与以往经典listview不同的是,RccyclerView直接把viewholder的实现封装起来,因此用户只要实现自己的viewholder即可。
通常一个RccyclerView主要要处理以下几个部分:
LayoutManager :RccyclerView将item布局方式单独放出来供开发者选择,可以把你的item设置成水平或者垂直或者
主要有 LinearLayoutManager(线性)、GridLayoutManager(宫格)、StaggeredGridLayoutManager(瀑布流)
Adapter:适配器,在listview中也有,主要用来提供数据适配
ItemAnimator:负责item的动画播放修改,添加,删除或移动
ItemDecoration:可以用来添加drawings或者改变item的布局,比如添加dividers
ViewHolder:用户实现自己的viewlder即可
点击事件:这个没有提供需要自己写,这个我在后面的例子中会给出说明
再介绍一下Cardview,跟RccyclerView一样也是suooport-v7新控件,可以让我们使用类似卡片的效果,我们还可以设置卡片的圆角和阴影效果,cardview是一个layout继承自frameLayout,因此需要在里面布局其他view控件,下面给出一个cardview常用属性
CardView_cardBackgroundColor 设置背景色
CardView_cardCornerRadius 设置圆角大小
CardView_cardElevation 设置z轴阴影
CardView_cardMaxElevation 设置z轴最大高度值
CardView_cardUseCompatPadding 是否使用CompadPadding
CardView_cardPreventCornerOverlap 是否使用PreventCornerOverlap
CardView_contentPadding 内容的padding
CardView_contentPaddingLeft 内容的左padding
CardView_contentPaddingTop 内容的上padding
CardView_contentPaddingRight 内容的右padding
CardView_contentPaddingBottom 内容的底padding
首先在AS中加入依赖
File>project structs,在+号选Library Dependency,加入如下来个依赖库
Item.java
public class Item { private String maintitle; private String subtitle; private boolean active; public Item(String maintitle, String subtitle, boolean active) { this.maintitle = maintitle; this.subtitle = subtitle; this.active = active; } public Item(String maintitle, String subtitle) { this.maintitle = maintitle; this.subtitle = subtitle; } public String getTitle() { return maintitle; } public String getSubtitle() { return subtitle; } public boolean isActive() { return active; } }
item.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:cardBackgroundColor="#79CDCD" app:cardCornerRadius="5dp" app:cardElevation="5dp" app:cardMaxElevation="8dp" app:cardUseCompatPadding="true" app:contentPadding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/maintitle" style="@style/Base.TextAppearance.AppCompat.Headline" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:text="Title" android:textColor="#FFFFFF" /> <TextView android:id="@+id/subtitle" style="@style/Base.TextAppearance.AppCompat.Subhead" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:singleLine="true" android:text="Subtitle" android:textColor="#FFFFFF" /> </LinearLayout> </android.support.v7.widget.CardView>
首先我们需要定义自己的viewholder类,这类必须要继承RecyclerView.ViewHolder,内部绑定了所需要引用的数据,这里只有俩个textview
public static class ViewHolder extends RecyclerView.ViewHolder { TextView maintitle; TextView subtitle; public ViewHolder(View itemView) { super(itemView); subtitle = (TextView) itemView.findViewById(R.id.subtitle); maintitle = (TextView) itemView.findViewById(R.id.maintitle); } }
public RecylerAdpater() { super(); items = new ArrayList<>(); for (int i = 0; i < ITEM_CONUT; i++) { items.add(new Item("Item" + i, "This is the Item number" + i)); } }
【1】onCreateViewHolder(ViewGroup parent, int i) 创建视图并且返回一个匹配的viewholder
【2】onBindViewHolder(ViewHolder holder, int position) 用每个item数据来填充viewholder
【3】getItemCount() 返回item的数目
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = mLayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { Item item = items.get(position); viewHolder.maintitle.setText(item.getTitle()); viewHolder.subtitle.setText(item.getSubtitle()); } @Override public int getItemCount() { return items.size(); }
<RelativeLayout 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=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </RelativeLayout>
public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initEvent(); } private void init() { recyclerView = (RecyclerView) findViewById(R.id.recycler_view); } private void initEvent() { recyclerView.setAdapter(new RecylerAdpater()); recyclerView.setItemAnimator(new DefaultItemAnimator()); //recyclerView.setLayoutManager(new LinearLayoutManager(this));//垂直线性布局 //recyclerView.setLayoutManager(new GridLayoutManager(this,2));//线性宫格显示,类似gridview recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, OrientationHelper.VERTICAL));//线性宫格显示类似瀑布流 } }
即实现相同的RecyclerView中实现不同样式的item,比如常见的headitem和bottomiItem就是通过这种方式实现的
首先事先定义出几套item的样式,这里使用了2套item样式,这里item布局仅做了颜色区分,当然可以做的更加复杂,这取决于各自的需求,这里只是演示一下多item的布局
然后利用item的isActive对item做标记
recylerAdapter.java中
public RecylerAdpater() { super(); items = new ArrayList<>(); for (int i = 0; i < ITEM_CONUT; i++) { if (i == 0) items.add(new Item("Start Item " + i, "This is the start Item number " + i, true)); if (i == ITEM_CONUT - 1) items.add(new Item("End Item " + i, "This is the end Item number " + i, true)); else items.add(new Item(" Item " + i, "This is the Item number " + i, false)); } }
这里我们也需要重写新的方法
@Override public int getItemViewType(int position) { Item item = items.get(position); return item.isActive() ? ACTIVE : IN_ACTIVE; }
然后我们在viewholder中对itenm布局做选择
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { final int layout = (viewType == IN_ACTIVE ? R.layout.item : R.layout.item_active); //View v = mLayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); View v = mLayoutInflater.from(viewGroup.getContext()).inflate(layout, viewGroup, false); return new ViewHolder(v); }
Recylerview点击事件需要我们自己写这点就比较麻烦
这里我们在适配器中通过接口方式来写自己的itemlistener
RecylerAdapter.java
定义抽象接口
public interface OnItemClickListerner { void onItemClick(View view, int position); void onItemLongClick(View view, int position); } public void setOnItemClickLitener(OnItemClickListerner mOnItemClickListerner) { this.mOnItemClickListerner = mOnItemClickListerner; }
//如果设置了回调则设施点击事件 if (mOnItemClickListerner != null) { viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = viewHolder.getLayoutPosition(); mOnItemClickListerner.onItemClick(viewHolder.itemView, pos); } }); viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = viewHolder.getLayoutPosition(); mOnItemClickListerner.onItemLongClick(viewHolder.itemView, pos); return false; } }); }
最后处理集中到MainActivity中来具体处理使用
mRecylerAdpater.setOnItemClickLitener(new RecylerAdpater.OnItemClickListerner() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "click item" + position, Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { mRecylerAdpater.removeData(position); Toast.makeText(MainActivity.this, "long click delete item" + position, Toast.LENGTH_SHORT).show(); } });
为了更新view,在listview中我们只有一个方法来监听数据item变化notifyDataSetChanged(),而在recylerView的adapter中,有多个方法
notifyItemChanged(int position) : position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了
notifyItemInserted(int position):这个方法是在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默 认的,也可以自己定义。
notifyItemRemoved(int position):删除position位置上的item
notifyItemMoved(int fromPosition, int toPosition):这个方法是从fromPosition移动到toPosition为止的时候可以使用这个方法刷新
notifyItemRangeChanged(int positionStart, int itemCount):刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)
notifyItemRangeInserted(int positionStart, int itemCount):批量插入
notifyItemRangeRemoved(int positionStart, int itemCount):第position个被删除的时候刷新,同样会有动画
notifyDataSetChanged()改变数据视图
我们在Adapter中加入增删函数
/*添加*/ public void addItem(int pos) { items.add(new Item("new Item", "This is the new Item ", false)); notifyItemInserted(pos); } /*删除*/ public void removeData(int pos) { items.remove(pos); notifyItemRemoved(pos); }
长按删除item
点击弹出Toast提示,长按删除item,点击menu加号添加item
所有demo地址http://download.csdn.net/detail/xsf50717/9314043