質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2174閲覧

[Android Studio]チェックボックス付ListviewでSearchviewによるフィルターがかからない

68kjo_pzdr

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2018/08/06 13:20

編集2018/08/10 11:53

タイトルの通りです。listviewに並んだ要素それぞれにチェックボックス(複数選択可)があり、チェックを入れたものの配列を保存する、というものに、searchviewによる検索機能を足そうとしてみました。(検索を前方一致以外にするにはadapterのgetFilterとかをいじる、と見たので、そうしました。)その結果、チェックを一つも打っていない状態なら検索が正常に動作するのに、1つでもチェックが入っている状態からは検索ワードを打ち込んでも反応しない、という状況になってしまいました。

SelectActivity

1public class SelectActivity extends AppCompatActivity { 2 private static ArrayList<Card> targetList; 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_select); 8 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_select); 11 12 Toolbar toolbar = findViewById(R.id.tool_bar); 13 setSupportActionBar(toolbar); 14 toolbar.setTitle(R.string.choose_cards); 15 16 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 17 getSupportActionBar().setHomeButtonEnabled(true); 18 19   setList(); 20 21 searchView = findViewById(R.id.searchView); 22 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 23 @Override 24 public boolean onQueryTextSubmit(String s) { 25 return false; 26 } 27 @Override 28 public boolean onQueryTextChange(String s) { 29 30 if (TextUtils.isEmpty(s)) { 31 listView.clearTextFilter(); 32 } else { 33 listView.setFilterText(s.toString()); 34 } 35 return true; 36 } 37 }); 38 39 @Override 40 public void onResume(){ 41 super.onResume(); 42 checkUpdate(); 43 } 44 @Override 45 public void onPause(){ 46 super.onPause(); 47 resisterTargetList(); 48 } 49 50 private void setList(){ 51 MyArrayAdapter adapter = new MyArrayAdapter( 52 this, android.R.layout.simple_list_item_multiple_choice, new ArrayList<String>(Arrays.asList(MainActivity.cardNames)), targetList); 53 54 listView = findViewById(R.id.listview); 55 listView.setAdapter(adapter); 56 listView.setTextFilterEnabled(true); 57 listView.setDivider(null); 58 } 59 60 public static void checkUpdate(){ 61 for(Card card: targetList){ 62 int id = Arrays.asList(MainActivity.cardNames).indexOf(card.getName()); 63 listView.setItemChecked(id, true); 64 } 65 } 66 67 public static void resisterTargetList(){ 68 SparseBooleanArray array = listView.getCheckedItemPositions(); 69 targetList.clear(); 70 71 for(int i = 0; i < array.size(); i++){ 72 int at = array.keyAt(i); 73 if(array.get(at)){ 74 targetList.add(MainActivity.cardList.get(at)); 75 } 76 } 77 } 78}

MyArrayAdapter

