ScrollView中的图像网格

我正在试图创build一个文本和图像的屏幕。 我想要像网格布局图像,如下所示,但我希望他们没有滚动function,除了由周围的ScrollView提供的。

一张图片最能说明我的问题:

替代文字

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

什么是最好的方式来显示不同数量的图像网格,其中网格没有滚动function?

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

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

替代文字

哦,男孩,是的,你会遇到这个问题。 这让我非常担心ListViews和GridViews不能扩展来包装他们的孩子,因为我们都知道,除了滚动和回收他们的孩子之外,他们还有更多有益的function。

尽pipe如此,你可以绕过这个或创build自己的布局,以适应您的需求,没有太多的困难。 关于我的头顶,我可以想到两种可能性:

在我自己的应用程序中,我在ScrollView中embedded了一个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方法(通过浏览源代码发现这个方法)内为你创build和测量所有的子项。 希望GridView的行为是相同的,但是如果不行的话,你仍然可以自己测量GridView的所有内容。 但是如果你能欺骗GridView为你做这件事情会更容易。

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

另一种可能是抛弃GridView并创build自己的布局。 您可以扩展AbsoluteLayoutRelativeLayout 。 例如,如果您扩展RelativeLayout ,则可以将每个图像LEFT_OF前一个图像的LEFT_OF ,跟踪每个图像的宽度,直到您在该行的空间不足,然后通过放置新图像的第一个图像开始下一行在最后一行的最高图像之下。 为了获得图像水平居中或等距列,你将不得不经历更多的痛苦。 也许AbsoluteLayout更好。 无论哪种方式,都是一种痛苦。

祝你好运。

带有页眉和页脚的GridView可以用来代替试图在GridView中embeddedGridView。 页眉和页脚可以是任何东西 – 文本,图像,列表等。有一个与页眉和页脚的GridView的例子: https : //github.com/SergeyBurish/HFGridView

你有2个解决scheme:

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

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

   RelativeLayout.LayoutParams lp =(RelativeLayout.LayoutParams)myGridView.getLayoutParams();
   // lp.setMargins(0,0,10,10);  //如果你有布局边距,你也必须设置它们
   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以上。

我发现了一种在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 <>

 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"})); 

我希望它有助于=)

像这样创build一个不可滚动的列表视图:

 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(); } } 

在您的布局文件中创build一个像这样的元素:

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

这应该工作。

尝试这个

  public static void setGridViewHeightBasedOnChildren(GridView gridView, int columns) { ListAdapter listAdapter = gridView.getAdapter(); if (listAdapter == null) return; int desiredWidth = View.MeasureSpec.makeMeasureSpec(gridView.getWidth(), View.MeasureSpec.UNSPECIFIED); int totalHeight = 0; View view = null; int rows = listAdapter.getCount() / columns; if(listAdapter.getCount() % columns> 0){ rows++; } for (int i = 0; i < rows; i++) { view = listAdapter.getView(i, view, gridView); if (i == 0) view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LinearLayout.LayoutParams.WRAP_CONTENT)); view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); totalHeight += view.getMeasuredHeight(); } ViewGroup.LayoutParams params = gridView.getLayoutParams(); params.height = totalHeight + (gridView.getHorizontalSpacing() * rows); gridView.setLayoutParams(params); gridView.requestLayout(); } 

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

更新:

从链接中我定制了一个ExpandedGridView:

 package org.undp.kh.sustainabledevelopmentgoals.model; import android.content.Context; import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.GridView; /** * Created by sarithnob on 8/28/17. */ 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; } }