Android 如何使用不同高度的单元格处理GridView?
注:好的,我承认标题有点模糊,但英语不是我的主要语言,我不知道如何用一句话来描述这个问题 背景 我正在尝试创建一个在gridView上显示所有应用程序信息的应用程序 gridView将其numColumns设置为auto_fit,以便为所有类型的屏幕很好地设置其列数 问题 由于每个应用程序的信息有时可能很长,因此单元格高度可能与它旁边的不同 我希望网格单元具有相同的宽度(在所有情况下都适用),并且对于每一行,高度应该由行单元的最大高度确定 这会导致奇怪的事情发生:Android 如何使用不同高度的单元格处理GridView?,android,textview,android-gridview,marquee,Android,Textview,Android Gridview,Marquee,注:好的,我承认标题有点模糊,但英语不是我的主要语言,我不知道如何用一句话来描述这个问题 背景 我正在尝试创建一个在gridView上显示所有应用程序信息的应用程序 gridView将其numColumns设置为auto_fit,以便为所有类型的屏幕很好地设置其列数 问题 由于每个应用程序的信息有时可能很长,因此单元格高度可能与它旁边的不同 我希望网格单元具有相同的宽度(在所有情况下都适用),并且对于每一行,高度应该由行单元的最大高度确定 这会导致奇怪的事情发生: 罕见:一些细胞正在变空。有时,
<?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>
我试过的
我尝试了多种可能的解决方案:
有没有一种方法可以使文本视图保持固定大小,同时允许它们使用滚动(手动或自动)显示其内容?好的,我找到了一个很好的解决方案,这将使行取决于它们的子行,但为此我不得不做出一些妥协:
_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));