Android 控件GridView使用案例讲解
简介
GridView
是 Android 中常用的控件,用于显示多个相同类型的数据项。它类似于网格布局,将数据按行列方式排列,每个数据项都展示在一个格子里,用户可以通过滑动、缩放、选择来操作它们。在本篇文章中,我们将会讲解 GridView
的使用,包括创建、配置、自定义和优化等。
创建
在 Android Studio 中,我们可以使用 XML 布局文件创建 GridView
,代码如下:
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:numColumns="3"
android:gravity="center"
android:stretchMode="columnWidth"/>
在上面的布局代码中,我们定义了一个 GridView
,它有 id 为 grid_view
,宽高都为 match_parent,每行展示三个数据项,每个数据项之间有 10dp 的垂直和水平间距,数据项的宽度会自动缩放以占据一整列的空间,如果一行上的数据项不足三个,它们会在水平方向居中显示。
然后,在代码中我们需要找到这个 GridView
,并向它添加数据项:
GridView gridView = findViewById(R.id.grid_view);
gridView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new String[]{"Item 1", "Item 2", "Item 3", "Item 4", ...}));
在这里,我们使用了 ArrayAdapter
,将一个字符串数组中的每个元素都封装成了一个 TextView
,然后把这些 TextView
作为数据项添加到了 GridView
中。
配置
为了让 GridView
更好的呈现我们的数据,我们可以通过设置相应的属性来决定它的显示方式。下面是一些常用的属性和作用:
android:numColumns
:设置GridView
每行展示的数据项个数。android:verticalSpacing
:设置每个数据项之间的垂直间距。android:horizontalSpacing
:设置每个数据项之间的水平间距。android:gravity
:设置数据项在整个GridView
中的对齐方式。android:stretchMode
:设置数据项的宽度缩放模式,可以设置为columnWidth
、spacingWidth
或none
。
除了上述属性外,我们还可以通过代码来实现进一步的配置,如设置数据项的点击事件、长按事件等。示例代码如下:
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 处理点击事件
}
});
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// 处理长按事件
return true;
}
});
在上述代码中,我们分别设置了 GridView
的点击事件和长按事件,根据事件的类型,我们可以在相应的回调方法中编写相应的逻辑代码。
自定义
使用 ArrayAdapter
,每个数据项都会被封装成一个 TextView
,而且每个数据项的显示样式都是一样的。如果我们需要自定义每个数据项的样式,可以通过自定义适配器来实现。示例代码如下:
public class MyAdapter extends BaseAdapter {
private List<MyData> dataList;
private LayoutInflater inflater;
public MyAdapter(Context context, List<MyData> dataList) {
this.dataList = dataList;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.my_item_layout, parent, false);
viewHolder = new ViewHolder();
viewHolder.imageView = convertView.findViewById(R.id.item_image);
viewHolder.textView = convertView.findViewById(R.id.item_text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
MyData data = (MyData) getItem(position);
viewHolder.imageView.setImageResource(data.getImageId());
viewHolder.textView.setText(data.getName());
return convertView;
}
private static class ViewHolder {
ImageView imageView;
TextView textView;
}
}
在上述代码中,我们创建了一个 MyAdapter
类,继承自 BaseAdapter
,并重写了其四个重要的方法,分别是 getCount
、getItem
、getItemId
和 getView
。其中 getView
方法是最为重要的方法,它决定了每个数据项的显示样式。我们在 getView
方法中使用了一个 ViewHolder 类来优化列表项的渲染,提高了 GridView
的显示效率。
然后,在代码中我们创建了一个 MyData
类,用于封装数据项的信息,它包含一个图片 ID 和一个名称字段。在 getView
方法中,我们将每个数据项对应的图片和名称分别设置到它们对应的 ImageView
和 TextView
。
最后,在代码中,我们找到 GridView
,并将其适配器设置为 MyAdapter
的一个实例:
GridView gridView = findViewById(R.id.grid_view);
List<MyData> dataList = new ArrayList<>();
// 添加数据
gridView.setAdapter(new MyAdapter(this, dataList));
优化
在 GridView
中,每个数据项的布局随着列表项的增加会变得越来越昂贵,会导致应用程序变慢或崩溃。因此,在使用 GridView
时,我们需要采取一些优化措施,以保证它的流畅性。
-
使用 ViewHolder 模式:ViewHolder 模式可以减少每个列表项布局时创建视图对象的次数,能够极大地提高性能。通过使用 ViewHolder,我们可以将列表项的布局对象缓存在内存中,减少视图对象的创建次数。
-
使用 convertView 缓存视图对象:在绑定数据时,使用已经创建的视图资源能够加快列表项的创建速度。使用 convertView 来缓存视图可以重复使用之前加载的视图,将它们存储在内存中,以便下次使用。
-
异步加载图片资源:当我们在列表项中添加了图片资源时,应该采用异步加载的方式,以免阻塞主线程。可以使用 Glide、Picasso 等图片库来实现异步加载。
示例代码如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.my_item_layout, parent, false);
viewHolder = new ViewHolder();
viewHolder.imageView = convertView.findViewById(R.id.item_image);
viewHolder.textView = convertView.findViewById(R.id.item_text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
MyData data = (MyData) getItem(position);
Glide.with(context)
.load(data.getImageUrl())
.into(viewHolder.imageView);
viewHolder.textView.setText(data.getName());
return convertView;
}
在上述代码中,我们使用了 Glide 异步加载图片,提高了列表项的渲染速度。
示例说明
示例 1:展示图片列表
首先,我们准备一些图片资源,将它们显示在 GridView
中。我们可以使用自定义适配器来实现列表项的自定义,也可以使用 ArrayAdapter
来快速创建视图。示例代码如下:
GridView gridView = findViewById(R.id.grid_view);
List<String> imageUrlList = new ArrayList<>();
// 添加图片资源
gridView.setAdapter(new ImageAdapter(this, imageUrlList));
在这里,我们创建了一个 ImageAdapter
类,用于封装图片的 URL,将图片异步加载并显示到 ImageView
中。示例代码如下:
public class ImageAdapter extends BaseAdapter {
private List<String> imageUrlList;
private LayoutInflater inflater;
public ImageAdapter(Context context, List<String> imageUrlList) {
this.imageUrlList = imageUrlList;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return imageUrlList.size();
}
@Override
public Object getItem(int position) {
return imageUrlList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(parent.getContext());
} else {
imageView = (ImageView) convertView;
}
Glide.with(parent.getContext())
.load(getItem(position))
.into(imageView);
return imageView;
}
}
示例 2:展示应用程序列表
其次,我们使用 GridView
来展示应用程序图标和名称。这里,我们使用了系统应用程序图标和名称,通过解析应用程序的信息来进行展示。示例代码如下:
GridView gridView = findViewById(R.id.grid_view);
List<AppData> appList = new ArrayList<>();
// 获取应用程序信息
PackageManager packageManager = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resolveInfoList) {
AppData appData = new AppData();
appData.setName(resolveInfo.loadLabel(packageManager).toString());
appData.setIcon(resolveInfo.loadIcon(packageManager));
appList.add(appData);
}
// 设置适配器
gridView.setAdapter(new AppAdapter(this, appList));
在这里,我们通过调用 PackageManager
的 queryIntentActivities
方法来获取系统中所有的应用程序信息,然后将它们转换为列表项展示出来。示例代码如下:
public class AppData {
private String name;
private Drawable icon;
// 省略 getter 和 setter 方法
}
public class AppAdapter extends BaseAdapter {
private List<AppData> appList;
private LayoutInflater inflater;
public AppAdapter(Context context, List<AppData> appList) {
this.appList = appList;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return appList.size();
}
@Override
public Object getItem(int position) {
return appList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.app_item_layout, parent, false);
viewHolder = new ViewHolder();
viewHolder.imageView = convertView.findViewById(R.id.app_icon);
viewHolder.textView = convertView.findViewById(R.id.app_name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
AppData appData = (AppData) getItem(position);
viewHolder.imageView.setImageDrawable(appData.getIcon());
viewHolder.textView.setText(appData.getName());
return convertView;
}
private static class ViewHolder {
ImageView imageView;
TextView textView;
}
}
在这里,我们创建了一个 AppAdapter
类,用于封装应用程序的图标和名称,将它们展示到 ImageView
和 TextView
中。通过使用 ViewHolder 和 convertView 缓存视图,我们能够快速地创建和显示列表项,并减少视图对象的创建次数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android 控件GridView使用案例讲解 - Python技术站