Gridview con due colonne e immagini ridimensionate automaticamente


179

Sto cercando di creare una griglia con due colonne. Intendo due foto per riga una accanto all'altra proprio come questa immagine.

inserisci qui la descrizione dell'immagine

Ma le mie foto hanno spazi tra loro, a causa del fatto che non ha le stesse dimensioni. Ecco cosa sto ottenendo.

inserisci qui la descrizione dell'immagine

come puoi vedere la prima immagine nasconde la legenda che mostra il nome del contatto e il numero di telefono. e le altre immagini non sono allungate correttamente.

Ecco il mio file XML GridView . Come puoi vedere, columnWidthè impostato su 200dp . Vorrei che fosse automatico , quindi le immagini verranno ridimensionate automaticamente per ogni dimensione dello schermo.

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

e qui è il file xml dell'articolo, che rappresenta ogni elemento stesso.

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

Quindi quello che voglio è mostrare due immagini per riga e le immagini si ridimensionano automaticamente, indipendentemente dalle dimensioni dello schermo. Cosa sto facendo di sbagliato nel mio layout?

Grazie.


1
Forse dovresti provare a incapsulare ImageView nel suo LinearLayout. In questo modo è possibile configurare il tag LinearLayout esattamente come lo si desidera e quindi semplicemente riempire ImageView.
Dani

@dani cosa intendi? posso ancora configurare ImageView esattamente come voglio. potresti darmi qualche esempio?
rogcg

penso che tu debba creare il pollice dalle immagini, che sono tutte uguali, ad esempio 100x100 o qualunque cosa ti serva. Se riesci a vedere l'immagine di esempio, l'effetto che stai cercando è visualizzare solo una parte dell'immagine. E nel tuo progetto visualizzi solo l'immagine originale, il che è sbagliato se devi creare una galleria. Prova a cercare i pollici nel sito web degli sviluppatori Android :)
Vasil Valchev

@VasilValchev ma il problema è che, anche se creo i pollici (ad es. 100x100), dovrò ridimensionarlo per schermi di dimensioni diverse. Uso anche la scaleTypeproprietà centerCrop su ImageView. Quello che devo ottenere è un modo per rendere le immagini affiancate e ridimensionare automaticamente per schermi di dimensioni diverse.
rogcg

Puoi sempre ottenere le dimensioni dello schermo in orizzontale con il codice e semplicemente dividerlo per / 2. Se riesci a vedere nel tuo progetto il problema è in altezza, se sai qual è esattamente il tuo peso puoi sempre fare un rettangolo perfetto. Non vedo dove sia il problema?
Vasil Valchev

Risposte:


402

Ecco un metodo relativamente semplice per farlo. Lancia una GridView nel layout, impostando la modalità di allungamento per allungare le larghezze delle colonne, imposta la spaziatura su 0 (o quello che desideri) e imposta il numero di colonne su 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>

Crea un'abitudine ImageViewche mantenga le sue proporzioni:

src / com / es / 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
    }
}

Crea un layout per un elemento della griglia usando SquareImageView e imposta scaleType su 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>

Ora crea una sorta di adattatore per il tuo GridView:

src / com / es / 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;
        }
    }
}

Imposta l'adattatore sul tuo 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));
}

E goditi i risultati:

Esempio GridView


3
ha funzionato! ma vorrei che mi spiegassi la necessità di creare una classe per ImageViewe perché usare qualcosa di simile <com.example.graphicstest.SquareImageView>invece di un semplice <ImageView>tag nel file xml . Potresti spiegarmi di più su queste proporzioni e su come non creare questa classe, influisce sugli elementi. c'è un modo per ottimizzare questo, senza la necessità della ImageViewclasse personalizzata ? grazie del tuo aiuto comunque.
rogcg

10
Fondamentalmente, nella classe ImageView di Android, non c'è modo di specificare semplicemente "hey, mantieni un rapporto di aspetto quadrato (larghezza / altezza) per questa vista" a meno che tu non abbia una larghezza e un'altezza del codice. Potresti fare alcune regolazioni manuali di LayoutParams in getView dell'adattatore, ma francamente, è molto più semplice lasciare che ImageView gestisca tutte le misurazioni e sovrascriva i risultati per dire "Qualunque sia la larghezza, mantieni la mia altezza uguale". Non devi mai pensarci, è sempre quadrato e funziona come previsto. Fondamentalmente questo è il modo più semplice per mantenere la vista quadrata.
Kevin Coppock

8
Non riesco a pensare a un motivo per evitare di creare la classe ImageView personalizzata, poiché puoi fare tutto ciò che puoi con una normale ImageView, ma questo ti impedisce di dover eseguire misurazioni e istanze LayoutParams e controllare ovunque .
Kevin Coppock

1
Grazie per il montaggio, ho pensato che potesse essere quello, lavorando come un fascino!
Zander,

1
@kcoppock: grazie mille per aver condiviso questo codice. Quello che mi piace di più è che puoi sostituire i colori per l'immagine con immagini "reali" e le dimensioni sono ridimensionate correttamente! Quello che vorrei capire è se è possibile ridimensionare le viste in modo che un certo numero di viste riempia l'intero schermo.
AntonSack,

14

un altro approccio semplice con roba integrata moderna come PercentRelativeLayout è ora disponibile per i nuovi utenti che hanno riscontrato questo problema. grazie al team Android per aver rilasciato questo articolo.

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

e per prestazioni migliori puoi usare alcune cose come il caricatore di immagini Picasso che ti aiutano a riempire l'intera larghezza di ogni immagine genitore. ad esempio nel tuo adattatore dovresti usare questo:

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

ora non hai più bisogno della classe CustomImageView.

PS, raccomando di usare ImageView al posto del Tipo Int nella classe Item.

spero che questo aiuto ..


Con API 26.1 questo è stato deprecato. Vedi link
Dominikus K.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.