Ответ 1
Хорошо, я нашел для этого приятное решение, которое заставит строки зависеть от их детей, но для этого мне пришлось сделать некоторые компромиссы:
-
это адаптер для 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 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;
}
}