web-dev-qa-db-ja.com

GridViewアイテムを正方形にする

GridViewのアイテムを正方形にしたいのですが。列は2つあり、アイテムの幅はfill_parent(たとえば、可能な限り水平方向のスペースを取ります。アイテムはカスタムビューです。

アイテムの高さを可変幅に等しくするにはどうすればよいですか?

77
anagaf

GridView列が引き伸ばされている場合、より簡単なソリューションがあります。 GridViewアイテムレイアウトのonMeasureをオーバーライドするだけです...

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

または、ビューを拡張したい場合は、次のような本当に簡単なことをしてください。

_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を呼び出す必要があることです。

53
Chris.Jenkins

これが現在のウィジェットで可能かどうかはわかりません。最善の策は、カスタムビューをカスタムの「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を使用して幅を計算する)、次に高さ=幅の最終寸法で2回目のパスを行うことです。 ..レイアウトは、プレーンレイアウトであり、(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を使用しました。

このウィジェットが向きと寸法の変化にどれだけうまく(または悪い)反応するかはわかりませんが、正しく機能しているようです。

15
Gregory

最終的に、グリッド項目を正方形にするのはかなり簡単になります。

グリッドアダプターの「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;
}
12
SteveBorkman

それが最良の方法であるかどうかはわかりませんが、カスタムビューを作成して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内で使用すると、両方で正方形が表示されます!

6
Luckcheese

これは私のために働いた!

あなたが私のような人で、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" />

それが誰かを助けることを願っています!

6
Anne-Claire

xmlに静的な列数を設定した場合、ビューの幅を取得して列数で割ることができます。

_auto_fit_を使用している場合、列カウント(getColumnCount()メソッドはありません)を取得するのは少しトリッキーになります、btw this question shouldどういうわけかあなたを助けます。

これは、固定数の列を持つアダプターのgetView(...)メソッドに使用しているコードです。

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

これは、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) );
4
Sileria

試して

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

他のモードで遊ぶこともできます

4
Art

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;
}
3
Joaquin Iurchuk

@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
larham1