🥰
【Android】ListViewを使ったリスト表示
ListViewとは
- 垂直方向にスクロール可能な1列のリストを表示します。
- ListViewにデータを表示するには、Adapterを利用します。
- AdapterとはデータとViewの間を受け渡しするオブジェクトです。
ListViewに使うAdapterにはいくつかの種類がありますが、今回は以下のAdapterを使ってサンプルアプリを実装します。
- ArrayAdapter
- SimpleAdapter
- BaseAdapter
アプリを作る
ArrayAdapter
ArrayAdapterを使ってAndroidのプラットフォームバージョンを表示するアプリを作ります。
プロジェクト名を「ArrayAdapter」で作成して、activity_main.xmlとMainActivity.javaを以下のようにします。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/platform_version_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package com.example.arrayadapter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] platformVersion = {
"Android 10.0",
"Android 9",
"Android 8.1",
"Android 8.0",
"Android 7.1.1",
"Android 7.1",
"Android 7.0",
"Android 6.0",
"Android 5.1",
"Android 5.0",
"Android 4.4W",
"Android 4.4",
"Android 4.3",
"Android 4.2、4.2.2",
"Android 4.1、4.1.1",
"Android 4.0.3、4.0.4",
"Android 4.0、4.0.1、4.0.2",
"Android 3.2",
"Android 3.1.x",
"Android 3.0.x",
"Android 2.3.4",
"Android 2.3.3",
"Android 2.3.2",
"Android 2.3.1",
"Android 2.3",
"Android 2.2.x",
"Android 2.1.x",
"Android 2.0.1",
"Android 2.0",
"Android 1.6",
"Android 1.5",
"Android 1.1",
"Android 1.0",
};
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
getApplicationContext(),
android.R.layout.simple_list_item_1, // Androidに組み込まれているレイアウト
platformVersion
);
ListView listView = findViewById(R.id.platform_version_list);
listView.setAdapter(arrayAdapter);
}
}
実行結果
SimpleAdapter
次にSimpleAdapterを使ってアプリを作ります。
専用のレイアウトファイルを作り、Android Versionの一覧リストを作成します。
プロジェクト名を「SimpleAdapter」で作成して以下のプログラムを作ります。
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">
<ListView
android:id="@+id/android_version_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
android_version.xml
- ListViewのレイアウト
<?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:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/platform_version"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_weight="0.4"
android:gravity="start|center"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textColor="#DD000000"
android:textSize="12sp" />
<TextView
android:id="@+id/api_level"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:gravity="start|center"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textColor="#DD000000"
android:textSize="12sp" />
<TextView
android:id="@+id/version_code"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_weight="0.5"
android:gravity="start|center"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textColor="#DD000000"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
AndroidVersionDetail.java
- Android Versionのデータを定義する
package com.example.simpleadapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AndroidVersionDetail {
public static List<Map<String, String>> getData() {
String[] platformVersionList = {
"Android 10.0",
"Android 9",
"Android 8.1",
"Android 8.0",
"Android 7.1, 7.1.1",
"Android 7.0",
"Android 6.0",
"Android 5.1",
"Android 5.0",
"Android 4.4W",
"Android 4.4",
"Android 4.3",
"Android 4.2, 4.2.2",
"Android 4.1, 4.1.1",
"Android 4.0.3, 4.0.4",
"Android 4.0, 4.0.1, 4.0.2",
"Android 3.2",
"Android 3.1.x",
"Android 3.0.x",
"Android 2.3.3, 2.3.4",
"Android 2.3, 2.3.1, 2.3.2",
"Android 2.2.x",
"Android 2.1.x",
"Android 2.0.1",
"Android 2.0",
"Android 1.6",
"Android 1.5",
"Android 1.1",
"Android 1.0",
};
String[] apiLevelList = {
"29",
"28",
"27",
"26",
"25",
"24",
"23",
"22",
"21",
"20",
"19",
"18",
"17",
"16",
"15",
"14",
"13",
"12",
"11",
"10",
"9",
"8",
"7",
"6",
"5",
"4",
"3",
"2",
"1",
};
String[] versionCodeList = {
"Q",
"P",
"O_MR1",
"O",
"N_MR1",
"N",
"M",
"LOLLIPOP_MR1",
"LOLLIPOP",
"KITKAT_WATCH",
"KITKAT",
"JELLY_BEAN_MR2",
"JELLY_BEAN_MR1",
"JELLY_BEAN",
"ICE_CREAM_SANDWICH_MR1",
"ICE_CREAM_SANDWICH",
"HONEYCOMB_MR2",
"HONEYCOMB_MR1",
"HONEYCOMB",
"GINGERBREAD_MR1",
"GINGERBREAD",
"FROYO",
"ECLAIR_MR1",
"ECLAIR_0_1",
"ECLAIR",
"DONUT",
"CUPCAKE",
"BASE_1_1",
"BASE",
};
List<Map<String, String>> list = new ArrayList<>();
for (int i = 0; i < platformVersionList.length; i++) {
Map<String, String> data = new HashMap<>();
data.put("platformVersion", platformVersionList[i]);
data.put("apiLevel", apiLevelList[i]);
data.put("versionCode", versionCodeList[i]);
list.add(data);
}
return list;
}
}
MainActivity.java
package com.example.simpleadapter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Map<String, String>> androidVersionList = AndroidVersionDetail.getData();
SimpleAdapter androidVersionListAdapter = new SimpleAdapter(
getApplicationContext(),
androidVersionList,
R.layout.android_version,
new String[]{"platformVersion", "apiLevel", "versionCode"},
new int[]{R.id.platform_version, R.id.api_level, R.id.version_code}
);
ListView listView = findViewById(R.id.android_version_list);
listView.setAdapter(androidVersionListAdapter);
}
}
実行結果
BaseAdapter
最後にBaseAdapterを使ってアプリを作ります。
以下のページのような、マテリアルデザインのカラーパレットリストを作ってみます。
https://material.io/design/color/the-color-system.html#tools-for-picking-colors
(少し下に移動したところにある、Pinkのカラーパレットを作ります。)
プロジェクト名を「BaseAdapter」にして以下のプログラムを作っていきます。
color_palette.xml
- ListViewのレイアウト
<?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">
<TextView
android:id="@+id/color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:padding="20dp" />
<TextView
android:id="@+id/color_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginStart="20dp"
android:gravity="center"
android:minHeight="50dp"
android:textSize="16sp" />
<TextView
android:id="@+id/color_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="20dp"
android:gravity="center"
android:minHeight="50dp"
android:textSize="16sp" />
</FrameLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/color_palette_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"/>
</LinearLayout>
ColorPaletteDetail.java
- カラーパレットのデータを定義
package com.example.baseadapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ColorPaletteDetail {
public static List<Map<String, String>> getData() {
String[] colorCode = {
"Pink 50",
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900",
"A100",
"A200",
"A400",
"A700",
};
String[] colorValue = {
"#FCE4EC",
"#F8BBD0",
"#F48FB1",
"#F06292",
"#EC407A",
"#E91E63",
"#D81B60",
"#C2185B",
"#AD1457",
"#880E4F",
"#FF80AB",
"#FF4081",
"#F50057",
"#C51162",
};
String black = "#FF000000";
String white = "#FFFFFFFF";
String[] textColor = {
black,
black,
black,
black,
black,
black,
white,
white,
white,
white,
black,
black,
black,
white,
};
List<Map<String, String>> list = new ArrayList<>();
for (int i = 0; i < colorCode.length; i++) {
Map<String, String> palette = new HashMap<>();
palette.put("colorCode", colorCode[i]);
palette.put("colorValue", colorValue[i]);
palette.put("textColor", textColor[i]);
list.add(palette);
}
return list;
}
}
ColorPaletteAdapter.java
package com.example.baseadapter;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
import java.util.Map;
public class ColorPaletteAdapter extends BaseAdapter {
private LayoutInflater _inflater;
private int _layoutId;
private List<Map<String, String>> _colorPaletteData;
ColorPaletteAdapter(Context context, int layoutId, List<Map<String, String>> colorPaletteData) {
this._inflater = LayoutInflater.from(context);
this._layoutId = layoutId;
this._colorPaletteData = colorPaletteData;
}
@Override
public int getCount() {
return _colorPaletteData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
/**
* AdapterViewで表示するViewを生成するためのメソッド
*
* @param position // 表示するITEMの位置
* @param convertView // 以前まで表示していたView
* @param parent // getViewで生成されたViewの親となるViewGroup
* @return view
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/*
Viewを再利用できるか判定する
nullであればViewを生成する
nullでなければViewの表示だけ変更して使いまわす
*/
if (convertView == null) {
convertView = _inflater.inflate(_layoutId, null);
}
TextView color = convertView.findViewById(R.id.color);
TextView colorCode = convertView.findViewById(R.id.color_code);
TextView colorValue = convertView.findViewById(R.id.color_value);
color.setBackgroundColor(
Color.parseColor(_colorPaletteData.get(position).get("colorValue"))
);
colorCode.setText(
_colorPaletteData.get(position).get("colorCode")
);
colorCode.setTextColor(
Color.parseColor(_colorPaletteData.get(position).get("textColor"))
);
colorValue.setText(
_colorPaletteData.get(position).get("colorValue")
);
colorValue.setTextColor(
Color.parseColor(_colorPaletteData.get(position).get("textColor"))
);
return convertView;
}
}
MainActivity.java
package com.example.baseadapter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Map<String, String>> colorPaletteData = ColorPaletteDetail.getData();
ColorPaletteAdapter colorPaletteAdapter = new ColorPaletteAdapter(
MainActivity.this,
R.layout.color_palette,
colorPaletteData
);
ListView colorPaletteList = findViewById(R.id.color_palette_list);
colorPaletteList.setAdapter(colorPaletteAdapter);
}
}
実行結果
ViewHolderパターンを使う
ViewHolderとは
ViewHolderパターンとは、スクロールするたびにコストが高いfindViewByIdを回避するための仕組みです。
ListViewを生成するときの定石っぽいです。
ViewHolderパターンを使用して先ほど作ったカラーパレットを改修します。
ColorPaletteAdapter.javaを以下のように変更します。
ColorPaletteAdapter.java
package com.example.baseadapter;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
import java.util.Map;
public class ColorPaletteAdapter extends BaseAdapter {
private LayoutInflater _inflater;
private int _layoutId;
private List<Map<String, String>> _colorPaletteData;
ColorPaletteAdapter(Context context, int layoutId, List<Map<String, String>> colorPaletteData) {
this._inflater = LayoutInflater.from(context);
this._layoutId = layoutId;
this._colorPaletteData = colorPaletteData;
}
@Override
public int getCount() {
return _colorPaletteData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
/**
* AdapterViewで表示するViewを生成するためのメソッド
*
* @param position // 表示するITEMの位置
* @param convertView // 以前まで表示していたView(リスト1行分)
* @param parent // getViewで生成されたViewの親となるViewGroup
* @return view
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
View view = convertView;
// Viewを再利用できるか判定する
if (view == null) {
// レイアウトを生成する
view = _inflater.inflate(_layoutId, null);
// Viewオブジェクトを生成する
viewHolder = createViewHolder(view);
// Viewにオブジェクトを保持する
view.setTag(viewHolder);
}
// Viewに保持したオブジェクトを取り出す
viewHolder = (ViewHolder) view.getTag();
viewHolder.color.setBackgroundColor(
Color.parseColor(_colorPaletteData.get(position).get("colorValue"))
);
viewHolder.colorCode.setText(
_colorPaletteData.get(position).get("colorCode")
);
viewHolder.colorCode.setTextColor(
Color.parseColor(_colorPaletteData.get(position).get("textColor"))
);
viewHolder.colorValue.setText(
_colorPaletteData.get(position).get("colorValue")
);
viewHolder.colorValue.setTextColor(
Color.parseColor(_colorPaletteData.get(position).get("textColor"))
);
// returnしたViewは次のgetView()の引数になる
return view;
}
private ViewHolder createViewHolder(View view) {
TextView color = view.findViewById(R.id.color);
TextView colorCode = view.findViewById(R.id.color_code);
TextView colorValue = view.findViewById(R.id.color_value);
return new ViewHolder(color, colorCode, colorValue);
}
private static class ViewHolder {
TextView color;
TextView colorCode;
TextView colorValue;
ViewHolder(TextView color, TextView colorCode, TextView colorValue) {
this.color = color;
this.colorCode = colorCode;
this.colorValue = colorValue;
}
}
}
実行結果は先ほどと同じになります。
Discussion