【问题标题】:Making GridView items square使 GridView 项目成为正方形
【发布时间】:2011-09-27 07:15:39
【问题描述】:

我希望我的GridView 的项目是方形的。有 2 列,项目宽度为 fill_parent(例如,它们占用尽可能多的水平空间。项目是自定义视图。

如何使项目的高度等于它们的可变宽度?

【问题讨论】:

    标签: android gridview


    【解决方案1】:

    当 GridView 列被拉伸时,有一个更简单的解决方案。只需使用...覆盖 GridView 项目布局的 onMeasure...

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

    【讨论】:

    • 效果很好。我在答案中错过了几件事:1.高度被忽略,宽度作为高度传递。 2.该方法应该在item和Grid本身中被覆盖。
    • 大约 1:这就是它的方格 --"
    • @KarthikPalanivelu 这将用于网格项目的布局,而不是 GridView 本身。您也许可以使用这个 sn-p 将 RelativeLayout 扩展到 SquareRelativeLayout。
    • 如果我在我的 gridview 中这样做,我会创建 GridView 正方形,而不是它的子项。
    • 一个完整的答案会很好。你是说扩展gridview?
    【解决方案2】:

    或者,如果您想扩展视图,只需执行一些非常简单的操作,例如:

    public class SquareImageView extends ImageView
    {
    
        public SquareImageView(final Context context)
        {
            super(context);
        }
    
        public SquareImageView(final Context context, final AttributeSet attrs)
        {
            super(context, attrs);
        }
    
        public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle)
        {
            super(context, attrs, defStyle);
        }
    
    
        @Override
        protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
        {
            final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
            setMeasuredDimension(width, width);
        }
    
        @Override
        protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh)
        {
            super.onSizeChanged(w, w, oldw, oldh);
        }
    }
    

    值得注意的是,super.onMeasure() 不是必需的。 onMeasured 要求是你必须调用setMeasuredDimension

    【讨论】:

    • 像魅力一样工作.. 谢谢克里斯 :)
    • @Chris.Jenkins 我不同意您的最后评论:如果我不调用 super.onMeasure() ,则不会绘制放置在其中的 ImageView。所以它似乎是onMeasure 方法的第一行所必需的。
    • @nerith,这是在特定设备上吗,因为我已经使用此代码很长时间了,并且从未遇到问题。有兴趣了解如何重现您所看到的内容。
    • @Chris.Jenkins 不在特定设备上。我的 SquareFrameLayout 是从 xml 加载的。您是否以编程方式添加您的孩子?
    • 哦,是的,这不适用于仅视图组的视图。也许我应该提一下。
    【解决方案3】:

    我不确定当前的小部件是否可行。您最好的选择可能是将您的自定义视图放在自定义的“SquareView”中。此视图可能只包含 1 个子视图,并在调用其 onLayout 方法时强制高度等于宽度。

    我从未尝试过这样做,但我认为这应该不会太难。另一种(可能更简单)的解决方案可能是将自定义视图的根布局子类化(例如,如果它是 LinearLayout,则创建 SquareLinearLayout),并将其用作容器。

    编辑:这是一个似乎对我有用的基本实现:

    package com.mantano.widget;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    
    public class SquareView extends ViewGroup {
    
        public SquareView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int u, int r, int d) {
            getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
            View child = getChildAt(0);
            child.measure(widthMeasureSpec, widthMeasureSpec);
            int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec);
            child.measure(width, width); // 2nd pass with the correct size
            setMeasuredDimension(width, width);
        }
    }
    

    它的设计目的是拥有一个独特的孩子,但为了简单起见,我忽略了所有检查。基本思想是用 GridView 设置的宽度/高度参数来测量孩子(在我的例子中,它使用 numColumns=4 来计算宽度),然后使用最终尺寸进行第二次传递,高度 = 宽度。 .. 布局只是一个简单的布局,它在 (0, 0) 处以所需的尺寸(从右到左,从下到上)布局唯一的孩子。

    这里是用于 GridView 项目的 XML:

    <?xml version="1.0" encoding="utf-8"?>
    <com.mantano.widget.SquareView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent" android:layout_height="wrap_content">
    
        <LinearLayout android:id="@+id/item" android:layout_width="fill_parent"
            android:layout_height="fill_parent" android:orientation="horizontal"
            android:gravity="center">
    
            <TextView android:id="@+id/text" android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:text="Hello world" />
        </LinearLayout>
    </com.mantano.widget.SquareView>
    

    我在 SquareView 中使用了 LinearLayout,以便让它管理所有的重力可能性、边距等。

    我不确定这个小部件对方向和尺寸变化的反应有多好(或差),但它似乎可以正常工作。

    【讨论】:

    • 这一切听起来都不错,唯一的问题是正确地写 onLayout(或 onMeasure)。目前我在 ItemAdapter.getView() 中设置了高度/宽度,但我不喜欢这个解决方案。
    • @anagaf 我用我刚刚测试过的代码编辑了我的答案,这似乎有效。这很容易理解,所以应该很容易修复,以防万一你发现一些小故障^^(不确定我是否应该编辑或发布第二个答案,如果我做错了对不起!)
    • 上面的布局不起作用---我不知道为什么,但是孩子们有一些微妙的布局问题,这意味着,例如,TextViews 不会换行,RelativeLayouts 会变得非常混乱.但是,我确实在这里找到了等价物:stackoverflow.com/questions/2948212/… ...尽管我仍然需要对其进行一些调整(它的大小基于最大尺寸而不仅仅是宽度)。
    【解决方案4】:

    最终获得网格项目正方形相当容易。

    在您的网格适配器的“GetView”方法中,只需执行以下操作:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        GridView grid = (GridView)parent;
        int size = grid.getRequestedColumnWidth();
    
        TextView text = new TextView(getContext());
        text.setLayoutParams(new GridView.LayoutParams(size, size));
    
        // Whatever else you need to set on your view
    
        return text;
    }
    

    【讨论】:

    • 这是唯一对我有用的解决方案...非常感谢!!
    • 不得不用“getColumnWidth”替换“getRequestedColumnWidth”,它对我有用..谢谢!
    • 这里也一样:我不得不用 getColumnWidth 替换 getRequestedColumnWidth 并为我工作......谢谢!
    【解决方案5】:

    我不知道这是否是最好的方法,但我做到了,让我的自定义视图以这种方式覆盖 onSizeChanged:

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    
        if (getLayoutParams() != null && w != h) {
            getLayoutParams().height = w;
            setLayoutParams(getLayoutParams());
        }
    }
    

    我在 LinearLayout 和 GridView 中使用此自定义视图,并且在两者中都显示为正方形!

    【讨论】:

    • 哦,伙计,你是救生员,我已经为此奋斗了好几天。除非您有很多孩子,否则 Gregory 的回答效果很好;然后,正如评论指出的那样,TextViews 不会换行,并且大多数视图不会重新调整它们的边界。但这解决了它!
    【解决方案6】:

    这对我有用!

    如果你和我一样不能使用 getRequestedColumnWidth() 因为你的 minSdk 低于 16,我建议这个选项。

    1. 在您的片段中:

      DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); int size = dm.widthPixels / nbColumns; CustomAdapter adapter = new CustomAdapter(list, size, getActivity());

    2. 在您的适配器中(在 getView(int position, View convertView, ViewGroup parent))

      v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));

    3. 片段.xml:

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

    4. custom_item.xml:(例如)

      <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" />

    希望对某人有所帮助!

    【讨论】:

      【解决方案7】:

      如果您在 xml 中设置静态列数,那么您可以获取视图的宽度并将其除以列数。

      如果您使用的是auto_fit,那么获取列数会有点棘手(没有 getColumnCount() 方法),顺便说一句,this 问题应该对您有所帮助。

      这是我在具有固定列数的适配器的getView(...) 方法中使用的代码:

          item_side = mFragment.holder.grid.getWidth() / N_COL;
          v.getLayoutParams().height = item_side;
          v.getLayoutParams().width = item_side;
      

      【讨论】:

        【解决方案8】:

        试试

        <GridView
        ...
        android:stretchMode="columnWidth" />
        

        你也可以玩其他模式

        【讨论】:

          【解决方案9】:

          这就是我在 GridView 中显示方形单元格的方法。我不确定你是否想要方形单元格或其他东西。

          GridView grid = new GridView( this );
          grid.setColumnWidth( UIScheme.cellSize );
          grid.setVerticalSpacing( UIScheme.gap );
          grid.setStretchMode( GridView.STRETCH_COLUMN_WIDTH );
          grid.setNumColumns( GridView.AUTO_FIT );
          

          然后我为每个单元格创建的视图我必须对其执行以下操作:

          cell.setLayoutParams( new GridView.LayoutParams(iconSize, iconSize) );
          

          【讨论】:

            【解决方案10】:

            基于SteveBorkman's answer,即 API 16+:

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
            
                GridView grid = (GridView)parent;
                int size = grid.getColumnWidth();
            
                if (convertView == null){
                    convertView = LayoutInflater.from(context).inflate(R.layout.your_item, null);
                    convertView.setLayoutParams(new GridView.LayoutParams(size, size));
                }
            
                 //Modify your convertView here
            
                 return convertView;
            }
            

            【讨论】:

              【解决方案11】:

              按照@Gregory 的回答,我不得不将我的图像包装在一个LinearLayout 中,以防止GridView 从正方形操纵它的尺寸。注意外部的LinearLayout应该设置成图片的尺寸,GridView列的宽度应该是图片的宽度加上任何边距。例如:

                  <!-- LinearLayout wrapper necessary to wrap image button in order to keep square;
                  otherwise, the grid view distorts it into rectangle.
              
                  also, margin top and right allows the indicator overlay to extend top and right.
              
                  NB: grid width is set in filter_icon_page.xml, and must correspond to size + margin
                  -->
              <LinearLayout
                      android:id="@+id/sport_icon_lay"
                      android:layout_width="60dp"
                      android:layout_height="60dp"
                      android:orientation="vertical"
              
                      android:layout_marginRight="6dp"
                      android:layout_marginTop="6dp"
                      >
              
                  <ImageButton
                          android:id="@+id/sport_icon"
                          android:layout_width="60dp"
                          android:layout_height="60dp"
                          android:maxHeight="60dp"
                          android:maxWidth="60dp"
                          android:scaleType="fitCenter"
                          />
              </LinearLayout>
              

              和 GridView 类似:

                 <GridView
                      android:id="@+id/grid"
                      android:layout_width="fill_parent"
                      android:layout_height="fill_parent"
                      android:fillViewport="true"
              
                      android:columnWidth="66dp"
              
                      android:numColumns="auto_fit"
                      android:verticalSpacing="25dp"
                      android:horizontalSpacing="24dp"
                      android:stretchMode="spacingWidth"
              
                      />
              

              【讨论】:

                【解决方案12】:

                在你的活动中

                 DisplayMetrics displaymetrics = new DisplayMetrics();
                 getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
                 valX = displaymetrics.widthPixels/columns_number;
                

                在GridView的CustomAdapter中

                 v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, YourActivity.valX));
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-05-16
                  • 2015-05-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多