在Android 5.0 版本之前,为了方便的显示多行数据,形如QQ聊天信息主界面,最常用的选择无非是ListView控件,但是ListView控件本身就有很大的局限性和效率问题(相对于RecyclerView控件)来说,比如说ListView只能竖向滚动显示数据,不能横向滚动显示数据,在一些特殊的需求中,ListView就无能为力了。在Android5.0版本之后,Android官方推出了一个新的控件:RecyclerView ,完全解耦的设计使得RecyclerView比起ListView灵活了太多,应用的场合也非常广泛。那么,就来看一下ListView和RecyclerView的用法和不同之处在哪:
首先我们先来看一下ListView控件的简单用法,比如说我们现在要显示这样一个界面:
每一行项目是一个ImageView和TextView控件的组合。
新建一个 Android 工程: 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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context="com.example.administrator.listviewandrecycleview.MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
在主布局文件中,我们添加了一个ListView控件,用于接下来的数据显示,之后我们要新建一个布局文件用于显示ListView中的项目数据 color_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:layout_height="wrap_content">
<ImageView
android:id="@+id/colorImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/colorNameTextView"
android:layout_marginLeft="10dp"
android:textSize="40sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
布局采用线性横向布局,文件中有两个控件ImageView、TextView。分别用于显示颜色和文字,有了控件,那么对应储存信息的类就有眉目了,新建一个类Color.java:
public class Color {
private String colorName;
private int imageId;
public Color(String colorName, int imageId) {
this.colorName = colorName;
this.imageId = imageId;
}
public String getColorName () {
return colorName;
}
public int getImageId() {
return imageId;
}
}
一个简单的类,储存的信息对应于我们前面布局文件中显示的信息。
ListView是需要适配器才能显示我们定义的布局文件的,那么我们接下来要为ListView设定一个适配器。这里采用ArrayAdapter作为基类适配器,我们新建一个类ColorAdapter来继承ArrayAdapter,并且加入我们自己的逻辑:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.administrator.listviewandrecycleview.R;
import java.util.List;
import javax.crypto.spec.PSource;
/**
* Created by Administrator on 2017/2/21.
* 自定义适配器类继承于 ArrayAdapter 类来实现 ListView 控件的数据显示,
* ListView 控件只有设置了适配器才能显示数据
*/
public class ColorAdapter extends ArrayAdapter {
private int itemLayoutId;
public ColorAdapter(Context context, int itemLayoutId, List<Color> objects) {
super(context, itemLayoutId, objects);
this.itemLayoutId = itemLayoutId;
}
/*
* getView方法用于返回ListView中的item 的视图
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Color color = (Color) getItem(position);
View view;
/*
* convertView 参数用于储存之前加载好的布局缓存,如果不为空,那么我们可以直接用这个用来给view赋值
* 提高ListView的运行效率
*/
if(convertView != null) {
view = convertView;
}else {
/*
* 加载自定义的布局文件,这个方法用于加载布局文件,并且返回一个 View 对象。
* 这样我们就能够在代码中使用布局文件中的各个属性。
* 这里的 inflate 方法的三个参数分别代表:
* 要加载的布局文件Id、为加载的布局文件外层再加一层父布局、第三个参数如果为 true 的话就是把加载的 View 加入父布局中作为子控件。否则就是只在父布局中声明,不添加进入父布局
* 这里我们当然不能加入父布局,因为我们的 View 是要加入 ListView 中作为子控件的
*/
view = LayoutInflater.from(getContext()).inflate(itemLayoutId, parent, false);
}
// 获取布局文件中的控件id并且显示对应信息:
ImageView imageView = (ImageView) view.findViewById(R.id.colorImageView);
TextView textView = (TextView) view.findViewById(R.id.colorNameTextView);
imageView.setImageResource(color.getImageId());
textView.setText(color.getColorName());
return view;
}
}
在ColorAdapter.java中,我们重写了ArrayAdapter类中的getView方法返回的View作为ListView中的item视图。ok,最后是MainActivity.java:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.ListViewCompat;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import listview.Color;
import listview.ColorAdapter;
public class MainActivity extends AppCompatActivity {
private String colorName[] = new String[]{
"blue", "colors", "green", "pink", "puple", "yellow"};
private int colorId[];
private static final int colorSum = 6;
List<Color> list = new ArrayList<Color>();
private ColorAdapter colorAdapter = null;
private ListView listView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initAdapter();
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(colorAdapter); // 为listView设置适配器
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // 设置ListView的点击响应事件
/*
* listView的点击事件:第一个参数是item所在的适配器引用,
* 第二个参数是点击的item的View对象,在这里这个View包含了一个ImageView和一个TextView
* (布局文件color_item布局文件中的控件)
* 第三个和第四个参数一般是一样的,代表你点击的item在ListView中的位置
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Color color = (Color) list.get(position); // 获取点击的View 中包含的Color 对象
Toast.makeText(MainActivity.this, "颜色名称:" + color.getColorName(), Toast.LENGTH_SHORT).show();
}
});
}
protected void initAdapter() {
colorAdapter = new ColorAdapter(this, R.layout.color_item, list);
colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,
R.mipmap.puple, R.mipmap.yellow};
for(int i = 0; i < colorSum; i++) {
Color color = new Color(colorName[i], colorId[i]);
list.add(color);
}
}
}
在MainActivity.java中我们用一个initAdapter方法来初始化ListView需要显示的数据信息,之后将数据信息加入ColorAdapter对象中并且设置ListView控件的适配器为ColorAdapter对象。基本的步骤就完成了,让我们来看一下效果:
ListView简单的用法就是这样了。我们在实际使用的时候可以根据我们自己的需求来设置ListView控件的item布局文件和ListView的点击事件处理。
那么接下来我们来看一下RecyclerView控件的简单用法:我们先用RecyclerView控件来实现上面的功能,你可以选择新建一个Android工程,也可以在上面的ListView控件中的工程中加一个Activity来显示RecyclerView,笔者这里选择的是新建一个Activity来显示RecyclerView: 因为RecyclerView是在android5.0版本新增在support.v7库中,并不是在SDK中,所以我们要进行依赖声明:在app中的build.gradle文件中加入以下代码:
compile 'com.android.support:recyclerview-v7:25.1.1'
并且点击屏幕右上方的sync now,如下图:
这里我用的是android studio IDE 个人感觉android studio 相比eclipse在android开放方面好,不过android studio 对电脑性能要求更加高。 好了我们还要知道,RecyclerView控件的适配器必须继承于RecyclerView.Adapter<RecyclerView.ViewHolder> 类并且重写其中的抽象方法,那么我们新建一个适配器类用来适配要在RecyclerView控件中显示的数据:ColorAdapterForRecyclerView.java:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.administrator.listviewandrecycleview.MainActivity;
import com.example.administrator.listviewandrecycleview.R;
import java.util.List;
/**
* Created by Administrator on 2017/2/21.
*/
public class ColorAdapterForRecyclerView extends RecyclerView.Adapter<ColorAdapterForRecyclerView.MyViewHolder> {
private List<Color> colorList = null;
private Context myContext = null; // Context对象作为Toast提示的第一个参数
/*
* 新建一个静态内部类MyViewHolder继承于RecyclerView.ViewHolder,根据java多态的特性,
* 我们在上面的泛型参数就可以传入这个类作为参数
*/
static class MyViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public MyViewHolder(View view) {
super(view);
imageView = (ImageView) view.findViewById(R.id.colorImageView);
textView = (TextView) view.findViewById(R.id.colorNameTextView);
}
}
public ColorAdapterForRecyclerView(Context context, List<Color> colorList) {
myContext = context;
this.colorList = colorList;
}
/*
* 重写父类的onCreateViewHolder方法,用于创建MyHolder对象作为RecyclerView的显示子项
* 每个 RecyclerView 控件的 item 调用这个方法之后调用
* onBindViewHolder 方法之后才能作为一个子项显示在 RecyclerView 控件中
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.color_item, parent, false);
/*
* 为每一个RecyclerView中显示的子项设置点击处理事件
*/
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView textView = (TextView) v.findViewById(R.id.colorNameTextView);
Toast.makeText(myContext, "颜色名称:" + textView.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
/*
* 重写父类的onBinderViewHolder方法,用于对RecyclerView中显示在屏幕中的子项设置对应的数据信息
*/
@Override
public void onBindViewHolder(MyViewHolder myViewHolder, int position) {
Color color = colorList.get(position);
myViewHolder.imageView.setImageResource(color.getImageId());
myViewHolder.textView.setText(color.getColorName());
}
/*
* 重写父类的getItemCount方法用于返回RecyclerView中一共有多少子项
*/
@Override
public int getItemCount() {
return colorList.size();
}
}
好了,RecyclerView的适配器已经写好了,接下来我们新建一个布局文件recycler_view_activity.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:id="@+id/activity_recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context="com.example.administrator.listviewandrecycleview.RecycleViewActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
这个布局文件就是加入了一个RecyclerView控件,注意我们在使用不是SDK中原本就存在的控件时,要写入这个控件的完整路径名(包括我们自定义的控件),接下来新建一个Activity用于显示RecyclerView,RecyclerViewActivity.java:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import listview.Color;
import listview.ColorAdapterForRecyclerView;
public class RecyclerViewActivity extends AppCompatActivity {
private RecyclerView recyclerView = null;
private String colorName[];
private int colorId[];
private static final int colorSum = 6;
List<Color> colorList = new ArrayList<Color>();
private ColorAdapterForRecyclerView colorAdapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycle_view);
initAdapter(); // 初始化信息,和ListView中的类似,只是适配器的类型不同
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
/*
* 因为RecyclerView只负责自己本身的创建和回收,所以RecyclerView中的子项创建、子项布局方式、
* 分割线、动画效果等等都需要我们自己完成,正是这种完全解耦的机制成就了RecyclerView控件的
* 灵活性,里面的东西完全由我们自己的需求来编辑逻辑完成
*/
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager); // 设置布局方式为线性布局,默认为竖向布局
recyclerView.setAdapter(colorAdapter);
}
protected void initAdapter() {
colorAdapter = new ColorAdapterForRecyclerView(this, colorList);
colorName = new String[]{
"blue", "colors", "green", "pink", "puple", "yellow"};
colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,
R.mipmap.puple, R.mipmap.yellow};
for (int i = 0; i < colorSum; i++) {
Color color = new Color(colorName[i], colorId[i]);
colorList.add(color);
}
}
}
好了,大体上的代码我们都完成了,最后在主界面加一个按钮用于启动RecyclerViewActivity就行了。下面看运行结果:
这里依然是MainActivity中的显示,多了一个按钮用于启动RecyclerViewActivity。我们点击这个按钮:
启动了RecyclerViewActivity之后点击“green”那一行(单击别的行也是可以的),成功显示了我们设定的事件信息。那么接下来如何显示横向的滚动View呢,其实很简单:只需要在RecyclerViewActivity中加一句代码:
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置控件内排布方式为水平
如图:
我们还需要对color_item.xml文件进行修改
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/colorImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/colorNameTextView"
android:layout_marginLeft="10dp"
android:textSize="40sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
其实就是把排布方式改为该为竖直方向,使得排版更加美观。好了,再试试:
成功了,我们可以左右滑动来显示不同的子项。那么如果要显示网状布局呢?其实也很简单,我们只需要改RecyclerView的布局管理类型为网状布局就行了:
/*
* 设置网状布局管理器,每一行3个子项,排布方式为竖直方向排布
*/
StaggeredGridLayoutManager staggeredGriadLayoutManager = new StaggeredGridLayoutManager(
3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGriadLayoutManager);
如图:
来看看效果:
ok,和我们预想的一样
最后,这里只是RecyclerView控件的基本用法,RecyclerView控件的用法很多,我们可以自由的在控件里面加入分割线,子项减少和增加的动画效果等等,我们可以自由的定制属于我们的效果。有兴趣的小伙伴可以看一下这篇博文:为RecyclerView 控件添加分隔线:http://blog.csdn.net/hacker_zhidian/article/details/57487844。
如果博客中有什么不正确的地方,还请多多指点。 谢谢观看。。。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有