如何用不同高度的细胞处理GridView的? [英] How to handle GridView with cell of different heights?

查看:131
本文介绍了如何用不同高度的细胞处理GridView的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注:好吧,我承认标题是有点模糊,但英语不是我的主要语言,我不知道如何来形容这个问题在一个森泰斯。

NOTE: OK, I admit the title is a bit vague, but English is not my main language, and I'm not sure how to describe the problem in one sentance.

我试图创建一个应用程序,显示了一个GridView的所有应用程序的信息。

I'm trying to create an app that shows all apps information on a gridView.

在GridView有其为numColumns设为auto_fit,使列的数量将很好地为所有类型的屏幕。

The gridView has its numColumns set to auto_fit , so that its number of columns will be set nicely for all types of screens.

因为每个应用程序的信息,有时是长,细胞高度可为那些在它旁边不同

Since each app's information can sometimes be long, the cell height can be different from those that are next to it.

欲网格单元是相同的宽度(其在所有情况下正常工作),并且对于每一行,其高度应通过该行的单元格的最大高度被确定。

I want the grid cells to be of the same width (which works fine on all cases), and for each row, the height should be determined by the max height of the row's cells.

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

This causes weird things to occur:

  1. 罕见:有的细胞变空。有时,当滚动和返回那里,细胞得到填补...
  2. 在相当普遍:有的细胞笼络其他细胞
  3. 在相当普遍:有的细胞不走,他们可以乘坐空间,留下无法点击空
  4. 非常罕见:与滚动播放的时候,如果你一路滚动到顶部,你会得到整个网格是空的,而不是滚动...

下面是截图同时显示#2,#3的问题(他们通常不会显示在一起):

Here is a screenshot showing both #2 and #3 issues (they don't usually show together) :

这是网格单元的XML:

This is the xml of the grid cell :

<?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>

我已经试过

我已经试过多种可能的解决方案:

What I've tried

I've tried multiple possible solutions:

  1. 使用Horizo​​ntalListView似乎解决这​​个问题,但它不允许点击/长击上的项目。

  1. using HorizontalListView seems to solve this, but then it doesn't allow clicking/long clicking on items.

我找到了一个不错的库使textViews有一个帐篷效应( < STRONG>此处 ),但它的许可证是不那么宽容。

I've found a nice library for making the textViews have a "marquee" effect (here) , but its license isn't so permissive.

设置单元格高度为固定一个或设置有固定的线路也记工作textViews,但随后削减了(部分)textViews的内容,而不向他们展示的能力。

Setting the cell height as fixed one or setting the textViews to have fixed lines count also work, but then it cuts down (part of) the content of the textViews without the ability to show them.

我也试着使用linearLayouts代替RelativeLayout的,但它并没有帮助。

I've also tried using linearLayouts instead of RelativeLayout, but it didn't help.

一个可能的解决方案是让使用上的GridView控件(使用getView上的所有项目),类似的 这code ,但它可以让你知道的列数,并且您也希望所有细胞是相同的高度。

a possible solution is to get the max height used by all views on the gridView (using getView on all items) , similar to this code, but it assumes you know the number of columns , and that you do want all cells to be of the same height.

我应该如何处理呢?

我应该真的使用类似 StaggeredGrid

Should I really use something like StaggeredGrid ?

有没有办法把textViews保持固定的大小而允许他们采用滚动(手动或自动)?

Is there a way to put the textViews to stay fixed in size yet allow them to show their content using scrolling (manually or automatically) ?

推荐答案

好了,我发现这是一个很好的解决方案,这将使得该行依靠子女,而是为了这个,我不得不做出一些妥协:

OK, i've found a nice solution for this, which will make the rows depend on their children, but for this I had to make some compromises :

  1. 这对一个列表视图,它具有水平线性布局其行的适配器。

  1. it's an adapter for a listView , which has horizontal linear layouts for its rows.

谁使用这个code应设置单元格的选择,选择做什么上点击或长击。

whoever uses this code should set the selector of the cells and choose what to do on clicking or long clicking.

谁使用这个code应该准备prepare对于ListView额外的最后一个单元格空单元格。

whoever uses this code should be ready to prepare an empty cell for the extra last cells of the listView.

这是用来应其listSelector设置为透明的列表视图,以禁止点击行。

the listView that is used should have its listSelector set to transparent, to disallow clicking on rows.

我希望任何人都可以做一个更好的解决方案,而无需额外的观点。

I hope anyone could make a better solution that won't need extra views.

示例用法:

_listAdapter=new GriddedListViewAdapter();
_listAdapter.setNumberOfColumns(numberOfColumns);
-listAdapter.setItems(items);
_listView.setAdapter(_listAdapter);

这里的code:

Here's the code:

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;
    }
  }

这篇关于如何用不同高度的细胞处理GridView的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