RecyclerView 的介绍以及多布局的实例

时间:2023-03-10 07:13:11
RecyclerView 的介绍以及多布局的实例

RecyclerView 的使用以及多布局的实例

  RecyclerView 是在Android5.0之后推出的,是一个比ListView更加灵活更加高效的适配器类型控件。但是RecyclerView不同于其他类型的适配器,它还需要一个LayoutManager进行页面控制展示。RecyclerView提供了三种布局管理器:
  1、LinearLayoutManager:线性布局管理器,支持水平和垂直效果。
  2、GridLayoutManager:网格布局管理器,支持水平和垂直效果。
  3、StaggeredGridLayoutManager:分布型管理器,瀑布流效果 RecyclerView的使用:
  1、引入RecyclerView依赖包,V7下的,兼容到API17.
  2、在xml布局中声明,在Java代码中初始化。
  3、设置布局管理器
  4、创建适配器,设置数据源,绑定适配器
    具体创建适配器:①创建一个类,继承RecyclerView.Adapter<ViewHolder>.
            ②创建一个类ViewHolder,继承RecyclerView。VIewHolder,该类需要创建一个匹配父类的构造。
            ③重写适配器中的方法:getItemCount():获取数据源的个数(item的数量);onCreateViewHolder():该方法中导入布局,实例化VIewHolder;onBindViewHolder():绑定VIewHolder,加载数据。
注意一点:RecyclerView的LinearLayoutManager不同于一般的适配器的布局,RecyclerView的item最外层的布局参数是有效的,如高度宽度等,所以在使用的时候,第一种方法是在导入View的时候指定没有parent(不推荐使用),第二种方法是在item布局的最外层指定具体的参数。
RecyclerView 为开发者提供了强大的复用机制,但是所有的点击事件都丢了,没有提供默认的点击事件,所以需要我们自己为RecyclerView手动实现点击。
看一个简单的例子,后面讲解下多布局的RecyclerView。效果图如下(不要吐槽,我知道很丑,能达到效果就好^_^):
RecyclerView 的介绍以及多布局的实例

第一步:创建布局,需要导入依赖包:android.support.v7.widget.RecyclerView

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="com.zcl.day40_recyleview01.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/teach_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:background="@drawable/backgroud_shap"
android:layout_height="match_parent">
<ImageView
android:src="@mipmap/ic_launcher"
android:layout_width="80dp"
android:layout_height="80dp" />
<TextView
android:id="@+id/teach_item_name"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>

Model.java

public class Model {
private String name;
private int height; public int getHeight() {
return height;
} public void setHeight(int height) {
this.height = height;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity implements RecyclerAdapter.OnItemClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.teach_recycler);
//设置布局管理器
//1、第一种LinearLayoutManager
// LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//2、第二种 GridLayoutManager
// GridLayoutManager layoutManager=new GridLayoutManager(this,3);
//3、第三种
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
// //设置布局的排版方向
// layoutManager.setOrientation(GridLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(layoutManager);
//绑定适配器
RecyclerAdapter adapter = new RecyclerAdapter(this, getData());
mRecyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(this);//将接口传递到数据产生的地方
} /**
* 获取数据源
*
* @return
*/
public List<Model> getData() {
List<Model> data = new ArrayList<>();
for (int i = 0; i < 30; i++) {
Model model = new Model();
model.setName("猴子请来的都比---" + i);
model.setHeight(((int) (Math.random() * 100 + 200)));
data.add(model);
}
return data;
} @Override
public void onItemClick(int position, Model model) {
Log.e(TAG, "onItemClick: " + position);
}
}

