详解Android使GridView横向水平滚动的实现方式

发布时间 - 2026-01-11 00:57:25    点击率:

Android为我们提供了竖直方向的滚动控件GridView,但如果我们想让它水平滚动起来,就需要自己实现了。

以下使用的测试数据datas集合都为List<ResolveInfo>类型,用来存储手机中的所有App

  public static List<ResolveInfo> getAppData(Context context) {
    PackageManager packageManager = context.getPackageManager();
    Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    return packageManager.queryIntentActivities(mainIntent, 0);
  }

一、单行横向显示

实现思路

  1. 在代码中动态设置GridView的NumColumns,使其等于GridView要显示的数据集合大小。
  2. 动态设置item项宽度,结合数据集合大小来设置GridView的总宽度。
  3. 使用HorizontalScrollView包裹GridView

具体实现

关键代码

  /**
   * 将GridView改成单行横向布局
   */
  private void changeGridView() {
    // item宽度
    int itemWidth = DensityUtil.dip2px(this, 100);
    // item之间的间隔
    int itemPaddingH = DensityUtil.dip2px(this, 1);
    int size = datas.size();
    // 计算GridView宽度
    int gridviewWidth = size * (itemWidth + itemPaddingH);

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
        gridviewWidth, LinearLayout.LayoutParams.MATCH_PARENT);
    mContentGv.setLayoutParams(params);
    mContentGv.setColumnWidth(itemWidth);
    mContentGv.setHorizontalSpacing(itemPaddingH);
    mContentGv.setStretchMode(GridView.NO_STRETCH);
    mContentGv.setNumColumns(size);
  }

这里用到的dip2px方法是根据手机的分辨率从 dp 的单位 转成为 px(像素)

  /**
   * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
   * @param context  上下文
   * @param dpValue  dp值
   * @return px值
   */
  public static int dip2px(Context context, float dpValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
  }

在布局文件中,使用HorizontalScrollView包裹GridView

  <HorizontalScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="none">
    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <GridView
        android:id="@+id/gv_horizontal_gridview_line"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none"/>
    </LinearLayout>
  </HorizontalScrollView>

通过以上设置,再加上Adapter适配器就能实现单行横向滚动了,适配器使用常规的实现方式就行,这里就不贴了

二、多行横向分页显示

实现思路

  1. 使用ViewPager实现左右翻页效果。
  2. 根据数据集合大小,计算出要显示的页数,并生成相应数量的GridView。
  3. 在GridView的Adapter适配器中,动态分配GridView需要显示的数据集合。
  4. 使用List保存多个GridView实例并传入ViewPager适配器中,一页ViewPager对应一个GridView实例。

具体实现

数据量很多时,需要进行分页,计算方式

需要页数 = 总数量 ÷ 每页显示数量

有些整除不了的,就需要使用Math.ceil()函数,向上取整

关键代码

  /**
   * 获取系统所有的应用程序,根据每页需要显示的item数量,生成相应数量的GridView页面
   */
  private void initViews(List<ResolveInfo> datas) {
    int dataSize = datas.size();

    // (需要页数 = 总数量 ÷ 每页显示数量)向上取整数
    int PageCount = (int) Math.ceil(dataSize / APP_SIZE);
    mGridViewList = new ArrayList<>();
    for (int i = 0; i <= PageCount; i++) {
      GridView appPage = new GridView(this);
      appPage.setAdapter(new HorizontalGvAdapter(this, datas, i));
      appPage.setNumColumns(4);
      appPage.setVerticalSpacing(1);
      appPage.setHorizontalSpacing(1);
      appPage.setHorizontalScrollBarEnabled(false);
      appPage.setVerticalScrollBarEnabled(false);
      mGridViewList.add(appPage);
    }

    if(dataSize % APP_SIZE == 0){
      mGridViewList.remove(mGridViewList.size()-1);
      PageCount--;
    }

    mGvPagerAdapter = new HorizontalGvPagerAdapter(mGridViewList);
    viewPager.setAdapter(mGvPagerAdapter);
    viewPager.addOnPageChangeListener(new MyPageChangeListener());

    addDot(PageCount);
  }

当总数量 ÷ 每页显示数量刚好被整除时,会出现一页空白页的情况,这个时候需要去掉多出来的那一页

    if(dataSize % APP_SIZE == 0){
      mGridViewList.remove(mGridViewList.size()-1);
      PageCount--;
    }

Adapter在创建初期就要对显示的数据进行控制,因为这里每个GridView都有一个单独的Adapter,所以需要对其显示的datas进行动态计算

通过传入构造方法的数据进行动态计算,可以得出数据开始加载的位置、结束加载的位置

HorizontalGvAdapter的构造方法:

  /**
   * 所有应用数据
   */
  private List<ResolveInfo> mAppDatas = new ArrayList<ResolveInfo>();

  public HorizontalGvAdapter(Context context, List<ResolveInfo> list, int page) {
    this.mContext = context;

    // 开始加载的位置
    int pageStart = page * HorizontalGridViewAct.APP_SIZE;
    // 结束加载的位置
    int pageEnd = pageStart + HorizontalGridViewAct.APP_SIZE;

    while ((pageStart < list.size()) && (pageStart < pageEnd)) {
      mAppDatas.add(list.get(pageStart));
      pageStart++;
    }
  }

