如何将多个GridView的添加到Android的Java中的滚动视图?多个、视图、如何将、GridView

2023-09-05 00:47:21 作者:少許懷念

我想多GridView的在运行时添加到滚动型线性布局。 但是,只有第一行显示。 请帮助

I'm trying to add multiple gridviews to a scrollview in linear layout at runtime. But only first row displays. Pls help

推荐答案

您不能在Android的窝滚动视图 - 即ListView控件,GridView控件,滚动型

You can't nest scrollable Views in Android - i.e. ListView, GridView, ScrollView.

您可以给看看下面code:

You could give a look at the following code:

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控件的好一点的版本,允许嵌套在滚动型时,它几乎工作。我说:几乎工作,因为我发现它有时是20-30像素太短或太长。 你应该注意到,这将prevent被重用的意见,所以它比普通的GridView的方式较重。

It is a little better version of GridView allowing it to almost work when nested in ScrollView. I said "almost work" since I found it sometimes being 20-30 pixels too short or too long. You should note that this would prevent the views from being reuse, so it is way heavier than normal GridView.

在我的情况,我结束了扩展的LinearLayout,并用它来调整其子女在列。这是不是真的很难 - 我可以给你的例子,如果你想要的。 :)

In my case I ended up extending LinearLayout and using it to align its children in columns. It wasn't really hard - I can give you examples if you want. :)

我从的GridView的例子这个答案。

下面是基于的LinearLayout一个GridView的例子:

Here is an example for a GridView based on 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;
    }

}

下面是我的自定义资源文件属性:

Here is my resource file for the custom attributes:

<?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和您的应用程序包是您的应用程序包的包 - 在应用程序清单中指定的。 :)

Please tell me if you have any troubles running the example - I'm not able to try it at the moment. So if you have issues, I'll check it up later. Don't forget to change the package names - "your_package" should be the the package where you store the GridLikeLayout and "YOUR APPLICATION PACKAGE" is your app's package - the one specified in the application manifest. :)