Вы не можете вкладывать прокручиваемые представления в Android - то есть ListView, GridView, ScrollView.
Вы можете взглянуть на следующий код:
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.GridView;
public class ScrollableGridView extends GridView {
boolean expanded = true;
public ScrollableGridView(Context context)
{
super(context);
}
public ScrollableGridView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ScrollableGridView(Context context, AttributeSet attrs,
int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// But do not use the highest 2 bits of this integer; those are
// reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
Это немного лучшая версия GridView, позволяющая практически работать при вложении в ScrollView. Я сказал «почти работа», так как иногда он был на 20-30 пикселей слишком коротким или слишком длинным.
Следует помнить, что это предотвратит повторное использование представлений, поэтому оно намного тяжелее обычного GridView.
В моем случае я закончил расширением LinearLayout и использовал его для выравнивания его дочерних элементов в столбцах. Это было не очень сложно - я могу привести примеры, если хотите. :)
Я получил пример GridView от этого ответа .
Вот пример для GridView, основанного на LinearLayout:
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class GridLikeLayout extends LinearLayout {
private static final int DEFAULT_ITEMS_PER_ROW = 1;
private final int DEFAULT_COLUMN_WIDTH = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 150, getContext().getResources()
.getDisplayMetrics());
private int itemsPerRow = DEFAULT_ITEMS_PER_ROW;
private List<View> innerViews = null;
private int columnWidth;
public GridLikeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.GridLikeLayout);
// itemsPerRow = a.getInt( R.styleable.GridLikeLayout_columns,
// DEFAULT_ITEMS_PER_ROW);
try {
columnWidth = (int) a.getDimension(
R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH);
} catch (UnsupportedOperationException uoe) {
columnWidth = (int) a.getInt(
R.styleable.GridLikeLayout_column_width, DEFAULT_COLUMN_WIDTH);
}
setOrientation(LinearLayout.VERTICAL);
}
public GridLikeLayout(Context context) {
super(context);
setOrientation(LinearLayout.VERTICAL);
}
public void setInnerViews(List<View> innerViews) {
this.innerViews = innerViews;
processViews();
}
public List<View> getInnerViews() {
return innerViews;
}
protected void processViews() {
if (null != innerViews) {
LinearLayout innerContainer = null;
innerContainer = generateInnerContainer();
int childrenCount = innerViews.size();
for (int index = 0; index < childrenCount; ++index) {
if (isFull(innerContainer)) {
addInnerContainer(innerContainer);
innerContainer = generateInnerContainer();
}
View child = innerViews.get(index);
if (null != child.getParent()) {
((ViewGroup) child.getParent()).removeView(child);
}
addInnerView(innerContainer, child);
}
addInnerContainer(innerContainer);
}
}
protected boolean isFull(LinearLayout innerContainer) {
return 0 == (innerContainer.getChildCount() % itemsPerRow)
&& 0 < innerContainer.getChildCount();
}
protected void addInnerView(LinearLayout innerContainer, View child) {
int width = LayoutParams.WRAP_CONTENT;
int height = LayoutParams.WRAP_CONTENT;
LayoutParams innerParams = new LayoutParams(width, height);
innerParams.weight = 1;
innerParams.gravity = Gravity.CENTER;
innerContainer.addView(child, innerParams);
}
protected void addInnerContainer(LinearLayout innerContainer) {
LayoutParams params = generateDefaultLayoutParams();
params.width = LayoutParams.MATCH_PARENT;
addView(innerContainer, params);
}
protected LinearLayout generateInnerContainer() {
LinearLayout innerContainer;
innerContainer = new LinearLayout(getContext());
innerContainer.setGravity(Gravity.CENTER);
return innerContainer;
}
public void setOnInnerViewClickListener(OnClickListener listener) {
for (View innerView : innerViews) {
innerView.setOnClickListener(listener);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Sets up mListPadding
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.UNSPECIFIED) {
if (columnWidth > 0) {
widthSize = columnWidth + getPaddingLeft() + getPaddingRight();
} else {
widthSize = getPaddingLeft() + getPaddingRight();
}
widthSize += getVerticalScrollbarWidth();
}
int childWidth = widthSize - getPaddingLeft() - getPaddingRight();
int columnsNumber = determineColumns(childWidth);
if (columnsNumber > 0 && columnsNumber != itemsPerRow) {
itemsPerRow = columnsNumber;
removeAllViews();
processViews();
}
}
protected int determineColumns(int availableSpace) {
int columnsNumber = itemsPerRow;
if (0 < columnWidth) {
columnsNumber = availableSpace / columnWidth;
}
return columnsNumber;
}
}
Вот мой файл ресурсов для пользовательских атрибутов:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="column_width" format="dimension|integer">
<enum name="single_column" value="-1" />
</attr>
<declare-styleable name="GridLikeLayout">
<attr name="column_width" />
</declare-styleable>
</resources>
Вот пример использования:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutContainer"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ScrollView
android:id="@+id/itemsScroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="@+id/itemsLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<your_package.view.GridLikeLayout
xmlns:my="YOUR APPLICATION PACKAGE"
android:id="@+id/MyGrid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
my:column_width="260dp"
android:focusable="true"
android:gravity="center_horizontal"
android:padding="5dp" >
</your_package.GridLikeLayout>
<View
android:id="@+id/viewSeparator"
android:layout_width="fill_parent"
android:layout_height="2dp" />
<your_package.GridLikeLayout
xmlns:my="YOUR APPLICATION PACKAGE"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
my:column_width="single_column" >
</your_package.GridLikeLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
Пожалуйста, скажите мне, если у вас есть какие-либо проблемы с примером - я не могу попробовать это в данный момент. Так что, если у вас есть проблемы, я проверю это позже. Не забудьте изменить имена пакетов - «your_package» должен быть пакетом, в котором вы храните GridLikeLayout, а «YOUR APPLICATION PACKAGE» - это пакет вашего приложения - тот, который указан в манифесте приложения. :)