[Android Studio]チェックボックス付ListviewでSearchviewによるフィルターがかからない
- 評価
- クリップ 0
- VIEW 1,114
タイトルの通りです。listviewに並んだ要素それぞれにチェックボックス(複数選択可)があり、チェックを入れたものの配列を保存する、というものに、searchviewによる検索機能を足そうとしてみました。(検索を前方一致以外にするにはadapterのgetFilterとかをいじる、と見たので、そうしました。)その結果、チェックを一つも打っていない状態なら検索が正常に動作するのに、1つでもチェックが入っている状態からは検索ワードを打ち込んでも反応しない、という状況になってしまいました。
public class SelectActivity extends AppCompatActivity {
private static ArrayList<Card> targetList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select);
Toolbar toolbar = findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
toolbar.setTitle(R.string.choose_cards);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
setList();
searchView = findViewById(R.id.searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
@Override
public boolean onQueryTextChange(String s) {
if (TextUtils.isEmpty(s)) {
listView.clearTextFilter();
} else {
listView.setFilterText(s.toString());
}
return true;
}
});
@Override
public void onResume(){
super.onResume();
checkUpdate();
}
@Override
public void onPause(){
super.onPause();
resisterTargetList();
}
private void setList(){
MyArrayAdapter adapter = new MyArrayAdapter(
this, android.R.layout.simple_list_item_multiple_choice, new ArrayList<String>(Arrays.asList(MainActivity.cardNames)), targetList);
listView = findViewById(R.id.listview);
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
listView.setDivider(null);
}
public static void checkUpdate(){
for(Card card: targetList){
int id = Arrays.asList(MainActivity.cardNames).indexOf(card.getName());
listView.setItemChecked(id, true);
}
}
public static void resisterTargetList(){
SparseBooleanArray array = listView.getCheckedItemPositions();
targetList.clear();
for(int i = 0; i < array.size(); i++){
int at = array.keyAt(i);
if(array.get(at)){
targetList.add(MainActivity.cardList.get(at));
}
}
}
}
public class MyArrayAdapter extends ArrayAdapter {
private ArrayList<String> cardNames;
private ArrayList<Card> targetList;
private TestFilter _filter;
public MyArrayAdapter(Context context, int resourceId, ArrayList<String> cardNames, ArrayList<Card> targetList){
super(context, resourceId, cardNames);
this.cardNames = (ArrayList<String>)cardNames.clone();
this.targetList = targetList;
this.otherList = otherList;
}
@Override
public boolean areAllItemsEnabled(){
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
View view = super.getView(position, convertView, parent);
return view;
}
@Override
public Filter getFilter() {
if(_filter == null) {
_filter = new TestFilter();
}
return _filter;
}
public class TestFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
SelectActivity.resisterTargetList();
ArrayList<String> items = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
items = new ArrayList<String>(cardNames);
} else {
// getCount及びgetItemはAdapterのメソッド
for(int i = 0, size = cardNames.size(); i < size; i++) {
String data = cardNames.get(i);
if(data.contains(constraint)) {
items.add(data);
}
}
}
FilterResults r = new FilterResults();
r.count = items.size();
r.values = items;
SelectActivity.checkUpdate();
return r;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
// Adapterのメソッドでデータの内容を更新する
if(results != null && results.count > 0) {
List<String> items = (List<String>) results.values;
clear();
addAll(items);
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
追記
MainActivityにあるcardList(Arraylist<Card>)は、idとnameを持つCardクラスのオブジェクトの集合で、このnameのみのstring配列がcardNamesです。selectActivityから離れるときにチェックを入れていたところのCardオブジェクトの配列をtargetList(Arraylist<Card>)に入れようとしています。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
Filterクラスの performFiltering メソッドは、メインスレッド以外のスレッド上で呼び出されるので、この中でUIに関する操作をしてはいけません。実際に動かしたことはないので確かなことは言えませんが、UIを操作する順番がおかしくなってしまいフィルターが効いていないように見えるのだと思います。チェックが1つでもされている時にのみ現象が起こるのは、checkUpdate()
内の処理が行われるのがチェックがされている時だからです。
まずはperformFilteringの中で呼んでいる SelectActivity.resisterTargetList();
と SelectActivity.checkUpdate();
を無くす方向で修正してください。publishResultsがフィルターした結果を元にUIを操作するためのメソッドなので、そちらの中に移せば意図する動作になると思います。
余談ですが、外部からアクセスできるようにするために変数やメソッドをstaticで宣言するのはオブジェクト指向の考え方に反するものであり、あまりオススメできません。(いわゆるstaticおじさんというやつです)そのあたりも修正しておいた方が今後バグを起こす可能性を減らせてよいと思います。
補足: staticを使わない方法について
いくらかやり方はありますが、簡単なのはActivityの中でMyArrayAdapterを継承したクラスを作り、そこでFilterを実装するものです。
private void setList(){
MyArrayAdapter adapter = new MyArrayAdapter(...) {
private Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
...
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// ここならActiviyのメソッドが呼べる
}
};
@NotNull
@Override
public Filter getFilter() {
return filter;
}
};
...
listView.setAdapter(adapter);
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
kakajika
2018/08/08 17:14
MyArrayAdapterのソースコードも貼っていただいた方が回答がつきやすいかと思います。
68kjo_pzdr
2018/08/08 18:06
ご指摘ありがとうございます。貼り忘れていました。
kakajika
2018/08/10 16:39
うーん、色々とツッコミどころがある感じですが、とりあえずMyArrayAdapterのソースを全部載せてください。targetListやcardNamesという変数とその扱いが怪しいですが、今のご質問のソースではそれが何なのか判断するのは厳しいです。