适配器

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> implements View.OnClickListener {
private static final String TAG = RecyclerAdapter.class.getSimpleName();
private List<Model> data;
private LayoutInflater inflater;
private RecyclerView mRecyclerView;//用来计算Child位置
private OnItemClickListener onItemClickListener;
//对外提供接口初始化方法
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener=onItemClickListener;
} public RecyclerAdapter(Context context,List<Model> data) {
this.data = data;
inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} public static class ViewHolder extends RecyclerView.ViewHolder{
TextView name; public ViewHolder(View itemView) {
super(itemView);
name= (TextView) itemView.findViewById(R.id.teach_item_name);
}
} /**
* 创建VIewHolder,导入布局,实例化itemView
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = inflater.inflate(R.layout.item, parent, false);
//导入itemView,为itemView设置点击事件
itemView.setOnClickListener(this);
return new ViewHolder(itemView);
} /**
* 绑定VIewHolder,加载数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.name.setText(data.get(position).getName());//加载数据
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
layoutParams.height=data.get(position).getHeight();
holder.itemView.setLayoutParams(layoutParams);
} /**
* 数据源的数量,item的个数
* @return
*/
@Override
public int getItemCount() {
return data!=null?data.size():0;
} /**
* 适配器绑定到RecyclerView 的时候,回将绑定适配器的RecyclerView 传递过来
* @param recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView=recyclerView;
} /**
*
* @param v 点击的View
*/
@Override
public void onClick(View v) {
//RecyclerView可以计算出这是第几个Child
int childAdapterPosition = mRecyclerView.getChildAdapterPosition(v);
Log.e(TAG, "onClick: "+childAdapterPosition );
if (onItemClickListener!=null) {
onItemClickListener.onItemClick(childAdapterPosition,data.get(childAdapterPosition));
}
} /**
* 接口回调
* 1、定义接口,定义接口中的方法
* 2、在数据产生的地方持有接口,并提供初始化方法,在数据产生的时候调用接口的方法
* 3、在需要处理数据的地方实现接口,实现接口中的方法,并将接口传递到数据产生的地方
*/
public interface OnItemClickListener{
void onItemClick(int position,Model model);
}
}

多布局的RecyclerView ---------------------------------------------------------------

先看下效果图:

RecyclerView 的介绍以及多布局的实例

这是

分析下该页面布局,三种布局,第一种是标题文字+内容简介文字占一个item,第二种是图片+标题占一个item,第三种是标题+内容,并且一个item中有两个这样的布局。那么可以用网格布局,分为两列,第一种跟第二种布局各自占两列,第三种布局占一列。那么怎么设置item可以横跨两列呢,就要用到gridLayoutManager.setSpanSizeLookup来设置,具体看代码:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="com.zcl.day40_task2.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

item1.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:id="@+id/iv_item1"
android:src="@mipmap/ic_launcher"
android:layout_width="match_parent"
android:layout_height="200dp" />
<TextView
android:id="@+id/tv_item1"
android:text="title"
android:textColor="#e5ffffff"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> </RelativeLayout>

item2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="200dp">
<TextView
android:id="@+id/tv_item2_title"
android:textSize="20sp"
android:textStyle="bold"
android:text="title"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_item2_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:text="content"
android:layout_marginBottom="10dp"
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

