Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何使用不同高度的单元格处理GridView?_Android_Textview_Android Gridview_Marquee - Fatal编程技术网

Android 如何使用不同高度的单元格处理GridView?

Android 如何使用不同高度的单元格处理GridView?,android,textview,android-gridview,marquee,Android,Textview,Android Gridview,Marquee,注:好的,我承认标题有点模糊,但英语不是我的主要语言,我不知道如何用一句话来描述这个问题 背景 我正在尝试创建一个在gridView上显示所有应用程序信息的应用程序 gridView将其numColumns设置为auto_fit,以便为所有类型的屏幕很好地设置其列数 问题 由于每个应用程序的信息有时可能很长,因此单元格高度可能与它旁边的不同 我希望网格单元具有相同的宽度(在所有情况下都适用),并且对于每一行,高度应该由行单元的最大高度确定 这会导致奇怪的事情发生: 罕见:一些细胞正在变空。有时,

注:好的,我承认标题有点模糊,但英语不是我的主要语言,我不知道如何用一句话来描述这个问题

背景 我正在尝试创建一个在gridView上显示所有应用程序信息的应用程序

gridView将其numColumns设置为auto_fit,以便为所有类型的屏幕很好地设置其列数

问题 由于每个应用程序的信息有时可能很长,因此单元格高度可能与它旁边的不同

我希望网格单元具有相同的宽度(在所有情况下都适用),并且对于每一行,高度应该由行单元的最大高度确定

