【问题标题】:How to force GridView to generate square cells in Android如何强制GridView在Android中生成方形单元格
【发布时间】:2014-08-16 11:58:48
【问题描述】:

如何强制 android GridView 生成方形单元格(单元格的高度等于单元格的宽度) GridView 有 10*9 个单元格,应用必须支持多屏!

我使用了线性布局:

row_grid.xml

<LinearLayout 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:padding="0dp" >

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:src="@drawable/ic_launcher" >
        </ImageView>

    </LinearLayout>

和 GridView: activity_main.xml

<RelativeLayout 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:background="@drawable/katy" >

    <GridView
        android:id="@+id/gridView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:horizontalSpacing="0dp"
        android:numColumns="4"
        android:stretchMode="columnWidth"
        android:verticalSpacing="0dp" >
    </GridView>
</RelativeLayout>

GridView 的每个单元格都包含一个具有相同宽度和高度的图像。 图像比单元格大,必须拉伸以适应单元格。

【问题讨论】:

    标签: android gridview layout


    【解决方案1】:

    首先,您需要创建一个可以使用的自定义 View 类,而不是您正在使用的默认 LinearLayout。然后你想覆盖 View 的 onMeasure 调用,并强制它是方形的:

    public class GridViewItem extends ImageView {
    
        public GridViewItem(Context context) {
            super(context);
        }
    
        public GridViewItem(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public GridViewItem(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
        }
    }
    

    然后您可以将 row_grid.xml 文件更改为:

    <path.to.item.GridViewItem xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/item_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher" >
    </path.to.item.GridViewItem>
    

    请务必将“path.to.item”更改为 GridViewItem.java 类所在的包。

    我还删除了您的 LinearLayout 父级,因为它在那里没有为您做任何事情。

    编辑:

    还将 scaleType 从 fitXY 更改为 centerCrop,这样您的图像就不会自行拉伸并保持其纵横比。而且,只要是方形图像,无论如何都不应裁剪。

    【讨论】:

    • 。谢谢。但是发生了运行时错误! 'android.view.InflateException: Binary XML file line #1: Error inflating class com.example.test.GridViewItem' 包下载链接:s000.tinyupload.com/index.php?file_id=90216865398945988480
    • @Jessica 您的 GridViewItem.java 类不在您在 XML 中指定的包中,这就是它无法膨胀的原因。你应该把它移到合适的包里,它应该适合你
    • 虽然如果您的网格项目只有一个图像视图,答案就完美无缺。如果您希望网格项目成为 ViewGroup 而不是 ImageView,请检查此答案 (stackoverflow.com/a/57232928/3021082)。
    【解决方案2】:

    你可以覆盖你的线性布局

    public class MyLinearLayout extends LinearLayout {
        public MyLinearLayout(Context context) {
            super(context);
        }
    
        public MyLinearLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
        }
    }
    

    然后在 item_grid.xml 中使用它

    <?xml version="1.0" encoding="utf-8"?>
    <com.example.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/item_grid"
    
        android:layout_margin="2dp"
        android:padding="3dp"
        android:gravity="center">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Category Name"
            android:textStyle="bold"
            android:textColor="@color/colorPrimary"
            android:id="@+id/tvCategoryName" />
    
    
    </com.example.MyLinearLayout>
    

    【讨论】:

      【解决方案3】:

      使用 ConstraintLayout 怎么样?

      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:gravity="center"
          android:padding="3dp">
      
          <ImageView
              android:id="@+id/imageView"
              android:layout_width="0dp"
              android:layout_height="0dp"
              android:scaleType="centerCrop"
              app:layout_constraintDimensionRatio="1:1"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent" />
      
      </androidx.constraintlayout.widget.ConstraintLayout>
      

      【讨论】:

        【解决方案4】:

        很好用,谢谢!我需要的一个小改进总是选择较小的值,以防止屏幕过冲:

        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if(heightMeasureSpec < widthMeasureSpec) {
                super.onMeasure(heightMeasureSpec, heightMeasureSpec);
            } else if(widthMeasureSpec < heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, widthMeasureSpec);
            } else {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        
        }
        

        【讨论】:

          【解决方案5】:
          import android.content.Context;
          import android.util.AttributeSet;
          import android.widget.RelativeLayout;
          
          public class GridViewItem extends RelativeLayout {
          
              public GridViewItem(Context context) {
                  super(context);
              }
          
              public GridViewItem(Context context, AttributeSet attrs) {
                  super(context, attrs);
              }
          
              public GridViewItem(Context context, AttributeSet attrs, int defStyle) {
                  super(context, attrs, defStyle);
              }
          
              @Override
              public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                  super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
              }
          }
          

          如果您的网格项目只有一张图片,那么answer 非常好。但是你想在你的网格项目中添加多个项目,那么你必须创建你的自定义GridViewItem 扩展你想要你的网格项目的布局。例如,在我的例子中,我有 RelativeLayout 作为父视图,所以我创建了 GridViewItem 扩展了 RelativeLayout,它完美地工作。

          【讨论】:

          • 这与@Cruceo 的回答有何不同?
          • @AmirDora。我的 GridViewItem 类扩展了 RelativeLayout,而 Cruceo 扩展了图像视图。正如我所写,如果您的网格项目有多个项目
          【解决方案6】:

          只要确保您的图片是方形的即可。并制作容器 wrap_content。

          【讨论】:

          • “对不起,客户先生,但您的图像需要是方形的。继续下载用于照片编辑的软件或应用程序,这样您就可以将 5000 张图像编辑成方形。”
          猜你喜欢
          • 2016-12-28
          • 2018-03-19
          • 2021-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多