77 votes

faire de la grille des éléments carrés

Je voudrais que les éléments de mon GridView soient carrés. Il y a 2 colonnes et la largeur des éléments est 'fill_parent' (par exemple, ils prennent autant d'espace horizontal que possible. Les éléments sont des vues personnalisées.

Comment faire en sorte que la hauteur des éléments soit égale à leur largeur variable?

107voto

jdamcd Points 1810

Il existe une solution plus simple lorsque les colonnes GridView sont étirées. Remplacez simplement la disposition de l'élément onMeasure de GridView par ...

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

54voto

Chris.Jenkins Points 5261

Ou si vous voulez étendre une vue, faites quelque chose de vraiment simple comme:

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

Il convient de noter que super.onMeasure() n'est pas nécessaire. onMeasured est que vous devez appeler setMeasuredDimension .

15voto

Gregory Points 2660

Je ne suis pas sûr que c'est possible avec le widgets. Votre meilleur pari pourrait être de mettre votre affichage personnalisé personnalisé dans un "SquareView". Ce point de vue pourrait ne contiennent que 1 vue d'enfant, et de la force de la hauteur égale à la largeur de ses onLayout méthode est appelée.

Je n'ai jamais essayé de faire quelque chose comme ça, mais je pense que ça ne devrait pas être trop difficile. Une alternative (et peut-être un peu plus facile) solution pourrait être de la sous-classe votre vue personnalisée racine de mise en page (comme si c'est un LinearLayout, faire un SquareLinearLayout), et de l'utiliser comme un conteneur à la place.

edit : Voici une implémentation de base qui semble fonctionner pour moi :

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

Il est conçu pour avoir un enfant, mais je l'ai ignoré tous les contrôles pour des raisons de simplicité. L'idée de base est de mesurer l'enfant avec la largeur/hauteur des paramètres fixés par le contrôle GridView (dans mon cas, il utilise numColumns=4 pour calculer la largeur), et puis faire une deuxième passe, avec les dimensions finales, avec hauteur=largeur... La mise en page est juste une simple mise en page, les mises en page qui l'enfant unique en (0, 0) avec les dimensions de votre choix (de droite à gauche, de bas en haut).

Et voici le code XML utilisé pour les éléments GridView :

<?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>

J'ai utilisé un LinearLayout à l'intérieur de la SquareView afin de gérer l'ensemble de la gravité des possibilités, les marges, etc.

Je ne suis pas sûr de savoir comment bien (ou mal) ce widget réagit à l'orientation et à la dimension des changements, mais il semble fonctionner correctement.

12voto

SteveBorkman Points 131

Il est assez facile d'obtenir le carré de la grille.

Dans votre méthode "GetView" de votre adaptateur de grille, faites simplement:

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

6voto

Luckcheese Points 81

Je ne sais pas si c'est la meilleure façon, mais j'y parviens en faisant en sorte que ma vue personnalisée écrase onSizeChanged de cette façon:

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

J'utilise cette vue personnalisée à l'intérieur d'un LinearLayout et d'un GridView et dans les deux cas, elle affiche un carré!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X