Tìm hiểu về gridview trong android

1. Giới thiệu về adapter

Có nhiều View cần tới Android Adapter để quản lý dữ liệu hiển thị, các View này là con của class AdapterView, bạn có thể xem ở hình minh họa dưới đây: alt

Android Adapter

alt

2. Giới thiệu về grid view

2.1 Giới thiệu

GridView trong Android hiển thị các item trong mảng lưới hai chiều có thể scroll và các item này không cần thiết phải được định nghĩa trước, nhưng chúng tự động chèn vào Layout bởi sử dụng một ListAdapter.

2.2 Một số thuộc tính đặc biệt

  • android:verticalSpacing -> Định nghĩa khoảng cách mặc định theo chiều dọc giữa các hàng. Có thể là trong px, dp, sp, in, hoặc mm
  • android:horizontalSpacing -> Định nghĩa khoảng cách mặc định theo chiều ngang giữa các cột. Có thể là trong px, dp, sp, in, hoặc mm
  • android:numColumns -> Xác định có bao nhiêu cột để hiển thị

3. Khởi tạo Adapter

3.1 Xây dựng đối tượng City

package com.example.tuananh.gridviewcustom.data.model;

/**
 * Created by framgia on 25/10/2016.
 */
public class City {
    private String mId;
    private String mName;
    private int mIdImage;

    public City(String id, String name, int idImage) {
        mId = id;
        mName = name;
        mIdImage = idImage;
    }

    public City(String name, int idImage) {
        mName = name;
        mIdImage = idImage;
    }

    public String getId() {
        return mId;
    }

    public String getName() {
        return mName;
    }

    public int getIdImage() {
        return mIdImage;
    }
}

3.2 Tạo activity_grid_view_custom.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:orientation="vertical"
    tools:context="com.example.tuananh.gridviewcustom.ui.activity.GridViewCustomActivity">

    <GridView
        android:id="@+id/grid_view_custom"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_marginTop="@dimen/activity_sell_gird_view_margin_top"
        android:gravity="center"
        android:horizontalSpacing="@dimen/activity_sell_gird_view_horizontal_spacing"
        android:numColumns="2"
        android:verticalSpacing="@dimen/activity_sell_gird_view_vertical_spacing"/>

</LinearLayout>

3.3 Khởi tạo data

private void createData() {
        mCityList = new ArrayList<>();
        mCityList.add(new City("01", "Hà Nội", R.drawable.image_ha_noi));
        mCityList.add(new City("02", "Hồ Chí Minh", R.drawable.image_ho_chi_minh));
        mCityList.add(new City("03", "Hải Phòng", R.drawable.image_hai_phong));
        mCityList.add(new City("04", "Đà Nẵng", R.drawable.image_da_nang));
        mCityList.add(new City("05", "Hà Giang", R.drawable.image_ha_giang));
        mCityList.add(new City("21", "Hải Dương", R.drawable.image_hai_duong));
        mCityList.add(new City("22", "Hưng Yên", R.drawable.image_hung_yen));
    }

3.4 Dùng layout default

android.R.layout.simple_list_item_1 chỉ gồm 1 textView

List<String> arrNameCity = new ArrayList<>();
                for (City city : mCityList) {
                    arrNameCity.add(city.getName());
                }
                ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                    android.R.layout.simple_list_item_1, arrNameCity);
                mGridViewCustom.setAdapter(adapter);

Ảnh kết quả

Screenshot from 2016-10-26 08-40-27.png

3.5 Custom gridView

mGridViewCustomAdapter = new GridViewCustomAdapter(this, mCityList, typeCustom);               mGridViewCustom.setAdapter(mGridViewCustomAdapter);

Adapter

package com.example.tuananh.gridviewcustom.ui.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.tuananh.gridviewcustom.R;
import com.example.tuananh.gridviewcustom.data.Constant;
import com.example.tuananh.gridviewcustom.data.model.City;

import java.util.List;

/**
 * Created by framgia on 24/10/2016.
 */
public class GridViewCustomAdapter extends BaseAdapter {
    private List<City> mCityList;
    private LayoutInflater mLayoutInflater;
    private int mTypeCustom;

