web-dev-qa-db-fra.com

Gridview avec deux colonnes et images redimensionnées automatiquement

J'essaie de faire un gridview avec deux colonnes. Je veux dire deux photos par rangée côte à côte, tout comme cette image.

enter image description here

Mais mes images ont des espaces entre elles, car elles ne sont pas de la même taille. Voici ce que je reçois.

enter image description here

comme vous pouvez le voir, la première image cache la légende qui indique le nom du contact et son numéro de téléphone. et les autres images ne sont pas étirées correctement.

Voici mon fichier (GridView xml. Comme vous pouvez le constater, la columnWidth est définie sur 200dp. Je voudrais que ce soit automatique, les images seront donc redimensionnées automatiquement pour chaque taille d'écran.

<?xml version="1.0" encoding="utf-8"?>
<GridView 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/gridViewContacts"
    Android:layout_width="fill_parent" 
    Android:layout_height="fill_parent"
    Android:numColumns="2"
    Android:columnWidth="200dp"
    Android:stretchMode="columnWidth"    
    Android:gravity="center" />

et voici le fichier élément XML, qui représente chaque élément lui-même.

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

    <ImageView
        Android:id="@+id/imageViewContactIcon"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:scaleType="fitXY" />

    <LinearLayout
        Android:id="@+id/linearlayoutContactName"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="horizontal"
        Android:paddingLeft="5dp"
        Android:paddingTop="5dp"
        Android:paddingBottom="5dp"
        Android:background="#99000000"
        Android:layout_alignBottom="@+id/imageViewContactIcon">

        <TextView
            Android:id="@+id/textViewContactName"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:textColor="#FFFFFF"
            Android:textStyle="bold"
            Android:textSize="15sp"
            Android:text="Lorem Ipsum" />       

        <TextView
            Android:id="@+id/textViewContactNumber"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:textColor="#FFFFFF"
            Android:layout_marginLeft="5dp"
            Android:focusable="true"
            Android:ellipsize="Marquee"
            Android:marqueeRepeatLimit="Marquee_forever"
            Android:textSize="10sp"
            Android:text="123456789" />

    </LinearLayout>

</RelativeLayout>

Donc ce que je veux, c'est montrer deux images par ligne et les images redimensionnées automatiquement, quelle que soit la taille de l'écran. Qu'est-ce que je fais de mal avec ma mise en page?

Merci.

174
rogcg

Voici une méthode relativement facile à faire. Ajoutez un GridView à votre présentation en définissant le mode d’extension pour étirer la largeur des colonnes, définissez un espacement égal à 0 (ou celui que vous souhaitiez) et définissez le nombre de colonnes à 2:

res/layout/main.xml

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

    <GridView
        Android:id="@+id/gridview"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:verticalSpacing="0dp"
        Android:horizontalSpacing="0dp"
        Android:stretchMode="columnWidth"
        Android:numColumns="2"/>

</FrameLayout>

Créez un ImageView personnalisé qui conserve ses proportions:

src/com/exemple/graphicstest/SquareImageView.Java

public class SquareImageView extends ImageView {
    public SquareImageView(Context context) {
        super(context);
    }

    public SquareImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
    }
}

Créez une mise en page pour un élément de grille à l'aide de ce SquareImageView et définissez le scaleType sur centerCrop:

res/layout/grid_item.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
             Android:layout_width="match_parent"
             Android:layout_height="match_parent">

    <com.example.graphicstest.SquareImageView
        Android:id="@+id/picture"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:scaleType="centerCrop"/>

    <TextView
        Android:id="@+id/text"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:paddingLeft="10dp"
        Android:paddingRight="10dp"
        Android:paddingTop="15dp"
        Android:paddingBottom="15dp"
        Android:layout_gravity="bottom"
        Android:textColor="@Android:color/white"
        Android:background="#55000000"/>

</FrameLayout>

Créez maintenant une sorte d’adaptateur pour votre GridView:

src/com/exemple/graphicstest/MyAdapter.Java

private final class MyAdapter extends BaseAdapter {
    private final List<Item> mItems = new ArrayList<Item>();
    private final LayoutInflater mInflater;

    public MyAdapter(Context context) {
        mInflater = LayoutInflater.from(context);

        mItems.add(new Item("Red",       R.drawable.red));
        mItems.add(new Item("Magenta",   R.drawable.Magenta));
        mItems.add(new Item("Dark Gray", R.drawable.dark_gray));
        mItems.add(new Item("Gray",      R.drawable.gray));
        mItems.add(new Item("Green",     R.drawable.green));
        mItems.add(new Item("Cyan",      R.drawable.cyan));
    }

    @Override
    public int getCount() {
        return mItems.size();
    }

    @Override
    public Item getItem(int i) {
        return mItems.get(i);
    }

    @Override
    public long getItemId(int i) {
        return mItems.get(i).drawableId;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        View v = view;
        ImageView picture;
        TextView name;

        if (v == null) {
            v = mInflater.inflate(R.layout.grid_item, viewGroup, false);
            v.setTag(R.id.picture, v.findViewById(R.id.picture));
            v.setTag(R.id.text, v.findViewById(R.id.text));
        }

        picture = (ImageView) v.getTag(R.id.picture);
        name = (TextView) v.getTag(R.id.text);

        Item item = getItem(i);

        picture.setImageResource(item.drawableId);
        name.setText(item.name);

        return v;
    }

    private static class Item {
        public final String name;
        public final int drawableId;

        Item(String name, int drawableId) {
            this.name = name;
            this.drawableId = drawableId;
        }
    }
}

Définissez cet adaptateur sur votre GridView:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    GridView gridView = (GridView)findViewById(R.id.gridview);
    gridView.setAdapter(new MyAdapter(this));
}

Et profitez des résultats:

Example GridView

396
kcoppock

une autre approche simple avec des éléments intégrés modernes tels que PercentRelativeLayout est désormais disponible pour les nouveaux utilisateurs qui rencontrent ce problème. merci à Android team pour la publication de cet élément.

<Android.support.percent.PercentRelativeLayout 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"
Android:clickable="true"
app:layout_widthPercent="50%">

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <ImageView
        Android:id="@+id/picture"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:scaleType="centerCrop" />

    <TextView
        Android:id="@+id/text"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_gravity="bottom"
        Android:background="#55000000"
        Android:paddingBottom="15dp"
        Android:paddingLeft="10dp"
        Android:paddingRight="10dp"
        Android:paddingTop="15dp"
        Android:textColor="@Android:color/white" />

</FrameLayout>

et pour de meilleures performances, vous pouvez utiliser des outils tels que picasso image loader, qui vous permettent de remplir toute la largeur de chaque image mère. Par exemple, dans votre adaptateur, vous devriez utiliser ceci:

int width= context.getResources().getDisplayMetrics().widthPixels;
    com.squareup.picasso.Picasso
            .with(context)
            .load("some url")
            .centerCrop().resize(width/2,width/2)
            .error(R.drawable.placeholder)
            .placeholder(R.drawable.placeholder)
            .into(item.drawableId);

maintenant, vous n’avez plus besoin de CustomImageView Class.

P.S Je recommande d'utiliser ImageView à la place de Type Int dans la classe Item.

espérons que cette aide ..

14
Setmax