这会导致奇怪的事情发生:

  • 罕见:一些细胞正在变空。有时,当滚动并返回时,单元格会被填满
  • 很常见:一些细胞会在其他细胞上画
  • 很常见:有些单元格不占用它们可以占用的空间,留下无法单击的空白空间
  • 非常罕见:当玩滚动时,如果你一直滚动到顶部,你会得到整个网格为空且不可滚动 下面是一个屏幕截图,显示了第2和第3个问题(它们通常不会同时显示):

    我用过的代码 这是网格单元的xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/list_divider_holo_dark" >
    
        <ImageView
            android:id="@+id/appIconImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:adjustViewBounds="true"
            android:contentDescription="@string/app_icon"
            android:src="@drawable/ic_menu_help" />
    
        <TextView
            android:id="@+id/appLabelTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@+id/isSystemAppImageView"
            android:layout_toRightOf="@+id/appIconImageView"
            android:ellipsize="marquee"
            android:text="label"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textStyle="bold"
            tools:ignore="HardcodedText" />
    
        <TextView
            android:id="@+id/appDescriptionTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/appLabelTextView"
            android:layout_below="@+id/appLabelTextView"
            android:layout_toLeftOf="@+id/isSystemAppImageView"
            android:ellipsize="marquee"
            android:text="description"
            tools:ignore="HardcodedText" />
    
        <ImageView
            android:id="@+id/isSystemAppImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/appDescriptionTextView"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:adjustViewBounds="true"
            android:contentDescription="@string/content_description_this_is_a_system_app"
            android:src="@drawable/stat_sys_warning" />
    
    </RelativeLayout>
    
    
    
    我试过的 我尝试了多种可能的解决方案:

  • 使用HorizontalListView似乎可以解决这个问题,但它不允许单击/长时间单击项目

  • 我发现了一个很好的库,可以使TextView具有“选框”效果(),但它的许可证并不那么宽松

  • 将单元格高度设置为fixed one或将TextView设置为fixed lines count也可以,但这样会减少TextView的内容(部分内容),而无法显示它们

  • 我也尝试过使用linearLayouts而不是RelativeLayout,但没有效果

  • 一种可能的解决方案是获取gridView上所有视图使用的最大高度(在所有项上使用getView),类似于,但它假定您知道列数,并且确实希望所有单元格具有相同的高度

  • 问题 我该怎么处理

    我真的应该用像这样的东西吗


    有没有一种方法可以使文本视图保持固定大小,同时允许它们使用滚动(手动或自动)显示其内容?

    好的,我找到了一个很好的解决方案,这将使行取决于它们的子行,但为此我不得不做出一些妥协:

  • 它是listView的适配器,它的行具有水平线性布局

  • 使用此代码的人应设置单元格选择器,并选择单击或长时间单击时要执行的操作

  • 使用此代码的人应该准备好为listView的额外最后一个单元格准备一个空单元格

  • 所使用的listView应将其listSelector设置为透明,以禁止单击行

  • 我希望任何人都能提出一个更好的解决方案,而不需要额外的视图

    示例用法:

    _listAdapter=new GriddedListViewAdapter();
    _listAdapter.setNumberOfColumns(numberOfColumns);
    -listAdapter.setItems(items);
    _listView.setAdapter(_listAdapter);
    
    代码如下:

    public abstract class GriddedListViewAdapter<ItemType> extends BaseAdapter
      {
      private int                       _numColumns =1;
      private final List<Row<ItemType>> _rows       =new ArrayList<Row<ItemType>>();
      protected final Context           _context    =App.global();
      private List<ItemType>            _items;
    
      public void setItems(final List<ItemType> items)
        {
        _items=items;
        prepareRows();
        notifyDataSetChanged();
        }
    
      private void prepareRows()
        {
        _rows.clear();
        final int itemsCount=_items.size();
        for(int i=0;i<itemsCount;i+=_numColumns)
          {
          final Row<ItemType> row=new Row<ItemType>();
          row.startIndex=i;
          row.items=new ArrayList<ItemType>(_numColumns);
          for(int j=0;j<_numColumns;++j)
            {
            ItemType item;
            if(i+j<itemsCount)
              item=_items.get(i+j);
            else item=null;
            row.items.add(item);
            }
          _rows.add(row);
          }
        }
    
      public void setNumberOfColumns(final int numColumns)
        {
        if(_numColumns==numColumns)
          return;
        _numColumns=numColumns;
        if(_items!=null)
          {
          prepareRows();
          notifyDataSetChanged();
          }
        }
    
      @Override
      public final int getCount()
        {
        return _rows.size();
        }
    
      @Override
      public final Row<ItemType> getItem(final int position)
        {
        return _rows.get(position);
        }
    
      @Override
      public final long getItemId(final int position)
        {
        return position;
        }
    
      @TargetApi(Build.VERSION_CODES.HONEYCOMB)
      @Override
      public final View getView(final int position,final View convertView,final ViewGroup parent)
        {
        final Row<ItemType> row=getItem(position);
        IcsLinearLayout rowLayout=(IcsLinearLayout)convertView;
        if(rowLayout==null)
          {
          rowLayout=new IcsLinearLayout(_context,null);
          rowLayout.setMeasureWithLargestChildEnabled(true);
          rowLayout.setShowDividers(IcsLinearLayout.SHOW_DIVIDER_MIDDLE);
          rowLayout.setDividerDrawable(_context.getResources().getDrawable(R.drawable.list_divider_holo_dark));
          rowLayout.setOrientation(LinearLayout.HORIZONTAL);
          rowLayout.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
          }
        final int childCount=rowLayout.getChildCount();
        for(int i=childCount;i>_numColumns;--i)
          rowLayout.removeViewAt(i-1);
        // reuse previous views of the row if possible
        for(int i=0;i<_numColumns;++i)
          {
          // reuse old views if possible
          final View cellConvertView=i<childCount ? rowLayout.getChildAt(i) : null;
          // fill cell with data
          final View cellView=getCellView(row.items.get(i),row.startIndex+i,cellConvertView,rowLayout);
          LinearLayout.LayoutParams layoutParams=(LinearLayout.LayoutParams)cellView.getLayoutParams();
          if(layoutParams==null)
            {
            layoutParams=new LinearLayout.LayoutParams(0,LayoutParams.MATCH_PARENT,1);
            layoutParams.gravity=Gravity.CENTER_VERTICAL;
            cellView.setLayoutParams(layoutParams);
            }
          else
            {
            final boolean needSetting=layoutParams.weight!=1||layoutParams.width!=0||layoutParams.height!=LayoutParams.MATCH_PARENT;
            if(needSetting)
              {
              layoutParams.width=0;
              layoutParams.height=LayoutParams.MATCH_PARENT;
              layoutParams.gravity=Gravity.CENTER_VERTICAL;
              layoutParams.weight=1;
              cellView.setLayoutParams(layoutParams);
              }
            }
          if(cellConvertView==null)
            rowLayout.addView(cellView);
          }
        return rowLayout;
        }
    
      @Override
      public final int getViewTypeCount()
        {
        return super.getViewTypeCount();
        }
    
      @Override
      public final int getItemViewType(final int position)
        {
        return super.getItemViewType(position);
        }
    
      /**
       * should handle getting a single cell view. <br/>
       * NOTE:read the parameters description carefully !
       * 
       * @param item
       * the item that is associated with the cell. if null, you should prepare an empty cell
       * @param rawPosition the position within the original list of items that is associated with the cell
       * @param convertView
       * a recycled cell. you must use it when it's not null, fill it with data, and return it
       * @param parent
       * the parent of the view. you should use it for inflating the view (but don't attach the view to the
       * parent)
       */
      public abstract View getCellView(ItemType item,int rawPosition,View convertView,ViewGroup parent);
    
      // ////////////////////////////////////
      // Row//
      // /////
      private static class Row<ItemType>
        {
        int                 startIndex;
        ArrayList<ItemType> items;
        }
      }
    
    公共抽象类GriddedListViewAdapter扩展了BaseAdapter
    {
    私有整数列=1;
    私有最终列表_rows=new ArrayList();
    受保护的最终上下文_Context=App.global();
    私人物品清单;
    公共无效设置项(最终列表项)
    {
    _项目=项目;
    prepareRows();
    notifyDataSetChanged();
    }
    私有无效预处理程序()
    {
    _行。清除();
    final int itemsCount=_items.size();
    
    对于(int i=0;i,这里有一个有效的解决方案:

    在该链接上解释的解决方案是基于其所有元素的高度(使用最大高度)计算每行高度

    它通过捕捉onScrollChanged事件并在每次FirstVisiblePosition更改时更新高度来实现这一点

    经过测试,它工作得很好,除了一个问题:一旦行大小增加,它就不会减少


    实际代码可在此处找到:

    上述解决方案的替代方案是使用和:


    您是否尝试过设置封闭相对布局的
    layout\u height=“wrap\u content”
    ?@KubaSpatny是的。遗憾的是,它没有帮助:(好的,Edgrid肯定会起作用,但可能有点过头了。你的意思是使用字幕效果库,你自己尝试过实现它吗?我没有,因为我不知道该怎么做以及需要多长时间。我在想也许它应该从horizontalScrollView扩展,但它不会被触摸。我也需要对它进行足够的定制,以告诉它如何移动。TextView和android:ellipsize=“marquee”都有
    android:maxLines=“4”
    标签(或
    android:maxLength=“10”
    然而,listview中的问题是,只有当某个视图处于焦点时,它才会滚动。因此,您必须创建一个扩展TextView的类(如图所示),但也有一个RecycleView的解决方案。我一直认为RecycleView像listview,而不是GridView,但我可能错了。Recy中可以有多个列吗clerView?GridView的问题是它有缺陷。RecyclerView可以按照您的意愿显示项目。唯一的问题是它的复杂性,因为它具有很高的模块性,并且它遗漏了一些我们曾经使用过的东西,比如快速卷轴、页眉和页脚。对于快速卷轴,我创建了一个库(这里:)。对于页脚和页眉,您需要将第一项和最后一项设置为不同的类型,遗憾的是,类似于ListView。然后,使用RecyclerView发布答案可能会很有用?
    recyclerView.setHasFixedSize(false);
    recyclerView.setLayoutManager(new GridLayoutManager(this, 2));