Руководство Android GridView
1. Что такое GridView?
GridView это viewgroup, который показывает элеметы в двумерной сетке.
GridItem
GridView создан из списка GridItem. GridItem это отдельная ячейка (cell) в gridview там где будут показаны данные. Любые данные в gridview показываются только через griditem.
GridItem это часть интерфейса, который может быть создан некоторыми View.
Android создает некоторые формы GridItem, они называются предопределенным Layout, я упомяну о них в примерах этой статьи.
Adapter
Android Adapter (Адаптер) это мост соединяющий View и базовые данные этого View. Adapter контролирует данные и адаптирует данные к отдельным ячейкам (GridItems) view.
Вы можете привязать Adapter к GridView используя метод setAdapter. Теперь, пoсмотрим как работает Adapter с помощью следующих изображений.
Вы можете привязать Adapter к GridView используя метод setAdapter. Теперь, пoсмотрим как работает Adapter с помощью следующих изображений.
GridView Selector
Чтобы лучше украсить GridView, вам нужно персонализировать эффекты, такие как изменение фонового цвета GridItem когда курсор переменяется на нет или изменить цвет фона когда выбран GridItem. Можете посмотреть пример персонализации GridView Selector в конце данной статьи.
2. Базовый GridView используя ArrayAdapter
ArrayAdapter
ArrayAdapter используется для отображения GridView с простыми GridItem, GridItem можно создать только из TextView, CheckedTextView, EditText,...
Если вы хотите GridView со более сложным GridItem, вы можете сами создать кастомизированный Adapter.
Если вы хотите GridView со более сложным GridItem, вы можете сами создать кастомизированный Adapter.
Пример GridView с ArrayAdapter
Создать Android project с названием SimpleGridView.
- File > New > New Project > Empty Activity
- Name: SimpleGridView
- Package name: org.o7planning.simplegridview
- Language: Java
Дизайн интерфейса:
Изменить настройки:
GridView
- android:numColumns ="2"
- android:stretchMode ="columnWidth"
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:id="@+id/gridView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:numColumns="2"
android:stretchMode="columnWidth"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Website.java
package org.o7planning.simplegridview;
public class Website {
private String name;
private String url;
public Website(String name, String url) {
this.name= name;
this.url= url;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
MainActivity.java
package org.o7planning.simplegridview;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private GridView gridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.gridView = (GridView)findViewById(R.id.gridView);
//
Website o7planning = new Website("o7planning","http://o7planning.org");
Website google = new Website("Google","http://google.com");
Website facebook = new Website("Facebook","http://facebook.com");
Website eclipse = new Website("Eclipse","http://eclipse.org");
Website yahoo = new Website("Yahoo","http://yahoo.com");
Website[] websites = new Website[]{o7planning,google, facebook,eclipse, yahoo};
// android.R.layout.simple_list_item_1 is a constant predefined layout of Android.
// used to create a GridView with simple GridItem (Only one TextView).
ArrayAdapter<Website> arrayAdapter
= new ArrayAdapter<Website>(this, android.R.layout.simple_list_item_1 , websites);
gridView.setAdapter(arrayAdapter);
// When the user clicks on the GridItem
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = gridView.getItemAtPosition(position);
Website website = (Website) o;
Toast.makeText(MainActivity.this, "Selected :" + " " + website.getName()+"\n("+ website.getUrl()+")",
Toast.LENGTH_LONG).show();
}
});
}
}
Запуск примера:
Готовые Layout для работы с ArrayAdapter
Android создал некоторые Layout (для GridItem, ListItem,..) которые могут работать с ArrayAdapter.
android.R.layout.simple_list_item_1
- Это простой layoutGridItem, созданный единственным TextView (Смотрите примеры выше).
android.R.layout.simple_list_item_checked & android.R.layout.simple_list_item_multiple_choice
- 2 Layout выше это простые layout чтобы создать GridView с GridItem имеющий checkbox.
- TODO
3. Кастомизировать GridView используя BaseAdapter
Вы можете создать кастомизированный GridViewer. Ваш Adapter нужно расширить из класса BaseAdapter.
Пример кастомизированного GridView
Создать "Empty Activity" project с названием CustomGridView.
- File > New > New Project > Empty Activity
- Name: CustomGridView
- Package name: org.o7planning.customgridview
- Language: Java
Предварительный просмотр приложения:
Приготовить несколько изображений:
Копировать и вставить изображения в папку mipmap:
vn.png | us.png | ru.png | jp.png | au.png |
Вам нужно создать layout для Griditem. На Android Studio нажмите на правую мышь на res/layout и выберите:
- New/Layout resource file
Ввод:
- File name: grid_item_layout.xml
- Root element: androidx.constraintlayout.widget.ConstraintLayout
Дизайн интерфейса GridItem.
Slider шаги дизайна интерфейса для GridItem:
ImageView
TextView 1:
TextView 2:
- ID: imageView_flag
TextView 1:
- ID: textView_countryName
- Text: Country Name
TextView 2:
- ID: textView_population
- Text: Population ....
grid_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView_flag"
android:layout_width="80dp"
android:layout_height="60dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView
android:id="@+id/textView_countryName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="Country Name"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView_flag"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView_population"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="Population"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView_flag"
app:layout_constraintTop_toBottomOf="@+id/textView_countryName" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
GridView
- android:numColumns ="2"
- android:stretchMode ="columnWidth"
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:id="@+id/gridView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:numColumns="2"
android:stretchMode="columnWidth"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
CustomGridAdapter это класс расширенный из BaseAdapter, выполняет обязанность отображать данные на Grid Item.
Country.java
package org.o7planning.customgridview;
public class Country {
private String countryName;
// Image name (Without extension)
private String flagName;
private int population;
public Country(String countryName, String flagName, int population) {
this.countryName= countryName;
this.flagName= flagName;
this.population= population;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public String getFlagName() {
return flagName;
}
public void setFlagName(String flagName) {
this.flagName = flagName;
}
@Override
public String toString() {
return this.countryName+" (Population: "+ this.population+")";
}
}
CustomGridAdapter.java
package org.o7planning.customgridview;
import android.content.Context;
import android.util.Log;
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 java.util.List;
public class CustomGridAdapter extends BaseAdapter {
private List<Country> listData;
private LayoutInflater layoutInflater;
private Context context;
public CustomGridAdapter(Context aContext, List<Country> listData) {
this.context = aContext;
this.listData = listData;
layoutInflater = LayoutInflater.from(aContext);
}
@Override
public int getCount() {
return listData.size();
}
@Override
public Object getItem(int position) {
return listData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.grid_item_layout, null);
holder = new ViewHolder();
holder.flagView = (ImageView) convertView.findViewById(R.id.imageView_flag);
holder.countryNameView = (TextView) convertView.findViewById(R.id.textView_countryName);
holder.populationView = (TextView) convertView.findViewById(R.id.textView_population);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Country country = this.listData.get(position);
holder.countryNameView.setText(country.getCountryName());
holder.populationView.setText("" + country.getPopulation());
int imageId = this.getMipmapResIdByName(country.getFlagName());
holder.flagView.setImageResource(imageId);
return convertView;
}
// Find Image ID corresponding to the name of the image (in the directory mipmap).
public int getMipmapResIdByName(String resName) {
String pkgName = context.getPackageName();
// Return 0 if not found.
int resID = context.getResources().getIdentifier(resName , "mipmap", pkgName);
Log.i("CustomGridView", "Res Name: "+ resName+"==> Res ID = "+ resID);
return resID;
}
static class ViewHolder {
ImageView flagView;
TextView countryNameView;
TextView populationView;
}
}
ActivityMain.java
package org.o7planning.customgridview;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Country> image_details = getListData();
final GridView gridView = (GridView) findViewById(R.id.gridView);
gridView.setAdapter(new CustomGridAdapter(this, image_details));
// When the user clicks on the GridItem
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = gridView.getItemAtPosition(position);
Country country = (Country) o;
Toast.makeText(MainActivity.this, "Selected :"
+ " " + country, Toast.LENGTH_LONG).show();
}
});
}
private List<Country> getListData() {
List<Country> list = new ArrayList<Country>();
Country vietnam = new Country("Vietnam", "vn", 98000000);
Country usa = new Country("United States", "us", 320000000);
Country russia = new Country("Russia", "ru", 142000000);
Country australia = new Country("Australia", "au", 23766305);
Country japan = new Country("Japan", "jp", 126788677);
list.add(vietnam);
list.add(usa);
list.add(russia);
list.add(australia);
list.add(japan);
return list;
}
}
Запуск приложения:
Пример кастомизираванного Selector
Чтобы улучшить GridView, вам нужно кастомизировать эффекты, например при изменении цвета фона GridItem при движении курсора или при выборе GridItem. Продолжим с примером.
Создать конфигурационные файлы:
- File name: item_state_normal.xml
- Directory: drawable
Индентично создайте другие 3 файла:
- item_state_pressed.xml
- item_state_selected.xml
- list_selector.xml
Когда Grid Item находится в обычном состоянии, стили (style) настроенные в item_state_normal.xml будт применены к GridItem.
item_state_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#f1f1f2"
android:centerColor="#e7e7e8"
android:endColor="#cfcfcf"
android:angle="270" />
</shape>
При нажатии на Grid Item стили настроенные в item_state_pressed.xml будут применены к GridItem
item_state_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#18d7e5"
android:centerColor="#16cedb"
android:endColor="#09adb9"
android:angle="270" />
</shape>
Когда GridItem выбирает style (стили) настройки в item_state_selected.xml будут применены к GridItem
item_state_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#18d7e5"
android:centerColor="#16cedb"
android:endColor="#09adb9"
android:angle="270" />
</shape>
Сопоставить определенные статусы GridItem с вышеуказанными файлами xml.
list_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="@drawable/item_state_normal" />
<item android:state_pressed="true"
android:drawable="@drawable/item_state_pressed" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="@drawable/item_state_selected" />
</selector>
Настроить ListSelector для GridView:
<GridView
...
android:listSelector="@drawable/list_selector" />
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:id="@+id/gridView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:numColumns="2"
android:stretchMode="columnWidth"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:listSelector="@drawable/list_selector" />
</androidx.constraintlayout.widget.ConstraintLayout>
Перезапустить приложение.
Pуководства Android
- Настроить Android Emulator в Android Studio
- Руководство Android ToggleButton
- Создать простой File Finder Dialog в Android
- Руководство Android TimePickerDialog
- Руководство Android DatePickerDialog
- Что мне нужно для начала работы с Android?
- Установите Android Studio в Windows
- Установите Intel® HAXM для Android Studio
- Руководство Android AsyncTask
- Руководство Android AsyncTaskLoader
- Руководство Android для начинающих - основные примеры
- Как узнать номер телефона Android Emulator и изменить его?
- Руководство Android TextInputLayout
- Руководство Android CardView
- Руководство Android ViewPager2
- Получить номер телефона в Android с помощью TelephonyManager
- Руководство Android Phone Call
- Руководство Android Wifi Scanning
- Руководство Android 2D Game для начинающих
- Руководство Android DialogFragment
- Руководство Android CharacterPickerDialog
- Руководство Android для начинающих - Hello Android
- Использование Android Device File Explorer
- Включить USB Debugging на устройстве Android
- Руководство Android UI Layouts
- Руководство Android SMS
- Руководство Android SQLite Database
- Руководство Google Maps Android API
- Руководство Текст в речь на Android
- Руководство Android Space
- Руководство Android Toast
- Создание пользовательских Android Toast
- Руководство Android SnackBar
- Руководство Android TextView
- Руководство Android TextClock
- Руководство Android EditText
- Руководство Android TextWatcher
- Форматирование номера кредитной карты с помощью Android TextWatcher
- Руководство Android Clipboard
- Создать простой File Chooser в Android
- Руководство Android AutoCompleteTextView и MultiAutoCompleteTextView
- Руководство Android ImageView
- Руководство Android ImageSwitcher
- Руководство Android ScrollView и HorizontalScrollView
- Руководство Android WebView
- Руководство Android SeekBar
- Руководство Android Dialog
- Руководство Android AlertDialog
- Руководство Android RatingBar
- Руководство Android ProgressBar
- Руководство Android Spinner
- Руководство Android Button
- Руководство Android Switch
- Руководство Android ImageButton
- Руководство Android FloatingActionButton
- Руководство Android CheckBox
- Руководство Android RadioGroup и RadioButton
- Руководство Android Chip и ChipGroup
- Использование Image assets и Icon assets Android Studio
- Настройка SD Card для Android Emulator
- Пример ChipGroup и Chip Entry
- Как добавить внешние библиотеки в Android Project в Android Studio?
- Как отключить разрешения, уже предоставленные приложению Android?
- Как удалить приложения из Android Emulator?
- Руководство Android LinearLayout
- Руководство Android TableLayout
- Руководство Android FrameLayout
- Руководство Android QuickContactBadge
- Руководство Android StackView
- Руководство Android Camera
- Руководство Android MediaPlayer
- Руководство Android VideoView
- Воспроизведение звуковых эффектов в Android с помощью SoundPool
- Руководство Android Networking
- Руководство Android JSON Parser
- Руководство Android SharedPreferences
- Руководство Android Internal Storage
- Руководство Android External Storage
- Руководство Android Intents
- Пример явного Android Intent, вызов другого Intent
- Пример неявного Android Intent, откройте URL, отправьте email
- Руководство Android Services
- Использовать оповещения в Android - Android Notification
- Руководство Android DatePicker
- Руководство Android TimePicker
- Руководство Android Chronometer
- Руководство Android OptionMenu
- Руководство Android ContextMenu
- Руководство Android PopupMenu
- Руководство Android Fragment
- Руководство Android ListView
- Android ListView с Checkbox с помощью ArrayAdapter
- Руководство Android GridView
Show More