"Simple" is "Best"

開発時に詰まったところや 調べた結果日本語での情報が無かったり古かったりした場合に自分用のメモとして高校生(?)が更新していくブログ

CardViewをListViewを使って表示させる

前々からCardViewをいじってみたくて調べていると

入れ子にしたりFor文回したりと意味がわからんことをやっていたので

ListViewで実装してみる

RecyclerViewに実装する方法は日本語であったが

ListViewに実装する方法はすぐに見つからなかったので

書き記しておく

 

目標

こんな感じになればOK

今回は素材を用意するのが面倒くさかったので

ImageViewを単色で塗りつぶした

f:id:bigbuddha:20161023213928p:plain

 

下準備

CardViewはサポートライブラリなので

build.gradeに例のあれを書き足してあげないといけない

compile "com.android.support:cardview-v7:+"

 

必要なクラスやレイアウト

必要なクラスやレイアウトを最初に書き出しておく

  1. MainActivity
  2. CardViewのレイアウト
  3. CardViewに表示させる情報
  4. CustomAdapter

このぐらいかな

3には色の情報(色名と色コード)を保存する

1.MainActivity

とりあえず中身は最後にちょちょっと実装するとして

Layoutを組む

 

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>

私はActivityのLayoutを一から書く派なので、

手元のコードと少し違うかもしれないが、問題はない

 

2.CardViewのLayout

"layout"フォルダを右クリックし、

[New]→[Layout resource file]を選択

名前は"card.xml"にしておいた

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

<android.support.v7.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="140dp"
card_view:cardCornerRadius="4dp"
android:layout_margin="16px">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f0f0f0">

<ImageView
android:id="@+id/image"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_margin="8dp"/>

<TextView
android:id="@+id/text"
android:text="CardView"
android:textSize="30dp"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</LinearLayout>

</android.support.v7.widget.CardView>

</LinearLayout>

CardViewの中にLinearLayoutを突っ込んで

「ImageView・TextView」の順に書いただけ

高さや横幅はお好みで

 

3.CardViewに載せる情報

CardViewに載せたい情報は

  1. 色の名前
  2. 色コード

の2つだけ

private String colorName = "";
private String colorCode  = "";

両方フィールドとしてprivateで宣言して

インスタンス化のときに代入してやる

あとで取り出すのでgetterを忘れずに

public class Card {

private String colorCode = "";
private String colorName = "";

public Card(String colorName, String colorCode) {
this.colorCode = colorCode;
this.colorName = colorName;
}

//↓getter
public String getColorName() {
return this.colorName;
}

public String getColorCode() {
return this.colorCode;
}

}

publicでもいいのかもしれないが

まぁ、無難にprivate

アクセス修飾子の勉強もせんとなぁ

 

4.CustomAdapter

これが一番面倒くさい

が、一番楽しい

public class ColorInfoAdapter extends ArrayAdapter<Card> {

private List<Card> cardList = null;

public ColorInfoAdapter(Context context, int resourceId, List<Card> cardList) {
super(context, resourceId, cardList);

this.cardList = cardList;
}

@Override
public int getCount() {
return cardList.size();
}

@Override
public Card getItem(int position) {
return cardList.get(position);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;

if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.card, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}

final Card CARDINFO = getItem(position);
if (CARDINFO != null) {
viewHolder.getColorName().setText(CARDINFO.getColorName());
viewHolder.getColorImage().setBackgroundColor(Color.parseColor(CARDINFO.getColorCode()));
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(), CARDINFO.getColorName(), Toast.LENGTH_SHORT).show();
}
});
}

return convertView;
}

private class ViewHolder {
private ImageView colorImage = null;
private TextView colorName = null;

public ViewHolder(View view) {
colorImage = (ImageView)view.findViewById(R.id.image);
colorName = (TextView) view.findViewById(R.id.text);
}

public ImageView getColorImage() {
return this.colorImage;
}

public TextView getColorName() {
return this.colorName;
}

}
}

ArrayAdapterを継承してやる

もちろんジェネリクスは先程作ったCard

 

フィールドで

private List cardList = null;

としてやる 

インスタンスはそのまんま

 

次にgetCount・,getItenを記述

何回もView#findViewByIdをすると処理が重いので

維持するためのViewHolderを作成

 フィールドでTextViewとImageViewを宣言してやる

あとはインスタンスで代入

書けたらgetViewをOverride

さっき作ったクラスをfinalで宣言

 

後はいつも通りのnullチェックですな

最後にTagをセットしてやる

そうすることで、あとでもっかい何かするときに

getTagだけで取り戻せる

 

さぁ、ラスト

さっきのクラスを使っていつも通り

setTextなりsetBackgroundColorなりをする

Cardに保存されているColorCodeはString型なんで

Color#parseColorで求めているint型に直してやる

 

おまけ

convertViewはCardViewなので

CardViewに対してOnClickなどが書きたい場合は

convertView.setOnClickListenear(...);

と書いてやる

 

今回は押したCardViewの色名をTost表示するようにした

 

5.MainActivity(再び)

一周回ってMainActivity

今回こそはコードを書く


public class ColorCardListActivity extends AppCompatActivity {

//変数宣言
private List<Card> cardList = null;
private ColorInfoAdapter adapter = null;
private ListView listView = null;

private final String[] COLORCODES = {"black", "red", "blue", "green", "yellow","white" };
private final String[] COLORNAMES = {"黒", "赤", "青", "緑", "黄", "白"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_color_card_list);

listView = (ListView)findViewById(R.id.listView);

cardList = new ArrayList<>();
for (int i = 0; i < COLORNAMES.length; i++) {
cardList.add(new Card(COLORNAMES[i], COLORCODES[i]));
}

adapter = new ColorInfoAdapter(this, R.layout.card, cardList);
listView.setAdapter(adapter);
}
}

 String配列2つは、色の名前とコードを対応させて保存している

Mapでも良かったがなんだかんだ言って面倒くさいので

配列2つにしておく

あとはListにfor文で情報を入れて

そいつをadapterに渡してListViewにセット

以上

f:id:bigbuddha:20161023230112p:plain

無事表示された

Tostもしっかり表示されている