【问题标题】:Auto fit according to screen size in grid layout android根据网格布局android中的屏幕尺寸自动适应
【发布时间】:2021-03-23 01:57:44
【问题描述】:

我创建了一个包含完整文本的网格。我希望文本根据屏幕大小自动调整。我试过下面的代码,

    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
    int noOfColumns = (int) (dpWidth / 50);
    return noOfColumns;

我想输出这样的东西

]2

它不符合我的需要。请帮忙 。提前致谢。

【问题讨论】:

  • 这段代码有什么问题?
  • 我想要 auto-fit 但它没有执行 auto-fit 。 @维亚切斯拉夫
  • 你的意思是你不能计算字体的高度。我说的对吗?
  • 不,我只是想根据屏幕大小来调整网格项目@Vyacheslav
  • 你的意思是宽屏应该有更多的列,还是相同数量的列,只是它们应该拉伸到填满屏幕?

标签: android grid-layout


【解决方案1】:

这是 GridLayout 的自定义实现,可以满足您的需求:AutoGridLayout

public class AutoGridLayout extends GridLayout {

    private int defaultColumnCount;
    private int columnWidth;

    public AutoGridLayout(Context context) {
        super(context);
        init(null, 0);
    }

    public AutoGridLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public AutoGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs, int defStyleAttr) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AutoGridLayout, 0, defStyleAttr);
        try {
            columnWidth = a.getDimensionPixelSize(R.styleable.AutoGridLayout_columnWidth, 0);

            int[] set = { android.R.attr.columnCount /* id 0 */ };
            a = getContext().obtainStyledAttributes(attrs, set, 0, defStyleAttr);
            defaultColumnCount = a.getInt(0, 10);
        } finally {
            a.recycle();
        }

        /* Initially set columnCount to 1, will be changed automatically later. */
        setColumnCount(1);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        super.onMeasure(widthSpec, heightSpec);

        int width = MeasureSpec.getSize(widthSpec);
        if (columnWidth > 0 && width > 0) {
            int totalSpace = width - getPaddingRight() - getPaddingLeft();
            int columnCount = Math.max(1, totalSpace / columnWidth);
            setColumnCount(columnCount);
        } else {
            setColumnCount(defaultColumnCount);
        }
    }
}

只需像这样添加到您的 XML 布局文件中:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.km.myproject.customview.AutoGridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="5"
        app:columnWidth="50dp"/>

</FrameLayout>

使用columnWidth 将尝试计算可以容纳多少列并自动设置最佳跨度计数。如果不使用(或由于某种原因未能测量),将使用columnCount 属性。

希望这会有所帮助!

【讨论】:

  • 这是否适用于使用卡片视图的 Recyclerview?要遵循的步骤?干得好!
  • 我找不到 R.styleable.AutoGridLayout 和 R.styleable.AutoGridLayout_columnWidth
  • 将以下内容添加到 attrs.xml:
【解决方案2】:

这是一个为您完成所有计算的网格布局的实现。它将所有子视图放置在具有相等边距的等距网格中。它还优化了列数,以便不要让所有行都尽可能满(例如,9 个子视图将适合 3 行,如 4、4、1,但 3、3、3 看起来要好得多) 一切都是动态的,所以不用担心风景/肖像/手机/平板电脑/电视


package .......;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/* A labor-saving layout
/  dynamically places all children on an equally-spaced grid.
   All children get the width/height of the largest child - so they all look similar
 */
public class AutoGridLayout extends ViewGroup
{

    private int mMaxHeight;
    private int mMaxWidth;

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

    public AutoGridLayout(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean shouldDelayChildPressedState()
    {
        return false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int count = getChildCount();

        mMaxHeight = 0;
        mMaxWidth = 0;
        int childState = 0;

        for (int i = 0; i < count; i++)
        {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE)
            {
                measureChild(child, widthMeasureSpec,  heightMeasureSpec);

                mMaxWidth = Math.max(mMaxWidth, child.getMeasuredWidth());
                mMaxHeight = Math.max(mMaxHeight, child.getMeasuredHeight());
            }
        }

        mMaxHeight = Math.max(mMaxHeight, getSuggestedMinimumHeight());
        mMaxWidth = Math.max(mMaxWidth, getSuggestedMinimumWidth());

        setMeasuredDimension(resolveSizeAndState(mMaxWidth, widthMeasureSpec, childState),
                             resolveSizeAndState(mMaxHeight, heightMeasureSpec,
                                                 childState << MEASURED_HEIGHT_STATE_SHIFT));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    {
        final float pxWidth = (right - left + 1);
        final float pxHeight  = (1 + bottom - top);
        final int totalChildCount = getChildCount();
        int count = 0;
        for (int i = 0; i < totalChildCount; i++)
        {
            if (getChildAt(i).getVisibility() != GONE)
                count++;
        }

        final float minSpacing = pxWidth / 20;
        final int maxPossibleColumns = (int) (pxWidth / (mMaxWidth + minSpacing));
        final int rows = (int)Math.ceil((float)count / maxPossibleColumns);
        final int voidsAtLastRow = (rows * maxPossibleColumns - count);
        // distribute the voids to get an even distribution is possible
        final int nColumns = maxPossibleColumns - voidsAtLastRow / rows;

        // equal spaces as margins and between childs (#spaces = #child + 1)
        final int xSpace = (int)Math.max(0,(pxWidth - nColumns * mMaxWidth) / (nColumns + 1));
        final int ySpace = (int)Math.max(0,(pxHeight - rows * mMaxHeight) / (rows + 1));

        int n = 0;
        for (int i = 0; i < totalChildCount; i++)
        {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE)
            {
                final int col = n % nColumns;
                final int x = xSpace + (xSpace + mMaxWidth) * col;

                final int row = n / nColumns;
                final int y = ySpace + (ySpace + mMaxHeight) * row;

                // Place the child.
                child.layout(x, y,x+mMaxWidth,y+mMaxHeight);
                n++;
            }
        }
    }

}