1 public class MyArrayAdapter extends ArrayAdapter { 2 3 private ArrayList<String> cardNames; 4 private ArrayList<Card> targetList; 5 6 private TestFilter _filter; 7 8 public MyArrayAdapter(Context context, int resourceId, ArrayList<String> cardNames, ArrayList<Card> targetList){ 9 super(context, resourceId, cardNames); 10 this.cardNames = (ArrayList<String>)cardNames.clone(); 11 this.targetList = targetList; 12 this.otherList = otherList; 13 } 14 15 @Override 16 public boolean areAllItemsEnabled(){ 17 return true; 18 } 19 20 @Override 21 public View getView(int position, View convertView, ViewGroup parent){ 22 View view = super.getView(position, convertView, parent); 23 return view; 24 } 25 26 @Override 27 public Filter getFilter() { 28 if(_filter == null) { 29 _filter = new TestFilter(); 30 } 31 return _filter; 32 } 33 34 public class TestFilter extends Filter { 35 36 @Override 37 protected FilterResults performFiltering(CharSequence constraint) { 38 39 SelectActivity.resisterTargetList(); 40 41 ArrayList<String> items = new ArrayList<>(); 42 if (constraint == null || constraint.length() == 0) { 43 items = new ArrayList<String>(cardNames); 44 } else { 45 // getCount及びgetItemはAdapterのメソッド 46 for(int i = 0, size = cardNames.size(); i < size; i++) { 47 String data = cardNames.get(i); 48 if(data.contains(constraint)) { 49 items.add(data); 50 } 51 } 52 } 53 54 FilterResults r = new FilterResults(); 55 r.count = items.size(); 56 r.values = items; 57 SelectActivity.checkUpdate(); 58 return r; 59 } 60 61 @SuppressWarnings("unchecked") 62 @Override 63 protected void publishResults(CharSequence constraint, Filter.FilterResults results) { 64 65 // Adapterのメソッドでデータの内容を更新する 66 if(results != null && results.count > 0) { 67 68 List<String> items = (List<String>) results.values; 69 clear(); 70 addAll(items); 71 72 notifyDataSetChanged(); 73 } else { 74 notifyDataSetInvalidated(); 75 } 76 } 77 } 78}

追記
MainActivityにあるcardList(Arraylist<Card>)は、idとnameを持つCardクラスのオブジェクトの集合で、このnameのみのstring配列がcardNamesです。selectActivityから離れるときにチェックを入れていたところのCardオブジェクトの配列をtargetList(Arraylist<Card>)に入れようとしています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kakajika

2018/08/08 08:14

MyArrayAdapterのソースコードも貼っていただいた方が回答がつきやすいかと思います。
68kjo_pzdr

2018/08/08 09:06

ご指摘ありがとうございます。貼り忘れていました。
kakajika

2018/08/10 07:39

うーん、色々とツッコミどころがある感じですが、とりあえずMyArrayAdapterのソースを全部載せてください。targetListやcardNamesという変数とその扱いが怪しいですが、今のご質問のソースではそれが何なのか判断するのは厳しいです。
guest

回答1

0

ベストアンサー

Filterクラスの performFiltering メソッドは、メインスレッド以外のスレッド上で呼び出されるので、この中でUIに関する操作をしてはいけません。実際に動かしたことはないので確かなことは言えませんが、UIを操作する順番がおかしくなってしまいフィルターが効いていないように見えるのだと思います。チェックが1つでもされている時にのみ現象が起こるのは、checkUpdate() 内の処理が行われるのがチェックがされている時だからです。

まずはperformFilteringの中で呼んでいる SelectActivity.resisterTargetList();SelectActivity.checkUpdate(); を無くす方向で修正してください。publishResultsがフィルターした結果を元にUIを操作するためのメソッドなので、そちらの中に移せば意図する動作になると思います。

余談ですが、外部からアクセスできるようにするために変数やメソッドをstaticで宣言するのはオブジェクト指向の考え方に反するものであり、あまりオススメできません。(いわゆるstaticおじさんというやつです)そのあたりも修正しておいた方が今後バグを起こす可能性を減らせてよいと思います。

補足: staticを使わない方法について

いくらかやり方はありますが、簡単なのはActivityの中でMyArrayAdapterを継承したクラスを作り、そこでFilterを実装するものです。

java

1private void setList(){ 2 MyArrayAdapter adapter = new MyArrayAdapter(...) { 3 private Filter filter = new Filter() { 4 @Override 5 protected FilterResults performFiltering(CharSequence constraint) { 6 ... 7 } 8 9 @Override 10 protected void publishResults(CharSequence constraint, FilterResults results) { 11 // ここならActiviyのメソッドが呼べる 12 } 13 }; 14 15 @NotNull 16 @Override 17 public Filter getFilter() { 18 return filter; 19 } 20 }; 21 22 ... 23 listView.setAdapter(adapter); 24}

投稿2018/08/20 09:40

編集2018/08/22 15:23
kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

68kjo_pzdr

2018/08/22 11:46

大変有難うございました!仰る通りpublishResultsの中にUI処理を移したら正常に動きました。 staticについては、activityクラスのインスタンスは生成出来ないと思うのですが、それ以外で他クラスから参照する方法が思いつきませんでした…。例えばどのように出来るか補足して頂けると大変助かります。
kakajika

2018/08/22 15:25

補足を追記しておきました。
68kjo_pzdr

2018/08/22 22:45

参考になります!誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問