Android 控件GridView使用案例讲解

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:设置数据项的宽度缩放模式,可以设置为 columnWidthspacingWidthnone

除了上述属性外,我们还可以通过代码来实现进一步的配置,如设置数据项的点击事件、长按事件等。示例代码如下:

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,并重写了其四个重要的方法,分别是 getCountgetItemgetItemIdgetView。其中 getView 方法是最为重要的方法,它决定了每个数据项的显示样式。我们在 getView 方法中使用了一个 ViewHolder 类来优化列表项的渲染,提高了 GridView 的显示效率。

然后,在代码中我们创建了一个 MyData 类,用于封装数据项的信息,它包含一个图片 ID 和一个名称字段。在 getView 方法中,我们将每个数据项对应的图片和名称分别设置到它们对应的 ImageViewTextView

最后,在代码中,我们找到 GridView,并将其适配器设置为 MyAdapter 的一个实例:

GridView gridView = findViewById(R.id.grid_view);
List<MyData> dataList = new ArrayList<>();
// 添加数据
gridView.setAdapter(new MyAdapter(this, dataList));

优化

GridView 中,每个数据项的布局随着列表项的增加会变得越来越昂贵,会导致应用程序变慢或崩溃。因此,在使用 GridView 时,我们需要采取一些优化措施,以保证它的流畅性。

  1. 使用 ViewHolder 模式:ViewHolder 模式可以减少每个列表项布局时创建视图对象的次数,能够极大地提高性能。通过使用 ViewHolder,我们可以将列表项的布局对象缓存在内存中,减少视图对象的创建次数。

  2. 使用 convertView 缓存视图对象:在绑定数据时,使用已经创建的视图资源能够加快列表项的创建速度。使用 convertView 来缓存视图可以重复使用之前加载的视图,将它们存储在内存中,以便下次使用。

  3. 异步加载图片资源:当我们在列表项中添加了图片资源时,应该采用异步加载的方式,以免阻塞主线程。可以使用 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));

在这里,我们通过调用 PackageManagerqueryIntentActivities 方法来获取系统中所有的应用程序信息,然后将它们转换为列表项展示出来。示例代码如下:

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 类,用于封装应用程序的图标和名称,将它们展示到 ImageViewTextView 中。通过使用 ViewHolder 和 convertView 缓存视图,我们能够快速地创建和显示列表项,并减少视图对象的创建次数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android 控件GridView使用案例讲解 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • 关于版本控制:如何强制”gitpull”覆盖本地文件?

    以下是关于如何强制git pull覆盖本地文件的完整攻略,包括两个示例说明: 1. 使用git reset命令 我们可以使用git reset命令强制git pull覆盖本地文件。以下是详细步骤: 在本地仓库中,使用命令获取最新的远程分支。 git reset命令将本地分支重置为远程分支。例如,如果我们要将本地分支master重为远程分支origin/mas…

    other 2023年5月7日
    00
  • 思科cisco路由器dhcp动态分配ip地址实现方法

    思科Cisco路由器DHCP动态分配IP地址实现方法攻略 介绍 动态主机配置协议(DHCP)是一种网络协议,用于自动分配IP地址和其他网络配置参数给网络上的设备。在思科Cisco路由器上,您可以配置DHCP服务器来实现动态分配IP地址的功能。下面是一个详细的攻略,介绍了如何在思科Cisco路由器上配置DHCP服务器。 步骤 步骤1:进入路由器配置模式 首先,…

    other 2023年7月31日
    00
  • Python学习笔记之字符串和字符串方法实例详解

    Python学习笔记之字符串和字符串方法实例详解 1. 字符串的基本操作 字符串是Python中常用的数据类型之一。字符串可以看做是由多个字符组成的序列,它们可以通过下标来访问。下面介绍一些字符串的基本操作。 1.1 字符串的下标访问 在Python中,我们可以使用下标来访问字符串中的单个字符。下标从0开始,表示第1个字符,依次类推。例如,对于字符串”hel…

    other 2023年6月20日
    00
  • jsjson转字符串

    jsjson转字符串 在 JavaScript 中,JSON(JavaScript Object Notation)格式是一个非常常见的数据交换格式。但有时候我们需要把 JSON 对象转换成字符串类型,以便于传输和存储。 本文将介绍如何使用 JavaScript 把 JSON 转化为字符串类型。 JSON.stringify() JSON.stringify…

    其他 2023年3月29日
    00
  • Python嵌套函数与nonlocal使用详细介绍

    Python嵌套函数与nonlocal使用详细介绍 在Python中,嵌套函数是指在一个函数内部定义另一个函数。这种嵌套的函数可以访问外部函数的变量,并且可以在外部函数的作用域内进行操作。而nonlocal关键字则用于在嵌套函数中修改外部函数的局部变量。本文将详细介绍Python中嵌套函数的概念以及如何使用nonlocal关键字。 嵌套函数的定义和使用 嵌套…

    other 2023年7月27日
    00
  • Java 中 Class Path 和 Package的使用详解

    Java 中 Class Path 和 Package 的使用详解 在 Java 开发中,Class Path 和 Package 是两个重要的概念。本攻略将详细讲解它们的使用方法和区别。 Class Path Class Path 是指 Java 虚拟机(JVM)用于查找类文件的路径。它可以是文件系统中的目录或者 JAR 文件。在编译和运行 Java 程序…

    other 2023年10月13日
    00
  • 相片管理必备:文件批量改名工具 自动以日期时间命名

    当你需要整理相机中的大量照片时,可能会遇到相同文件名的情况,这样就会导致照片的混乱和找寻困难。因此,我们可以使用文件批量改名工具来自动化处理。 工具介绍 常见的文件批量修改工具有:Bulk Rename Utility,ReNamer,A Better Finder Rename等。以Bulk Rename Utility为例,它是一款免费的Windows文…

    other 2023年6月26日
    00
  • lambda动态表达式(排序)

    Lambda动态表达式(排序) 在程序开发中,经常需要对集合中的元素进行排序。对于基本类型的数组,可以使用Java中的Arrays.sort()方法进行排序。然而,对于自定义类型的元素,需要实现Comparable接口来实现排序,这会增加代码的复杂性。此时,我们可以使用Lambda动态表达式来实现排序功能。 Lambda表达式是Java8引入的一个重要特性,…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部