    public GridViewCustomAdapter(Context context, List<City> cityList, int typeCustom) {
        mLayoutInflater = LayoutInflater.from(context);
        mCityList = cityList;
        mTypeCustom = typeCustom;
    }

    @Override
    public int getCount() {
        // quy định số lượng hiển thị
        return mCityList == null ? 0 : mCityList.size();
    }

    @Override
    public Object getItem(int position) {
        return mCityList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return Integer.parseInt(mCityList.get(position).getId());
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        switch (mTypeCustom) {
            case Constant.TYPE_GRID_VIEW_CUSTOM_TEXT_CUSTOM_ONE_TEXT:
                return getViewTextCustomOneText(position, convertView, parent);
            case Constant.TYPE_GRID_VIEW_CUSTOM_TEXT_CUSTOM_MORE_TEXT:
                return getViewTextCustomMoreText(position, convertView, parent);
            case Constant.TYPE_GRID_VIEW_CUSTOM_IMAGE:
                return getViewImageCustom(position, convertView, parent);
            case Constant.TYPE_GRID_VIEW_CUSTOM_IMAGE_AND_TEXT:
                return getViewImageTextCustom(position, convertView, parent);
            default:
                return getViewTextCustomOneText(position, convertView, parent);
        }
    }
}

  • Custom one text
 private View getViewTextCustomOneText(int position, View convertView, ViewGroup parent) {
        String nameCity = mCityList.get(position).getName();
        TextView textViewNameCity;
        if (convertView == null) {
            convertView =
                mLayoutInflater.inflate(R.layout.item_grid_view_custom_one_text, parent, false);
            textViewNameCity = (TextView) convertView.findViewById(R.id.text_custom_one_text);
        } else {
            textViewNameCity = (TextView) convertView;
        }
        textViewNameCity.setText(nameCity);
        return textViewNameCity;
    }

với layout item_grid_view_custom_one_text

<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/text_custom_one_text"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="@dimen/text_view_width"
          android:layout_height="@dimen/text_view_height"
          android:background="@drawable/surround_item"
          android:gravity="center">
</TextView>

Ảnh kết quả

Screenshot from 2016-10-26 09-00-21.png

  • Custom more text
private View getViewTextCustomMoreText(int position, View convertView, ViewGroup parent) {
        ViewTextHolder viewTextHolder;
        if (convertView == null) {
            convertView = mLayoutInflater.inflate(R.layout.item_grid_view_custom_more_text,
                parent, false);
            viewTextHolder = new ViewTextHolder();
            viewTextHolder.mTextViewNameCity =
                (TextView) convertView.findViewById(R.id.text_name_city);
            viewTextHolder.mTextViewIdCity = (TextView) convertView.findViewById(R.id.text_id_city);
            convertView.setTag(viewTextHolder);
        } else {
            viewTextHolder = (ViewTextHolder) convertView.getTag();
        }
        String nameCity = mCityList.get(position).getName();
        String idCity = mCityList.get(position).getId();
        viewTextHolder.mTextViewNameCity.setText(nameCity);
        viewTextHolder.mTextViewIdCity.setText(
            new StringBuilder().append(Constant.ID_PROVINCE).append(idCity).toString());
        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        return convertView;
    }

    private class ViewTextHolder {
        private TextView mTextViewNameCity;
        private TextView mTextViewIdCity;
    }

với layout item_grid_view_custom_more_text

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@drawable/surround_item"
              android:orientation="vertical">

    <TextView
        android:id="@+id/text_id_city"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/text_name_city"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:paddingTop="@dimen/padding_small"
        android:textColor="@android:color/holo_red_light"/>
</LinearLayout>

Ảnh kết quả :

Screenshot from 2016-10-26 09-00-10.png

  • Custom image
private View getViewImageCustom(int position, View convertView, ViewGroup parent) {
        ImageView imageViewCity;
        if (convertView == null) {
            convertView =
                mLayoutInflater.inflate(R.layout.item_grid_view_custom_image, parent, false);
            imageViewCity = (ImageView) convertView.findViewById(R.id.image_item);
            convertView.setTag(imageViewCity);
        } else {
            imageViewCity = (ImageView) convertView.getTag();
        }
        imageViewCity.setImageResource(mCityList.get(position).getIdImage());
        return convertView;
    }