item3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="200dp">
<TextView
android:id="@+id/tv_item3_title"
android:textSize="20sp"
android:lines="2"
android:ellipsize="end"
android:text="title"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="60dp" />
<TextView
android:id="@+id/tv_item3_content"
android:lines="2"
android:ellipsize="end"
android:text="content"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:layout_marginRight="15dp"
android:layout_width="match_parent"
android:layout_height="60dp" /> </LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyAdapter.OnItemClickLietener{

    private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
private MyAdapter adapter;
private List<Model> data;
public static final String URL_PATH="http://dxy.com/app/i/feed/index/list?hardName=Google%20Nexus%205%20-%205.1.0%20-%20API%2022%20-%201080x1920&u=&bv=2015&ac=d5424fa6-adff-4b0a-8917-4264daf4a348&vc=5.1.9&vs=5.1&mc=00000000600ba4e6ffffffff99d603a9"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
} private void initView() {
ImageLoader.init(this);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//设置布局管理器
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
Log.e(TAG, "initView:----1 " );
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
int spansize=1;
switch (adapter.getItemViewType(position)) {
case 1:
spansize=2;
break;
case 2:
spansize=2;
break;
}
return spansize;
}
});
Log.e(TAG, "initView: -----2" );
mRecyclerView.setLayoutManager(gridLayoutManager); adapter = new MyAdapter(this, getData());
mRecyclerView.setAdapter(adapter);
adapter.setClickLietener(this);
Log.e(TAG, "initView: 4" );
} public List<Model> getData() {
Log.e(TAG, "getData: 3" );
HttpUtil.getStringAsync(URL_PATH, new HttpUtil.RequestCallBack() {
@Override
public void onFailure() {
Log.e(TAG, "onFailure: " );
} @Override
public void onSuccess(String result) {
Gson gson = new Gson();
ModelData modelData = gson.fromJson(result, ModelData.class);
List<Model> data =modelData.getData().getItems();
Log.e(TAG, "onSuccess: "+data );
adapter.addRes(data);
} @Override
public void onFinish() {
Log.e(TAG, "onFinish: " );
}
}); return data;
} @Override
public void setItemClickListener(int position) {
Log.e(TAG, "setItemClickListener: "+position );
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener {

    private List<Model> data;
private LayoutInflater inflater;
private RecyclerView mRecyclerView;
private OnItemClickLietener clickLietener; public void setClickLietener(OnItemClickLietener clickLietener){
this.clickLietener=clickLietener;
} public MyAdapter(Context context, List<Model> data) {
this.data = data;
inflater = LayoutInflater.from(context);
} @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = null;
switch (viewType) {
case 1:
itemView = inflater.inflate(R.layout.item1, parent, false);
break;
case 2:
itemView = inflater.inflate(R.layout.item2, parent, false);
break;
case 8:
itemView = inflater.inflate(R.layout.item3, parent, false);
break;
//设置监听
}
itemView.setOnClickListener(this);
return new ViewHolder(itemView);
} @Override
public void onBindViewHolder(ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case 1:
ImageView imageView = (ImageView) holder.getView(R.id.iv_item1);
TextView textView = (TextView) holder.getView(R.id.tv_item1);
textView.setText(data.get(position).getTitle());
String picPath = data.get(position).getCover();
ImageLoader.display(imageView, picPath);
break;
case 2:
TextView item2Title = (TextView) holder.getView(R.id.tv_item2_title);
TextView item2Content = (TextView) holder.getView(R.id.tv_item2_content);
item2Title.setText(data.get(position).getTitle());
item2Content.setText(data.get(position).getContent());
break;
case 8:
TextView item3Title = (TextView) holder.getView(R.id.tv_item3_title);
TextView item3Content = (TextView) holder.getView(R.id.tv_item3_content);
item3Title.setText(data.get(position).getTitle());
item3Content.setText(data.get(position).getContent());
break;
}
} @Override
public int getItemCount() {
return data != null ? data.size() : 0;
} @Override
public int getItemViewType(int position) {
return data.get(position).getShow_type();
} @Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView=recyclerView;
} public void addRes(List<Model> data) {
if (data != null) {
this.data = data;
notifyDataSetChanged();
}
} @Override
public void onClick(View v) {
int childAdapterPosition = mRecyclerView.getChildAdapterPosition(v);
if (clickLietener!=null) {
clickLietener.setItemClickListener(childAdapterPosition);
}
} public static class ViewHolder extends RecyclerView.ViewHolder { private Map<Integer, View> mCacheView; public ViewHolder(View itemView) {
super(itemView);
mCacheView = new HashMap<>();
} public View getView(int resId) {
View view;
if (mCacheView.containsKey(resId)) {
view = mCacheView.get(resId);
} else {
view = itemView.findViewById(resId);
mCacheView.put(resId, view);
}
return view;
}
} public interface OnItemClickLietener{
void setItemClickListener(int position);
}
}

代码中使用的网络数据的请求以及图片的加载是自己封装的类库,大家可以忽略,用自己的代码填充,能理解RecyclerView就好,另外数据的实体类太简单,也没有贴上代码。最后不要忘了配置网络权限哦。

我的github:https://github.com/SiberiaDante