CardViewをListViewを使って表示させる
前々からCardViewをいじってみたくて調べていると
入れ子にしたりFor文回したりと意味がわからんことをやっていたので
ListViewで実装してみる
RecyclerViewに実装する方法は日本語であったが
ListViewに実装する方法はすぐに見つからなかったので
書き記しておく
目標
こんな感じになればOK
今回は素材を用意するのが面倒くさかったので
ImageViewを単色で塗りつぶした
下準備
CardViewはサポートライブラリなので
build.gradeに例のあれを書き足してあげないといけない
compile "com.android.support:cardview-v7:+"
必要なクラスやレイアウト
必要なクラスやレイアウトを最初に書き出しておく
- MainActivity
- CardViewのレイアウト
- CardViewに表示させる情報
- 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に載せたい情報は
- 色の名前
- 色コード
の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にセット
以上
無事表示された
Tostもしっかり表示されている