Blue note.

Android開発勉強ブログ。指摘ありましたらコメントください。

基本的なRecyclerViewを作る

Poplation Ranking

  • 人口ランキングをRecyclerViewで表示、チェックボックスで地域絞り込み
  • こんなものを作る
    f:id:mdvpo:20181118170258p:plain
    PoplationRanking

構成

  • MainActivity
  • RankAdapter : adpter
  • Data : データ配列を保持
  • activity_main
  • ranking_list : RecyclerView内部のView

実装方法

app > build.gradle

  • ライブラリを追加
  • dependencies {} implementation 'com.android.support:recyclerview-v7:28.0.0'

activity_main.xml

  • RecyclerViewを1つ用意
  <android.support.v7.widget.RecyclerView
      android:id="@+id/rankList"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
  </android.support.v7.widget.RecyclerView>

ranking_list.xml

  • RecyclerViewで使用する1列分のviewを作成
  • {順位、国名、人口数、地域}の4つを横並びで表示したいので以下のようにする。
  • 国ごとのテキストの長さにかかわらず4つの幅を固定させたいのでlayout_weightを使う
    • 順位1,国名4,人口2,地域2 でとりあえず割り振る
    • このときlayout_width="0dp"にしないとlayout_weightが効かない
<?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="wrap_content"
    android:orientation="horizontal"
    android:padding="4dp">
    <TextView
        android:id="@+id/rank"
        android:layout_weight="1"
        android:layout_width="0sp"
        android:layout_height="wrap_content"
        android:textColor="#000000"/>
    <TextView
        android:id="@+id/country"
        android:layout_weight="4"
        android:layout_gravity="start"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="#000000"/>
    <TextView
        android:id="@+id/poplation"
        android:layout_weight="2"
        android:layout_gravity="start"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="#000000"/>
    <TextView
        android:id="@+id/area"
        android:layout_gravity="start"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="#000000"/>
</LinearLayout>

参考 layout_weightの使い方 - ASとか

Data.java

  • 人口を載せてくれているサイトがあったのでそれを見て手打ちして文字列の二次元配列String[][]にする
  • 2/3が数値データなのにこのやり方ってどーなのと思いつつも最善策がわからずとりあえずこれで...
  • エリアの名前を毎回入力するのが手間なのでエリア配列areaArrayを作って番号を割り振る、data配列にはエリア名ではなくエリア番号を入力
  • エリア番号を確認しながら記入する作業面倒くさくて時間短縮できた気がしなかった

参考 世界の人口ランキング - 世界経済のネタ帳

public class Data {
    public static String[][]  data = {
            {"Chinese","1390","0" },
            {"India","1316","0" },
            ~~~省略~~
    };
}
    public static String[] areaArray ={
      "アジア","北米","中南米","ヨーロッパ","オセアニア","中東","アフリカ"
    };

RankAdapter.java

  • RecyclerViewにセットするためのAdapterを用意
  • ざっとこんな感じ
public class RankAdapter extends RecyclerView.Adapter<RankAdapter.ViewHolder> {

    String[][] array;
    
    class ViewHolder extends RecyclerView.ViewHolder{
        TextView rank;
        TextView country;
        TextView poplation;
        TextView area;

        ViewHolder(View view){
            super(view);
            rank = view.findViewById(R.id.rank);
            country = view.findViewById(R.id.country);
            poplation = view.findViewById(R.id.poplation);
            area = view.findViewById(R.id.area);
        }
    }
    RankAdapter(String[][] _array){
        array = _array;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
        View view = layoutInflater.inflate(R.layout.ranking_list, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
        viewHolder.rank.setText("No."+ String.valueOf(i+1));
        viewHolder.country.setText(array[i][0]);
        viewHolder.poplation.setText(array[i][1]);
        viewHolder.area.setText(Data.areaArray[Integer.parseInt(array[i][2])]);
    }

    @Override
    public int getItemCount() {
        return array.length;
    }
}
  • ViewHolder
    • リスト一行ごとにfindViewByIdしてたら重くなるけどviewHolderで指定しておけば1回で済んで高速化できる、という代物らしい
    • データを渡すview(今回はすべてTextView)の指定を行っておく

参考

ViewHolderを使わないでListViewを高速化する - Qiita Android ListViewとAdapterとViewHolder - うちなー えんじにあ ぶろぐ

  • onCreateViewHolder
    • Layoutの設定
  • onBindViewHolder

    • 各viewにデータをセット
  • getItemCount

    • ここの戻り値分onCreateViewHolderonBindViewHolderが処理される
    • 最初、処理ちゃんと描いたのに何も表示されない!なんで!とおもったらここがreturn 0;になってた...
    • とりあえずデータを全部突っ込んどいても、条件でデータ数変えられるのは地味に便利そう