导读:
RecyclerView:
RecyclerView 比 ListView 更高级且更具灵活性。 它是一个用于显示庞大数据集的容器,可通过保持有限数量的视图进行非常有效的滚动操作。 如果您有数据集合,其中的元素将因用户操作或网络事件而在运行时发生改变,请使用 RecyclerView 。
RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由,可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果.
CradView:顾名思义就是卡片view,可以设置阴影,圆角,等等。。---------本文有借鉴薛瑄大神的文章,大神就是大神写的是真的好
适合人群:这是一篇适合新手使用RecyclerView控件的解析。
准备工作:
实际上第一条导包好像是把所有的support:design包里面的东西都引入了,因为这个时候实现Toolbar不需要额外导包。
实现RecyclerView:
1.想要控制其item们的排列方式,请使用布局管理器LayoutManager
2.如果要创建一个适配器,请使用RecyclerView.Adapter
3.想要控制Item间的间隔,请使用RecyclerView.ItemDecoration
4.想要控制Item增删的动画,请使用RecyclerView.ItemAnimator
在DefaultItemAnimator中有Add、Remove、Move、Change四种动画.
要实现这四种动画,数据更新时要使用以下方法
Adapter.notifyItemInserted(int position)
Adapter.notifyItemRemoved(int position)
Adapter.notifyItemChanged(int position)
Adapter.notifyItemMoved(int fromPosition, int toPosition)
5.CardView 扩展 FrameLayout 类并让您能够显示卡片内的信息,这些信息在整个平台中拥有一致的呈现方式。CardView 小部件可拥有阴影和圆角。
其中1,2是必须实现的,3,4,5可以让RecyclerView变得更加美观。
RecyclerView-----xml布局:
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/liner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="添加"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="删除"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="List"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Grid"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_flow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="flow"
android:textAllCaps="false" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
实现MyRecyclerViewAdapter
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder> {
LayoutInflater mInflater;
// Context context;
private List<Mtext> datas;
public MyRecyclerViewAdapter(Context context,List<Mtext> datas){
mInflater = LayoutInflater.from(context);
this.datas=datas;
// this.context=context;
}
/*①onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,
但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,
然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写*/
//onCreateViewHolder 通过这个方法来创建ViewHolder,把自定义的viewholder创建出来
//实际上就是创建条目的View的结构
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//View.inflate将布局给找到
View view=View.inflate(parent.getContext(),R.layout.item_recyclerview,null);
//该方法返回一个ViewHolder,参数是view
return new MyViewHolder(view);
}
/*
* ②onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder
这里面主要进行数据整理并显示在界面上,我怎么觉得我打字是这么的快,哈哈! 皮
*/
//通过onBindViewHolder将点击事件传到界面上进行操作
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
String data=datas.get(position).getUsertext();
holder.tv_title.setText(data);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { //单击事件
if (listener!=null){
listener.onClick(datas.get(position).getUsertext(),datas.get(position).getPostion());
}
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { //长按事件
@Override
public boolean onLongClick(View view) {
if(listener!=null){
listener.onLongClick(datas.get(position).getUsertext(),datas.get(position).getPostion());
}
return true;
}
});
}
//添加数据
public void addData( String username,int position) {
Mtext mtext=new Mtext(username,position);
datas.add(mtext);
//刷新适配器
notifyItemInserted(position);
}
//移除数据
public void removeData(int position) {
datas.remove(position);
//刷新适配器
notifyItemRemoved(position);
}
/*总共有多少个条目*/
@Override
public int getItemCount() {
return datas==null? 0:datas.size();
}
//一个最基本的RecyclerView适配器需要具备这几个方法
class MyViewHolder extends RecyclerView.ViewHolder{
private TextView tv_title;
public MyViewHolder(View itemView) {
super(itemView);
//itemView 实际上就是条目的View对象 在条目的View对象中找到要修改的控件 通过
//成员变量缓存起来
tv_title=itemView.findViewById(R.id.tv_title);
}
}
//声明一个点击事件接口类型的成员变量
private MyClickListener listener;
//传入点击事件具体实现的方法
public void setListener(MyClickListener listener) {
this.listener = listener;
}
//声明一个点击事件的接口
public interface MyClickListener{
void onClick(String username,int postion);
void onLongClick(String username,int postion);
}
}
基本的RecyclerViewAdapter,要实现的四个方法:
2.getItemCount() 获取总的条目数
3.onCreateViewHolder() 创建ViewHolder
4.onBindViewHolder() 将数据绑定至ViewHolder
RecyclerView排序:
recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
实现RecyclerView动画:
//实现动画效果
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setAddDuration(1000);
defaultItemAnimator.setRemoveDuration(1000);
recyclerview.setItemAnimator(defaultItemAnimator);
在DefaultItemAnimator中有Add、Remove、Move、Change四种动画.
需要注意的是,要实现这四种动画效果,数据更新时不能通过:
Adapter.notifyDataSetChanged();
而是通过:
Adapter.notifyItemInserted(int position)
Adapter.notifyItemRemoved(int position)
Adapter.notifyItemChanged(int position)
Adapter.notifyItemMoved(int fromPosition, int toPosition)
CardView----xml布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:foreground="?attr/selectableItemBackground"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="5dp"
android:layout_marginTop="5dp"
app:cardUseCompatPadding="true"
android:layout_marginBottom="1dp"
app:cardPreventCornerOverlap="true"
>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:padding="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:padding="5dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="Content"
android:textSize="25sp"
android:textAllCaps="false"
android:textColor="#000000" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
CardView基本属性:
app:cardBackgroundColor这是设置背景颜色
app:cardCornerRadius这是设置圆角大小
app:cardElevation这是设置z轴的阴影
app:cardMaxElevation这是设置z轴的最大高度值
app:cardUseCompatPadding是否使用CompatPadding
app:cardPreventCornerOverlap是否使用PreventCornerOverlap
app:contentPadding 设置内容的padding
app:contentPaddingLeft 设置内容的左padding
app:contentPaddingTop 设置内容的上padding
app:contentPaddingRight 设置内容的右padding
app:contentPaddingBottom 设置内容的底padding
/关于在5.0后显示异常问题解决方法
<!-- 在v20和之前的版本中添加内边距,这个属性是为了防止卡片内容和边角的重叠 -->
app:cardPreventCornerOverlap="true"
<!-- 设置内边距,v21+的版本和之前的版本仍旧具有一样的计算方式 -->
app:cardUseCompatPadding="true"
Mtext公共代码类:
快速生成get,set,构造方法:Alt+Insert
public class Mtext {
private String usertext;
private int postion;
public Mtext(String usertext, int postion) {
this.usertext = usertext;
this.postion = postion;
}
public String getUsertext() {
return usertext;
}
public void setUsertext(String usertext) {
this.usertext = usertext;
}
public int getPostion() {
return postion;
}
public void setPostion(int postion) {
this.postion = postion;
}
}
MainActivity代码:
package com.example.administrator.recyclerview;
import android.content.Intent;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_add;
private Button btn_delete;
private Button btn_list;
private Button btn_grid;
private Button btn_flow;
private RecyclerView recyclerview;
private LinearLayout linearLayout;
private MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//设置RecyclerView的适配器
//RecyclerView通过构造方法给RecyclerAdpater适配器传递数据
adapter = new MyRecyclerViewAdapter(this,Data()); //context,List<Mtext>datas
recyclerview.setAdapter(adapter);
//LayoutManager
recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// recyclerview.scrollToPosition(datas.size()-1);
//实现动画效果
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setAddDuration(1000);
defaultItemAnimator.setRemoveDuration(1000);
recyclerview.setItemAnimator(defaultItemAnimator);
//我真tmd机智
adapter.setListener(new MyRecyclerViewAdapter.MyClickListener() {
//Item单击事件
@Override
public void onClick(String username,int postion) { //postion的作用是防止跳转时进入同一个界面,以及不同操作实现在一个界面上
Toast.makeText(MainActivity.this,"点击了"+username,Toast.LENGTH_SHORT).show();
switch (postion){
case 0:
Intent intent=new Intent(getApplicationContext(),Okhttpdemo.class);
startActivity(intent);
break;
/*case 1:*/ } }
//Item长按事件
@Override
public void onLongClick(String username, final int postion) { //postion的作用根据int值进行移除
Snackbar.make(linearLayout, "确定删除" + username + "吗?", Snackbar.LENGTH_LONG)
.setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View view) {
//删除该CradView
adapter.removeData(postion);
}
}).show();
}
});
}
//准备数据源
public List<Mtext> Data() {
List<Mtext> datas = new ArrayList<>();
Mtext mtext=new Mtext("Okhttp",0);
datas.add(mtext);
Mtext mtext1=new Mtext("FastJson",1);
datas.add(mtext1);
return datas;
}
private void initView() {
setContentView(R.layout.activity_main);
linearLayout= (LinearLayout) findViewById(R.id.liner);
btn_add = (Button) findViewById(R.id.btn_add);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_list = (Button) findViewById(R.id.btn_list);
btn_grid = (Button) findViewById(R.id.btn_grid);
btn_flow = (Button) findViewById(R.id.btn_flow);
recyclerview = (RecyclerView) findViewById(R.id.recyclerview);
//设置点击事件
btn_add.setOnClickListener(this);
btn_delete.setOnClickListener(this);
btn_list.setOnClickListener(this);
btn_grid.setOnClickListener(this);
btn_flow.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_add:
adapter.addData("FastJson",1);
recyclerview.scrollToPosition(0);
break;
case R.id.btn_list:
//设置List类型效果
recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
break;
case R.id.btn_grid:
//设置Grid类型效果,九宫格
recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this, 2, GridLayoutManager.VERTICAL, false));
// recyclerview.scrollToPosition(99);
break;
case R.id.btn_flow:
//设置瀑布流类型效果
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
break;
}
}
}
好了,到此一个RecyclerView+CradView的demo,就做好了,实现了显示,增加和移除的动画效果,瀑布流,以及单击和长按事件,另外本demo重启后数据是会恢复原样的,是因为List<Mtext>Data()的原因。
推荐一个大神封装的RecyclerView库:https://github.com/CymChad/BaseRecyclerViewAdapterHelper