GridView 항목을 정사각형으로 만들기


78

내 아이템을 GridView사각형으로 만들고 싶습니다 . 2 개의 열이 있으며 항목 너비는 fill_parent(예 : 가능한 한 많은 가로 공간을 차지합니다. 항목은 사용자 정의보기입니다.

항목 높이를 가변 너비와 동일하게 만드는 방법은 무엇입니까?

답변:


106

GridView 열을 늘릴 때 더 간단한 솔루션이 있습니다. GridView 항목 레이아웃의 onMeasure를 다음으로 재정의하십시오.

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

잘 작동합니다. 대답에서 놓친 몇 가지 사항 : 1. 높이는 무시되고 너비는 높이로 전달됩니다. 2. 메서드는 항목과 그리드 자체에서 재정의되어야합니다.
AlikElzin-kilaka

12
1 소개 : 그 광장을 만드는거야 - "
mDroidd

2
@KarthikPalanivelu 이것은 GridView 자체가 아니라 그리드 항목의 레이아웃에 사용됩니다. 이 스 니펫을 사용하여 RelativeLayout을 SquareRelativeLayout으로 확장 할 수 있습니다.
jdamcd

1
내 gridview에서 그렇게하면 자식이 아닌 GridView 사각형을 만듭니다.
Daniel Bo

4
완전한 대답이 좋을 것입니다. gridview를 확장하라는 건가요?
StarWind0

56

또는 뷰를 확장하려면 다음과 같이 아주 간단한 작업을 수행하십시오.

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입니다.


2
매력처럼 작동합니다 .. 감사합니다 크리스 :
KARTHIK Andhamil

2
@ Chris.Jenkins 마지막 의견에 동의하지 않습니다.을 호출하지 않으면 super.onMeasure()내부에 배치 된 ImageView가 그려지지 않습니다. 따라서 onMeasure방법의 첫 번째 줄로 필요한 것 같습니다 .
cyrilchampier 2015-08-05

@nerith, 나는이 코드를 아주 오랫동안 사용해 왔으며 결코 문제를 일으키지 않았기 때문에 특정 장치에서 발생합니다. 보고있는 것을 재현하는 방법에 관심이 있습니다.
Chris.Jenkins

@ Chris.Jenkins는 특정 장치에 없습니다. 내 SquareFrameLayout은 xml에서로드됩니다. 프로그래밍 방식으로 자녀를 추가합니까?
cyrilchampier 2015-08-07

오 예 이것은 뷰 그룹 전용 뷰에서는 작동하지 않습니다. 제가 언급해야 할 것 같습니다.
Chris.Jenkins 2015-08-07

16

현재 위젯에서 이것이 가능한지 잘 모르겠습니다. 가장 좋은 방법은 사용자 정의보기를 사용자 정의 "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)을 올바르게 작성하는 것입니다. Currenlty ItemAdapter.getView ()에서 높이 / 너비를 설정했지만이 솔루션이 마음에 들지 않습니다.
anagaf 2011

@anagaf 방금 테스트 한 코드로 내 대답을 편집했는데 작동하는 것 같습니다. 이해하기 쉽기 때문에 문제가있을 경우를 대비하여 쉽게 고칠 수있을 것입니다 ^^ (수정하거나 두 번째 답변을 게시해야하는지 확실하지 않습니다. 잘못하면 죄송합니다!)
Gregory

1
위의 레이아웃이 작동하지 않습니다. --- 이유는 모르겠지만 자식들에게 미묘한 레이아웃 문제가 있습니다. 예를 들어 TextViews가 래핑되지 않고 RelativeLayouts가 끔찍하게 혼란스러워집니다. 그러나 나는 여기에 상응하는 것을 찾았습니다 : stackoverflow.com/questions/2948212/… ... 아직 약간 조정이 필요했지만 (폭이 아닌 가장 큰 치수를 기준으로 크기를 조정합니다).
다윗은 주어

12

그리드 항목 사각형을 얻는 것은 상당히 쉽습니다.

그리드 어댑터의 "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;
}

이것이 저에게 효과가 있었던 유일한 해결책입니다 ... 정말 감사합니다 !!
Zeba

4
"getRequestedColumnWidth"를 "getColumnWidth"로 바꾸어야했고 저에게 효과적이었습니다. 감사합니다!
Ayad Kara Kâhya

1
여기에 동일 : 나는 교체 getRequestedColumnWidth해야 getColumnWidth했고 나를 위해 일했습니다 ... 감사합니다!
Yahya

6

이것이 최선의 방법인지는 모르겠지만 사용자 정의보기를 사용하여 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는 래핑되지 않고 대부분의 뷰는 경계를 다시 조정하지 않습니다. 그러나 이것은 그것을 고친다!
Makario

6

이것은 나를 위해 일했습니다!

당신이 나와 같고 minSdk가 16보다 낮기 때문에 getRequestedColumnWidth ()를 사용할 수 없다면이 옵션을 제안합니다.

  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. fragment.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" />

누군가를 도울 수 있기를 바랍니다!


5

xml에서 정적 열 수를 설정하면보기의 너비를 열 수로 나눌 수 있습니다.

사용하는 경우 auto_fit열 수를 얻는 것이 약간 까다로울 것입니다 (getColumnCount () 메서드가 없습니다). btw 질문은 어떻게 든 도움이 될 것입니다.

이것은 getView(...)고정 된 수의 열이있는 어댑터 메서드에 사용하는 코드 입니다.

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

5

시험

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

다른 모드로도 플레이 할 수 있습니다


4

이것이 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) );

3

API 16+ 인 SteveBorkman의 답변을 기반으로합니다 .

@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;
}

1

@Gregory의 답변 라인을 따라 GridView가 정사각형에서 치수를 조작하지 못하도록 LinearLayout에 이미지를 래핑해야했습니다. 외부 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"

        />

-1

당신의 활동에서

 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));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.