Gridview dengan dua kolom dan gambar yang diubah ukuran otomatis

179

Saya mencoba membuat gridview dengan dua kolom. Maksud saya dua foto per baris berdampingan seperti gambar ini.

masukkan deskripsi gambar di sini

Tapi gambar saya memiliki ruang di antara mereka, karena ukurannya tidak sama. Inilah yang saya dapatkan.

masukkan deskripsi gambar di sini

karena Anda dapat melihat gambar pertama menyembunyikan legenda yang menunjukkan nama kontak dan nomor telepon. dan gambar-gambar lainnya tidak diregangkan dengan benar.

Ini file xml GridView saya . Seperti yang Anda lihat columnWidthdiatur ke 200dp . Saya ingin ini otomatis , sehingga gambar akan secara otomatis mengubah ukuran untuk setiap ukuran layar.

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

dan di sini adalah file item xml, yang mewakili setiap item itu sendiri.

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

Jadi yang saya inginkan adalah menampilkan dua gambar per baris, dan ukuran gambar otomatis, tidak peduli ukuran layarnya. Apa yang saya lakukan salah pada tata letak?

Terima kasih.

rogcg
sumber
1
Mungkin Anda harus mencoba merangkum ImageView dalam LinearLayout sendiri. Dengan cara ini Anda dapat mengkonfigurasi tag LinearLayout persis seperti yang Anda inginkan dan kemudian cukup ImageView mengisinya.
dani
@ani apa maksudmu? saya masih dapat mengkonfigurasi ImageView persis seperti yang saya inginkan. dapatkah Anda memberi saya contoh?
rogcg
saya pikir Anda perlu membuat jempol dari gambar, yang semuanya sama, ex 100x100 atau apa pun yang Anda butuhkan. Jika Anda dapat melihat contoh gambar Anda, efek yang Anda cari hanya menampilkan sebagian gambar. Dan dalam proyek Anda, Anda hanya menampilkan gambar asli, yang salah jika Anda perlu membuat galeri. Coba cari jempol di situs web dev android :)
Vasil Valchev
@VasilValchev tetapi masalahnya adalah, bahkan jika saya membuat jempol (misalnya 100x100), saya perlu mengubah ukurannya untuk ukuran layar yang berbeda. Saya sudah menggunakan scaleTypeproperti centerCrop di ImageView. Yang perlu saya capai adalah cara membuat gambar berdampingan, dan secara otomatis mengubah ukuran untuk ukuran layar yang berbeda.
rogcg
Anda selalu bisa mendapatkan ukuran layar dalam kode whit horisontal dan hanya membaginya dengan / 2. Jika Anda dapat melihat dalam proyek Anda masalahnya adalah tingginya, jika Anda tahu apa sebenarnya berat badan Anda, Anda selalu dapat membuat persegi panjang yang sempurna. Saya tidak melihat di mana masalahnya?
Vasil Valchev

Jawaban:

402

Inilah metode yang relatif mudah untuk melakukan ini. Lemparkan GridView ke tata letak Anda, atur mode peregangan untuk meregangkan lebar kolom, atur jarak ke 0 (atau apa pun yang Anda inginkan), dan atur jumlah kolom menjadi 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>

Buat kebiasaan ImageViewyang mempertahankan rasio aspeknya:

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

Buat tata letak untuk item kisi menggunakan SquareImageView ini dan atur scaleType ke 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>

Sekarang buat semacam adaptor untuk laptop Anda GridView :

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

Setel adaptor itu ke 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));
}

Dan nikmati hasilnya:

Contoh GridView

Kevin Coppock
sumber
3
itu berhasil! tapi saya ingin Anda menjelaskan kepada saya perlunya membuat kelas untuk ImageViewdan mengapa menggunakan sesuatu seperti ini <com.example.graphicstest.SquareImageView>alih-alih <ImageView>tag sederhana dalam file xml . Bisakah Anda menjelaskan lebih lanjut tentang rasio aspek ini , dan bagaimana tidak membuat kelas ini, memengaruhi item. apakah ada cara untuk mengoptimalkan ini, tanpa perlu ImageViewkelas khusus ? terima kasih atas bantuan Anda.
rogcg
10
Pada dasarnya, di kelas ImageView Android, tidak ada cara untuk secara spesifik menentukan "hei, pertahankan rasio aspek kuadrat (lebar / tinggi) untuk tampilan ini" kecuali Anda memiliki lebar dan tinggi kode yang sulit. Anda dapat melakukan beberapa penyesuaian LayoutParams secara manual di getView adaptor, tetapi sejujurnya, jauh lebih mudah untuk membiarkan ImageView menangani semua pengukuran, dan hanya menimpa hasilnya dengan mengatakan "Apa pun lebarnya, buat tinggi saya tetap sama". Anda tidak pernah harus memikirkannya, selalu persegi, dan hanya berfungsi seperti yang diharapkan. Pada dasarnya ini adalah cara termudah untuk menjaga tampilan persegi.
Kevin Coppock
8
Saya tidak bisa memikirkan alasan untuk menghindari membuat kelas ImageView kustom, karena Anda dapat melakukan segalanya dengan itu yang Anda bisa dengan ImageView biasa, tetapi ini hanya membuat Anda tidak harus melakukan pengukuran dan instantiasi LayoutParams dan memeriksa semua tempat. .
Kevin Coppock
1
Terima kasih telah mengedit, berpikir itu bisa saja, bekerja seperti pesona!
Zander
1
@ kcoppock: Terima kasih banyak untuk membagikan kode ini. Yang paling saya sukai adalah Anda dapat mengganti warna untuk tampilan gambar dengan gambar "asli" dan ukurannya diubah dengan benar! Yang ingin saya pahami adalah apakah mungkin untuk mengubah ukuran tampilan sehingga sejumlah tampilan memenuhi seluruh layar.
AntonSack
14

pendekatan sederhana lain dengan barang bawaan modern seperti PercentRelativeLayout sekarang tersedia untuk pengguna baru yang mengalami masalah ini. terima kasih kepada tim android untuk merilis item ini.

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

dan untuk kinerja yang lebih baik Anda dapat menggunakan beberapa hal seperti picasso image loader yang membantu Anda mengisi seluruh lebar setiap gambar orang tua. misalnya di adaptor Anda, Anda harus menggunakan ini:

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

sekarang Anda tidak perlu Kelas CustomImageView lagi.

PS saya sarankan untuk menggunakan ImageView di tempat Tipe Int di Item kelas.

semoga ini membantu ..

Setmax
sumber
Dengan API 26.1 ini menjadi rusak. Lihat tautan
Dominikus K.