如果需要加小圆点的话,可以先在布局中用一个空LinearLayout当小圆点的容器

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="#ffffff"
       android:orientation="vertical">
  <android.support.v4.view.ViewPager
    android:id="@+id/vp_horizontal_gridview"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:layout_gravity="center"
    android:background="#c5c5c5"
    android:scaleType="fitXY"/>

  <!-- 底部小圆点 -->
  <LinearLayout
    android:id="@+id/ll_dot_container"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#4b4b4b"
    android:layout_gravity="bottom"
    android:gravity="center"
    android:orientation="horizontal"/>
</LinearLayout>

然后在代码中用List<View>来保存创建的小圆点

  // 放圆点的list
  private List<View> dotViewsList;

  /**
   * 创建指定数量的圆点
   * @param dotNumber viewPager的数量
   */
  private void addDot(int dotNumber) {
    if (null == dotViewsList) {
      dotViewsList = new ArrayList<View>();
    }
    LinearLayout dotLayout = (LinearLayout) findViewById(R.id.ll_dot_container);
    for (int i = 0; i <= dotNumber; i++) {
      ImageView dotView = new ImageView(this);
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
          FrameLayout.LayoutParams.WRAP_CONTENT,
          FrameLayout.LayoutParams.WRAP_CONTENT);

      // 圆点与圆点之间的距离
      params.leftMargin = 10;
      params.rightMargin = 10;

      // 圆点的大小
      params.height = 15;
      params.width = 15;

      dotLayout.addView(dotView, params);
      dotViewsList.add(dotView);
    }
    // 设置圆点默认选中第一个
    setDotShow(0);
  }
动态添加完小圆点后,就可以设置它们的选中状态了,这里只需要更改对应小圆点的图片显示就行

  /**
   * 显示底部圆点导航
   * @param position 选中哪个圆点
   */
  private void setDotShow(int position){
    if (dotViewsList == null){
      return;
    }
    for (int i = 0; i < dotViewsList.size(); i++) {
      if (i == position) {
        dotViewsList.get(position).setBackgroundResource(R.drawable.ic_dot_on);
      } else {
        dotViewsList.get(i).setBackgroundResource(R.drawable.ic_dot_off);
      }
    }
  }

三、总结

以上就是让GridView横向滚动的实现方式,其实我们完全可以不必这么麻烦,Google在support-v7包中为我们提供了RecyclerView控件,切换横向和竖直滚动只需要让布局管理器使用setOrientation方法设置一下就好,非常便捷,如果项目允许,建议使用RecyclerView来实现此类需求。

希望对大家的学习有所帮助,也希望大家多多支持。


# gridview横向水平滚动  # gridview横向滚动  # gridview  # 横向滚动条  # android开发之横向滚动/竖向滚动的ListView(固定列头)  # Android程序开发之ListView实现横向滚动(带表头与固定列)  # Android使用GridView实现横向滚动效果  # Android开发实现横向列表GridView横向滚动的方法【附源码下载】  # Android GridView实现横向列表水平滚动  # Android自定义ViewGroup实现可滚动的横向布局(2)  # Android实现自定义的弹幕效果  # 实例解析如何在Android应用中实现弹幕动画效果  # Android 实现仿网络直播弹幕功能详解及实例  # Android实现横向无限循环滚动的单行弹幕效果  # 圆点  # 每页  # 小圆点  # 加载  # 就行  # 分页  # 转成  # 都有  # 第一个  # 就能  # 多个  # 就不  # 就好  # 只需  # 再加上  # 对其  # 此类  # 这个时候  # 使其  # 要让 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 怎么用AI帮你设计一套个性化的手机App图标?  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  Android 常见的图片加载框架详细介绍  奇安信“盘古石”团队突破 iOS 26.1 提权  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  javascript中的数组方法有哪些_如何利用数组方法简化数据处理  Android仿QQ列表左滑删除操作  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  JavaScript如何实现继承_有哪些常用方法  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  如何用AWS免费套餐快速搭建高效网站?  原生JS实现图片轮播切换效果  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  QQ浏览器网页版登录入口 个人中心在线进入  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  动图在线制作网站有哪些,滑动动图图集怎么做?  C++时间戳转换成日期时间的步骤和示例代码  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Python文本处理实践_日志清洗解析【指导】  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  JavaScript如何实现音频处理_Web Audio API如何工作?  Android中AutoCompleteTextView自动提示  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】  phpredis提高消息队列的实时性方法(推荐)  java中使用zxing批量生成二维码立牌  Python面向对象测试方法_mock解析【教程】  高防服务器如何保障网站安全无虞?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  Laravel如何使用Eloquent进行子查询  iOS发送验证码倒计时应用  如何为不同团队 ID 动态生成多个“认领值班”按钮  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  Laravel如何生成URL和重定向?(路由助手函数)  Python自动化办公教程_ExcelWordPDF批量处理案例  昵图网官方站入口 昵图网素材图库官网入口  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  JavaScript如何实现路由_前端路由原理是什么  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  Laravel怎么上传文件_Laravel图片上传及存储配置  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  黑客如何利用漏洞与弱口令入侵网站服务器?