当前位置: 移动技术网 > 移动技术>移动开发>Android > 详解Android使GridView横向水平滚动的实现方式

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

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来实现此类需求。

希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网