Re: ListView 一行のみの動的背景色変更方法

3,467 views
Skip to first unread message

Wadecom Android Dept.

unread,
Nov 7, 2012, 11:48:37 PM11/7/12
to android-g...@googlegroups.com
tymas 様

Wadecom株式会社 Android事業部の前澤と申します。

ArrayAdapterを継承したカスタムAdapterクラスを作って、
そのクラスでgetViewメソッドをOverrideし、
そこで背景色を設定するのが手っ取り早いかと思います。

以上、お役に立てれば幸いです。


2012年11月8日木曜日 13時30分25秒 UTC+9 tyamas:
アンドロイドのアプリを開発し始めて半年ほどのtymasと申します。初心者の質問で申し訳ありませんが、教えてください。
 
現在、外部機器リーダー(バーコードリーダのようなもの)を使って、検品する在庫管理システムを作っています。
 
今のシステムは
 
①DB("id"と"name"のcolums構成)から、検品物"name"をArrayadapterに加えてListView表示を行います
 
②外部機器リーダーを用いてバーコードからidを読み込んだら、そのタイミングでDBでidとnameをひも付けして、Arrayadapter.remove(name)で、一致したListViewの項目の削除を行う
 
という所まで完成しています。
 
ここから質問なのですが、このListViewからの項目削除という部分を、削除ではなく項目の背景色を変えると処理に変えたいのです。
 
簡単そうだと思っていたのですが、なかなかどうしてその方法を見つけることができません。
Arrayadapter.setBackgroundColor(name)のような処理が出来れば簡単なのになぁと思いつつ、いい処理方法が見つかりません。
 
具体的なコードというより、処理手順のヒントやらどうだろうといった案があれば教えていただきたいです。
 

tyamas

unread,
Nov 8, 2012, 12:28:03 AM11/8/12
to android-g...@googlegroups.com
前澤様、
 
ご回答ありがとうございます。
ご教示いただいた方法についてはすでに試してみております。
参考書のサンプルコードから典型的なArrayadapter拡張コードを作りました。
positionを使った色の変更は試して成功しています。
 
私の目的はバーコードから読みだされるidとひも付けしたString型のobjectを使って、
ListViewからobjectとイコールになる項目を指定して、色付けする事なのですが、そこで詰まっています。
 
お忙しい所恐縮ではございますが、ご回答いただけるとありがたいです。
 
 
class ViewHolder{
 TextView textView;
}
public class ImageAdapter extends ArrayAdapter<String> {
 private LayoutInflater inflater;
 private int color_green;
 
 public ImageAdapter(Context context, List<String> objects){
  super(context,0,objects);
  this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  color_green = context.getResources().getColor(R.color.Green);
 }
 
 @Override
 public View getView(int position, View convertView, ViewGroup parent){
  ViewHolder holder;
  if(convertView == null){
   convertView = inflater.inflate(R.layout.list_row, parent, false);
   holder = new ViewHolder();
   holder.textView = (TextView) convertView.findViewById(R.id.textView1);
   convertView.setTag(holder);
  }
  else{
   holder = (ViewHolder)convertView.getTag();
  }
  
  String data = getItem(position);
  holder.textView.setText(data);
  
  return convertView;
  
 }
}
 
 
 

2012年11月8日木曜日 13時48分37秒 UTC+9 Wadecom Android Dept.:

Wadecom Android Dept.

unread,
Nov 8, 2012, 1:10:28 AM11/8/12
to android-g...@googlegroups.com
tymas 様

> ListViewからobjectとイコールになる項目を指定して
イコールとなる項目を探すのができない、つまりpositionが特定できないという認識でよいでしょうか?

いくつか方法はありますが、
ArrayAdapter<String>
のままでいく場合、まずImageAdapterクラスに色を変えるpositionのリストを用意します。
getViewメソッド内で、指定されたpositionが上記のリストに存在する場合、色を変える、という処理を追加します。
次に、バーコードから新しくidが読み込まれたとき、対応するStringのpositionを、
ListView.getItemAtPositonで探します。これは指定したpositionのStringが取れます。
forループあたりを使って、新しく読み込まれたidに対応するStringと、上記メソッドで返ってきたStringを比較して、
同じならpositionのリストにそのときのpositionをaddします。
これで、色が変わるかと思います。

別の方法ではリストの変わりに、ArrayAdapter<Data>などにして(DataはStringとフラグを持つクラス、もっと言えば、そもそもidも一緒にもてばString比較ではなくid比較ともできる)管理する方法もあります。

いずれにしても、getItemAtPositionがキーワードになるでしょうか。
いかがでしょうか?

2012年11月8日木曜日 14時28分03秒 UTC+9 tyamas:

tyamas

unread,
Nov 8, 2012, 2:06:23 AM11/8/12
to android-g...@googlegroups.com
前澤様、
 
ありがとうございます。本当に助かります。
まだ少しだけ問題がありますが、前進できました。
グローバルでint型TargetPos = -1
TargetPos = ArrayAdapter.getPosition(name);
 
getView(position,convertView,parent)内部で
if(position == TargetPos){
holder.textView.setBackgroundColor(color_green)
}
 
として、読み込んだタグの行に色付けできました。
 
二つ問題がありまして、
ひとつは、getView()
のリストのスクロールに対応できないということです。
画面に5つの項目があるとpositionが
1
2
3
4
5
になりますが、一つ項目をスクロールすると
2
3
4
5
1
になってしまう事です。
理想的には
2
3
4
5
6
にしたいのです…
もうひとつは、同じバーコード2回以上読み込むとたまに関係ないところが反応しているのです。
TargetPosをtoastして確認しているので、埋め込まれているデータに間違いはないのですが、よくわかりません。
 
とりあえず、
前澤様に、ご教示頂いたData型のフラグのほうで挑戦してみたいと思います。

2012年11月8日木曜日 15時10分28秒 UTC+9 Wadecom Android Dept.:

Wadecom Android Dept.

unread,
Nov 8, 2012, 2:15:00 AM11/8/12
to android-g...@googlegroups.com
tymas 様

自分で提示しておいて恐縮なのですが、
たしかにpositionを保持する方法は問題があるかもしれません。。。
おとなしく後者のほうでやったほうがいいかと思います。
(実際、考えてみると、自分が似たような処理をやる際は常に後者のほうでやっていました。。。)

後、補足なのですが、
色を変える部分の処理にはelseもつけて、デフォルトのカラーを入れる処理も書いたほうがよいかと思います。

以上、お役に立てれば幸いです。

tyamas

unread,
Nov 8, 2012, 3:56:42 AM11/8/12
to android-g...@googlegroups.com
前澤様、
 
ご指摘通りelse文をつけて、指摘外の行が色が付いてしまう事を防げました。
positionを保持する方法は見つけきれないです。
 
そこで、ご指摘の後者の方法を試したいのですが、なかなかサンプルに巡り合えません。
class Data{
 String text;
 boolean flag;
 public Data(String text , boolean flag){
this.text = text;
this.flag = flag;
}
 
class ViewHolder{
 TextView textView;
 boolean flag;
}
 
でImageAdapterクラスをData型にしてみたんですが、ここからどうして良いかいまいち思い浮かびません。
多分 ViewHolder 内のフラグを型ではなく、何かしらのクラスにしなければいけないような気がするのですが、
こういった処理の経験があれば、アドバイス頂けないでしょうか?
 
何度も何度も本当にご迷惑おかけいたします。
 

2012年11月8日木曜日 16時15分00秒 UTC+9 Wadecom Android Dept.:

Wadecom Android Dept.

unread,
Nov 8, 2012, 4:26:06 AM11/8/12
to android-g...@googlegroups.com
tymas 様

フラグはViewHolderに持たなくてもいいかと思います。
ViewHolderはその名のとおり、ViewのHolderになるはずなので。

さて、処理ですが、
1.getItemAtPositionで対象のpositionを見つける
2.そのpositionの要素のフラグを書き換える (getItemAtPositionで対象のDataオブジェクトは取れているはずなので、単純にフラグを書き換えられるはず)
3.getViewメソッド内で、getItem(position)でDataオブジェクトをとり、フラグをチェックし、フラグに応じて背景を書き換える

たとえばこのようになるかと思います。

例:
 「Activity側処理」
   ~バーコード読んだ~
   for (iでループ) {
     Data data = (Data) getItemAtPosition(i);
     if (データがバーコードで読んだデータかどうか) {
       data.flag = true;
           }
       }

  「getViewメソッド」
   ~いろいろ処理~
   if (getItem(position).flag) {
     色変更
       } else {
     デフォルトの色セット
       }
       String text = getItem(position).text;
       holder.textView.setText(text);

いかがでしょうか?


2012年11月8日木曜日 17時56分42秒 UTC+9 tyamas:

tyamas

unread,
Nov 9, 2012, 3:58:42 AM11/9/12
to android-g...@googlegroups.com
前澤様、
 
いろいろありがとうございました。
すべて解決できました。
最初は無理かと思いましたが、ここで質問して本当に良かったです。
adapterの拡張についても詳しくなれました。
 
本当にありがとうございました。

2012年11月8日木曜日 18時26分06秒 UTC+9 Wadecom Android Dept.:
Reply all
Reply to author
Forward
0 new messages