với layout item_grid_view_custom_image:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@drawable/surround_item"
              android:orientation="vertical">

    <ImageView
        android:id="@+id/image_item"
        android:layout_width="@dimen/image_city_size"
        android:layout_height="@dimen/image_city_size"
        android:layout_gravity="center_horizontal"
        android:scaleType="centerCrop">
    </ImageView>
</LinearLayout>

Ảnh kết quả :

Screenshot from 2016-10-26 08-59-55.png

  • Image and text
 private View getViewImageTextCustom(int position, View convertView, ViewGroup parent) {
        ViewImageTextHolder viewImageTextHolder;
        if (convertView == null) {
            convertView =
                mLayoutInflater
                    .inflate(R.layout.item_grid_view_custom_image_and_text, parent, false);
            viewImageTextHolder = new ViewImageTextHolder();
            viewImageTextHolder.mTextViewIdCity = (TextView) convertView.findViewById(
                R.id.text_id_city_item);
            viewImageTextHolder.mTextViewNameCity = (TextView) convertView.findViewById(
                R.id.text_name_city_item);
            viewImageTextHolder.mImageViewCity = (ImageView) convertView.findViewById(
                R.id.image_city_item);
            convertView.setTag(viewImageTextHolder);
        } else {
            viewImageTextHolder = (ViewImageTextHolder) convertView.getTag();
        }
        City city = mCityList.get(position);
        String idCity = city.getId();
        String nameCity = city.getName();
        int idImageCity = city.getIdImage();
        viewImageTextHolder.mTextViewIdCity.setText(
            new StringBuilder().append(Constant.ID_PROVINCE).append(idCity).toString());
        viewImageTextHolder.mTextViewNameCity.setText(nameCity);
        viewImageTextHolder.mImageViewCity.setImageResource(idImageCity);
        return convertView;
    }
     private class ViewImageTextHolder {
        private TextView mTextViewIdCity;
        private TextView mTextViewNameCity;
        private ImageView mImageViewCity;
    }

với layout item_grid_view_custom_image_and_text:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@drawable/surround_item"
              android:orientation="vertical">

    <TextView
        android:id="@+id/text_id_city_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/text_name_city_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:paddingTop="@dimen/padding_small"
        android:textColor="@android:color/holo_red_light"/>

    <ImageView
        android:id="@+id/image_city_item"
        android:layout_width="@dimen/image_city_size"
        android:layout_height="@dimen/image_city_size"
        android:layout_gravity="center_horizontal"
        android:scaleType="centerCrop"/>
</LinearLayout>

Ảnh kết quả :

Screenshot from 2016-10-26 08-57-54.png

4. Chú ý

  • Xác định số lượng đối tượng hiển thị của gridview:
    Bình thường mình có "numColumns" để xác định số cột tối đa của gridview nếu muốn xác định số hàng tối đa của gridview nữa thì trong hàm getCount() chúng ta return ra (numColumns * numRow) với numColumns là số cột tối đa, numRow là số hàng tối đa.
@Override
    public int getCount() {
        // quy định số lượng hiển thị
        //return mCityList == null ? 0 : mCityList.size();
        return = numColumns * numRow;
    }
  • Chú ý với layout chỉ có 1 thành phần như item_grid_view_custom_one_text ở trên phải dùng như sau mới thay đổi kích thước các ô trong gridView được
mLayoutInflater.inflate(R.layout.item_grid_view_custom_image_and_text, parent, false);

nếu dùng

mLayoutInflater.inflate(R.layout.item_grid_view_custom_image_and_text,null;

bạn đặt giá trị kích thước của ô là bao nhiêu cũng ko đổi.

Xem ở link : http://stackoverflow.com/questions/24503760/cardview-layout-width-match-parent-does-not-match-parent-recyclerview-width

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <stroke
        android:width="@dimen/stroke_with"
        android:color="@android:color/darker_gray">
    </stroke>
    <padding
        android:bottom="@dimen/padding_small"
        android:left="@dimen/padding_small"
        android:right="@dimen/padding_small"
        android:top="@dimen/padding_small">
    </padding>
    <corners
        android:radius="@dimen/corners_radius">
    </corners>
</shape>

5 Link source code

Source code