ScrollView中的图像网格

时间:2010-12-24 01:03:55

标签: android user-interface gridview imageview scrollview

我正在尝试创建一个包含文字和图片的屏幕。我希望图像像网格一样布局,如下所示,但我希望它们没有周围ScrollView提供的滚动功能。

图片最能说明我的问题:

alt text

<ScrollView>
    <LinearLayout>
        <ImageView />
        <TextView />
        <GridView />
        <TextView />
    </LinearLayout>
</ScrollView>

显示不同数量图像的网格的最佳方法是什么,网格没有滚动功能?

请注意,禁用GridView的滚动功能不起作用,因为这只会禁用滚动条但不会显示所有项目。

更新: 下图显示了在GridView中禁用滚动条的情况。

alt text

7 个答案:

答案 0 :(得分:186)

哦,男孩,是的,你会遇到这个问题。它让我感到疯狂的是ListViews和GridViews无法扩展以包装他们的孩子,因为我们都知道他们除了滚动和回收他们的孩子之外还有更多有益的功能。

尽管如此,你可以解决这个问题,或者创建自己的布局以满足您的需求,而不会有太多困难。我能想到两个可能性:

在我自己的应用程序中,我在ScrollView中嵌入了ListView。我通过明确告诉ListView与其内容完全一样高来完成此操作。我是通过在ListView.onMeasure()方法中更改布局参数来实现的,如下所示:

public class ExpandableListView extends ListView {

    boolean expanded = false;

    public ExpandableListView(Context context, AttributeSet attrs, int defaultStyle) {
        super(context, attrs, defaultStyle);
    }

    public boolean isExpanded() {
        return expanded;
    }

    public void setExpanded(boolean expanded) {
        this.expanded = 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.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                        MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

            LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

这是有效的,因为当您为ListView提供AT_MOST模式时,它会在onMeasure方法内部为您创建并测量其所有子项(我通过浏览源代码发现了这一点) )。希望GridView的行为相同,但如果没有,您仍然可以自己测量GridView的所有内容。但如果你能欺骗GridView为你做这件事会更容易。

现在,您必须记住,此解决方案将完全禁用视图回收,使GridView如此高效,并且即使它们不可见,所有这些ImageView也将在内存中。我的下一个解决方案也是如此。

另一种可能性是抛弃GridView并创建自己的布局。您可以延长AbsoluteLayoutRelativeLayout。例如,如果您展开RelativeLayout,则可以将每个图像LEFT_OF放在前一个图像上,跟踪每个图像的宽度,直到该行用完房间,然后开始下一行通过将新行BELOW的第一张图像放在最后一行的最高图像上。要使图像水平居中或在等间距列中,您将不得不经历更多的痛苦。也许AbsoluteLayout更好。无论哪种方式,都是一种痛苦。

祝你好运。

答案 1 :(得分:4)

可以使用带有页眉和页脚的GridView,而不是尝试在ScrollView中嵌入GridView。页眉和页脚可以是任何内容 - 文本,图像,列表等。有一个带页眉和页脚的GridView示例:https://github.com/SergeyBurish/HFGridView

答案 2 :(得分:3)

你有两个解决方案:

  1. 编写自己的自定义布局。这将是更难的解决方案(但可能被认为是正确的解决方案)。

  2. 在代码中设置GridView的实际高度。例如:

  3.   RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) myGridView.getLayoutParams();
      // lp.setMargins(0, 0, 10, 10); // if you have layout margins, you have to set them too
      lp.height = measureRealHeight(...);
      myGridView.setLayoutParams(lp);
    

    measureRealHeight()方法看起来应该是这样的(希望我做对了):

    private int measureRealHeight(...)
    {
      final int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
      final double screenDensity = getResources().getDisplayMetrics().density;
      final int paddingLeft = (int) (X * screenDensity + 0.5f); // where X is your desired padding
      final int paddingRight = ...;
      final int horizontalSpacing = (int) (X * screenDensity + 0.5f); // the spacing between your columns
      final int verticalSpacing = ...; // the spacing between your rows
      final int columnWidth = (int) (X * screenDensity + 0.5f);             
      final int columnsCount = (screenWidth - paddingLeft - paddingRight + horizontalSpacing - myGridView.getVerticalScrollbarWidth()) / (columnWidth + horizontalSpacing);
      final int rowsCount = picsCount / columnsCount + (picsCount % columnsCount == 0 ? 0 : 1);
    
      return columnWidth * rowsCount + verticalSpacing * (rowsCount - 1);
    }
    

    以上代码应该适用于Android 1.5 +。

答案 3 :(得分:2)

创建一个不可滚动的列表视图,如下所示:

public class ExpandableListView extends ListView{

public ExpandableListView(Context context) {
    super(context);
}

public ExpandableListView(Context context, AttributeSet attrs, int defaultStyle) {
    super(context, attrs, defaultStyle);
}

public ExpandableListView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
            Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
    ViewGroup.LayoutParams params = getLayoutParams();
    params.height = getMeasuredHeight();
  }
}

在你的布局文件中创建一个这样的元素:

<com.example.ExpandableListView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"/>

这应该有用。

答案 4 :(得分:1)

我找到了一种在ScrollView中为GridView提供固定大小的方法,并可以滚动它。

为此,您必须实现一个扩展GridView的新类,并重写onTouchEvent()以调用requestDisallowInterceptTouchEvent(true)。 因此,父视图将使网格拦截触摸事件。

GridViewScrollable.java:

package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.GridView;

public class GridViewScrollable extends GridView {

    public GridViewAdjuntos(Context context) {
        super(context);
    }

    public GridViewAdjuntos(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public GridViewAdjuntos(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev){
        // Called when a child does not want this parent and its ancestors to intercept touch events.
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(ev);
    }
}

使用您想要的特征在布局中添加它:

<ScrollView 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:isScrollContainer="true" >

    <com.example.GridViewScrollable
    android:id="@+id/myGVS"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:numColumns="auto_fit"
    android:columnWidth="100dp"
    android:stretchMode="columnWidth" />

</ScrollView>

只需在您的活动中获取并设置适配器,例如 ArrayAdapter&lt;&gt;

GridViewScrollable mGridView = (GridViewScrollable) findViewById(R.id.myGVS);
mGridView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{"one", "two", "three", "four", "five"}));

我希望它有帮助=)

答案 5 :(得分:0)

试试这个

public interface UserRepository extends CrudRepository<User,Integer>

答案 6 :(得分:0)

对于GridView与保存ScrollView内的其他View以使其全部滚动,请转到此链接:http://www.londatiga.net/it/programming/android/make-android-listview-gridview-expandable-inside-scrollview/#comment-3967742。这是有帮助的,并节省了我的时间,我只花了5分钟,当我从来不知道它。

更新

从链接我自定义ExpandedGridView:

public class ExpandedGridView extends GridView {
    boolean expanded = false;

    public ExpandedGridView(Context context) {
        super(context);
    }

    public ExpandedGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ExpandedGridView(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;
    }
}

将您的xml从GridView更改为已定制的ExpandedGridView。

<com.your.package.ExpandedGridView
    android:id="@+id/home_screen_list_goals"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:numColumns="2" />

用法:

在您的活动中调用它。如果在片段中使用contentView.findViewById(...)。哪个contentView是您定义的整个布局。

ExpandedGridView gridView = (ExpandedGridView) findViewById(R.id.home_screen_list_goals);
//set data into grid view
gridView.setAdapter(YOUR_ADAPTER_OBJECT);
gridView.setExpanded(true);