【讨论】:

    【解决方案3】:

    使用FlexboxLayoutRecyclerView 来处理这种类型的layout

    RecyclerView recyclerView = (RecyclerView) context.findViewById(R.id.recyclerview);
    FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
    layoutManager.setFlexDirection(FlexDirection.COLUMN);
    layoutManager.setJustifyContent(JustifyContent.FLEX_START);
    recyclerView.setLayoutManager(layoutManager);
    

    更多请查看FlexboxLayout

    FlexboxLayout 也可以处理不同宽度高度的视图,就像Gallery 中的图像一样

    【讨论】:

      【解决方案4】:

      执行以下操作;

      • 使用您的代码计算 onCreate 或 onCreateView 中的列数。请记住列之间的间距。

      • 在具有上述计数的 GridLayout 上调用 setColumnCount

      • 在您的 xml 中,将属性 android:layout_columnWeight="1" 添加到 GridLayout 中的所有项目。这将导致列在 API 21 及更高版本中拉伸。

      • 在 API 21 之前,您可以将 GridView 本身水平居中,使其看起来不错。或者更好的是,计算首选 columnWidth (gridWidth / columnCount),并遍历网格 (ViewGroup) 中的所有项目,并将它们的宽度设置为 columnWidth。

      【讨论】:

        【解决方案5】:

        很难让GridLayout 做你需要的事情:

        • 即使您可以从DisplayMetrics 读取屏幕宽度,该方法仍与支持分屏的新版本 Android 不兼容。您需要父视图的宽度,而不是整个屏幕。

        • 即使假设显示指标为显示活动的窗口提供了可靠的宽度,但只要将布局放在另一个片段旁边的片段中,此逻辑就会中断。创建如此不灵活的东西是没有意义的。

        • 在布局完成之前,父视图的宽度是未知的。这并不意味着它无法使用,只是很棘手。

        简单的做法是使用GridView,因为它具有autofit 列数选项,因此设计得更好。

        【讨论】:

        • 其实getMetrics好像返回了分割窗口的虚拟大小,所以会很好用。您将使用getRealMetrics 来获取全屏大小。
        • 谢谢你,我会相信你的话。我仍然会担心 RemixOS、三星和其他硬件公司在皮肤中使用的各种方案,以及通常在我没有测试过的某些设备上可能发生的情况。
        • 其实我自己从来没有测试过,我只是引用我在stackoverflow.com/questions/36706365/…读到的内容
        • 实际上我想要在网格内进行拖放功能。我尝试使用网格视图的自动调整功能,但出现错误。请在这里查看我的问题stackoverflow.com/questions/39434558/… 所以我尝试使用网格布局@lionscribe
        • 我尝试了网格视图,但遇到了一些其他错误。请在这里查看我的错误stackoverflow.com/questions/39434558/…@x-code
        【解决方案6】:

        您可以为此使用dimens.xml 文件。 然后在GridLayout中更新android:columnCount="@dimen/columnCount"

        https://suragch.medium.com/using-dimens-xml-in-android-10dec2fe485c

        【讨论】:

          【解决方案7】:

          对于网格布局

           <?xml version="1.0" encoding="utf-8"?>
          <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:columnCount="4"
              android:orientation="horizontal" >
              <Button android:text="1" />
              <Button android:text="2" />
              <Button android:text="3" />
              <Button android:text="4" />
              <Button android:text="5" />
              <Button android:text="6" />
              <Button android:text="7" />
              <Button android:text="8" />
              <Button android:text="9" />
              <Button android:text="10" />
              <Button android:text="11" />
              <Button android:text="12" />
              <Button android:text="13" />
              <Button android:text="14" />
              <Button android:text="15" />
              <Button android:text="16" />
          </GridLayout>
          

          以编程方式:

          GridLayout gridLayout = new GridLayout(this);
          gridLayout .setColumnCount(4);
          ///...
          

          一个例子:https://stackoverflow.com/a/14715333/1979882

          调整gridview使用这个方法:

          private void adjustGridView() {
            gv.setNumColumns(GridView.AUTO_FIT);
            gv.setColumnWidth(70);
          }
          

          【讨论】:

          • 我们可以在网格布局中实现相同的功能吗?因为我在网格布局中找不到 auto_fit 函数@Vyacheslav
          • 我希望列是 auto_fit 而不是硬编码值@Vyacheslav
          • 更新了代码方式。请更准确地描述问题。带代码。 @Anusha
          • 我不想像你指定的那样指定 columCount 但我想成为 auto_fit 。如何在gridlayout中设置为Auto_fit? @维亚切斯拉夫
          • 怎么样?它们在网格视图中自动调整。但是网格布局呢?并参考了所有这些链接,但没有任何帮助@Vyacheslav
          猜你喜欢
          • 2012-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-02
          • 2020-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多