「問題はどこに!?」
どうでしょうか。こんな感じです。しかしこれだけ見るとすごい簡単にみえます。応用みききそうだし、構造も簡単だし。
しかし考えてみたら、データが少なくそれをチェックする場合よりも、データがスクロールするほどあり、その中からデータ
をチェックしてなにかしたい。というほうが多いのです。
そんな場合、やはりListView。しかもアダプターを使用して自作の行を作ったりしますそれをrowとします。
ここを見るかたなら簡単に作れるでしょう。みなさんの問題も同じかと思います。
そうです、スクロールするほどのデータがあり、rowにチェックボックス部品を設定して、いざ稼働させると・・・
「チェックがキエル!」「へんなとこにチェックハイットル!」「そういやどこにタップ処理かけばいいんだ・・」
みたいな問題がいっぺんにたくさんでます。
問題は沢山の場所でいっぺんに起きています。まず考えるのは色々な問題がどこにどういうふうに起きているかを見えるようにしたい。デバック作業をしたいわけです。で考えるとチェックした時におかしなことになるのなら、チェックした瞬間を見えるようにして変数の変動などみればいいわけです。
さて、ここで問題が起こります。さきほど作成したプログラムでならそれは可能です。がアダプターを使うとrowは別のクラスに作ることが多いですね。row部品はアダプターで設定するということはアダプター側でタップ感知しなければいけません。
ではそうすればいいじゃないか!なのですが 、確かにやってみてもいいかもしれません。やるのが正しいでしょう。んで私もやってみました。するとどうでしょう。そして変数の変動などをみます。結果、ワケワカラン。ナンダコレ。ナンデコウナルンダYO!状態です。
色々なサイトを参考にしました。同じ症状になるので解決してみた!というサイトもありました。で考察してみますと、
タップした時の画面の状態がかならずしもそのチェックボタンを参照して変数に設定されているとは限らない・・・・
なにをいっているんだかわかりませんが、ようは、さきほど作ったプログラムと作ろうとしているプログラムの違いを見てみればわかります。
さきほどのプログラムは、明示的に、的確に、確実に、わかりやすく、3つのデータがそれぞれのCheckBoxに設定していてされています。当たり前ですね。
しかしアダプターを使用すると、よく見ると、1つのCheckBoxをArrayListやList分だけふやしてListViewに登録します。つまり、rowをたくさん勝手に増やすわけです。それぞれのrowに違いはありません。でもCheckBoxはそれぞれ違いがあるはずなので増やした分のCheckBoxを個別に記憶させておき参照すればいいかも・・・
それができたとします。しかし次に問題が、データ分だけのCheckBoxがいっぺんには登録されません。画面にでている分だけ登録されている感じになっています。
そうです。アダプターでは、画面に出現する分しか登録されていないっぽいのです。(つд・)
しかも作られたら別でCheckBoxを登録して、チェックしたら登録分だけすべて参照比較してみたのですが、期待したものと違います。確実に比較できるようにしたのですがそれでもだめ。
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String str = "なし";
int i=0;
while(i < checkbox1.size())
{
if(checkbox1.get(i) == buttonView)
{
str ="同じのアッタヨ!";
makeTost(str+" "+ i+"番目",0);
mk.rm.objList.get(i).check = isChecked;
break;
}
i++;
}
if(i == checkbox1.size()) makeTost(str+" i="+i,0);
}
checkbox1が記憶させたはずのCheckBoxです。これでやると、スクロールなしなら、表示されている分だけの判定は完璧でした。しかしスクロールさせると、以前登録されているCheckBoxと同じものが判定されてしまいます。いわゆる「使い回し」をしているわけです。なので渡された 値 = チェックされた場所のポジション = オブジェクトのポジション とは な ら な い わけです。
しかもですね、ここで想像するとわかると思うのですが、そもそもrowのポジション、いわゆる設定するオブジェクトのポジションを表す、この二つを一致させるためのメソッドを設定していません。rowで一番上のチェックをしてもそれがどのポジションかなんて、このアダプターではわからないのです。
わかるのは、オブジェクトのポジションのものを画面に表示させているということだけです。
なのでまずはこのポジションを保存させておくことが必要になります。
わかりにくいですがたとえば、オブジェクトの1,2,3,4,5番目まで表示させます、となるとCheckBoxは No1,2,3,4,5、を使おう。そしてスクロールして、オブジェクト15,16,17,18、19番目を表示させる時にもNo1,2,3,4,5、を使うということなので、まずは、今どのポジションが表示されているかを設定し、CheckBoxでの直接の判定はせずに、オブジェクトそのもので判定するべきなのかも・・ってことですね。そういう色々かぶっていることが、1個チェックしたはずなのにたくさんチェックされたり、スクロールしたらチェックが消えたりの要因と思われます。なので、チェック状態をオブジェクトごとに保存し、確実にチェックポジションとオブジェクトポジションをつなぎ合わせ保存、そこで更新。が一番いいのかもしれません。
でもこれだと更新のたびに画面が上部に移ってしまうので問題なんですよね・・(つд・)
でも改善点はみえてきました。しかしながらめんどくさそうなので、別の観点でそれを克服しました。
これまたメリットデメリット(リンスではない)があります。考え方は簡単で、
「ListViewタップでチェックを入れる」
これです。すごい簡単でした。作ってみました。
|