一連の画像を検索するアクティビティがあります。画像はギャラリーに表示されます。ユーザーが検索語を入力できる EditText があります。ユーザーが EditText にテキストを入力すると、入力したテキストに従ってギャラリーがフィルター処理されます。
私はSearchResultAdapter extends BaseAdapter implements Filterable
基本的にうまく動作するを作りました。ユーザーがテキストを入力すると、アダプター内のデータがフィルター処理されます。結果をログに記録しました。これまでのところ機能しています。次に、notifyAdapterSetChanged を呼び出して、更新されたデータ セットがギャラリーに表示されるようにします。notifyAdapterSetChanged が実際に呼び出され、ギャラリーがアダプター getCount() を呼び出すときに要求が受信されます (すべての呼び出しをログに記録しました)。
選択を 0 に設定すると、ギャラリーにアイテムがない場合に予想されるように、IndexOutOfBoundsException が原因でアプリケーションがクラッシュします。それでも、ギャラリーには以前にあったすべての画像が表示されます。
問題は、データ セットが空の場合 (つまり、ユーザーがどの画像にも適合しない検索語を入力した場合)、ギャラリーに更新が表示されないことです。ギャラリーは notifyAdapterSetChanged を受け取り、項目数 (0) でアダプターを照会し、スクロール制限を更新します。ギャラリーに表示される画像は更新されません。基本的に表示する画像がないため、画像をスクロールできなくなりましたが、画像はギャラリーから削除されません。ユーザーには、ギャラリーがフリーズしたように見えます。
無効な検索用語が削除されると (つまり、データ セットが空でない場合)、ギャラリーには正しい画像が表示されます。また、アプリケーションを最小化してから再度開いたときのように、特定の条件下では、ギャラリーに空のリストが表示されます。ただし、ギャラリーが空になる条件を再現できません(アプリケーションの最小化/再開は別として):
ギャラリーを無効にして requestLayout() しようとしましたが、役に立ちません。ギャラリーに表示された画像のリストを更新させる方法を知っている人はいますか?
ユーザーが画像に一致しないテキストを入力した場合のログ メッセージは次のとおりです。
[SearchResultAdapter.SearchFilter] Results: 0
[SearchResultAdapter.SearchFilter] called notifyDataSetChanged()
[SearchResultAdapter.getCount()] getCount called: dateset size 0
[SearchResultAdapter.getCount()] getCount called: dateset size 0
データ セットのサイズに応じて、ギャラリーによってアダプターが実際にどのように呼び出されるかに注目してください。
アクティビティの初期化コード:
final Gallery gallery = (Gallery) findViewById(R.id.search_results);
final SearchResultAdapter adapter = new SearchResultAdapter(this, gallery);
gallery.setAdapter(adapter);
EditText searchField = (EditText) findViewById(R.id.search_searchfield);
searchField.addTextChangedListener(new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{
// TODO unhardcode criterion
adapter.putFilterTerm(SearchCriteria.OFFERING, s.toString());
adapter.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// do nothing
}
@Override
public void afterTextChanged(Editable s)
{
// do nothing
}
});
そして SearchResultAdapter (重要でない行は省略されています):
public class SearchResultAdapter extends BaseAdapter implements Filterable
{
private Context context;
private Filter filter;
public void putFilterTerm(SearchCriteria key, String value)
{
filterTerms.put(key, value);
}
public boolean containsFilterTerm(SearchCriteria key)
{
return filterTerms.containsKey(key);
}
public String getFilterTerm(SearchCriteria key)
{
return filterTerms.get(key);
}
List<PageContainer> completeList = new ArrayList<PageContainer>();
List<PageContainer> currentList = new ArrayList<PageContainer>();
Map<SearchCriteria, String> filterTerms = new HashMap<SearchCriteria, String>();
View view;
public SearchResultAdapter(Context context, View gallery)
{
this.context = context;
this.view = gallery;
for (ContentPropertyContainer page : Model.getInstance()
.getRootContainer().getChildren())
{
completeList.add((PageContainer) page);
}
currentList.addAll(completeList);
}
@Override
public int getCount()
{
return currentList.size();
}
@Override
public Object getItem(int position)
{
return currentList.get(position);
}
@Override
public long getItemId(int position)
{
PageContainer item = currentList.get(position);
for (int i = 0; i < completeList.size(); ++i)
{
if (completeList.get(i) == item)
{
return i;
}
}
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View listview = convertView;
// Code left out here tries to reuse the convertView
// like Romain Guy said in a Google I/O Talk
return listview;
}
private class ResultList
{
ResultList(List<PageContainer> results)
{
this.results = results;
}
List<PageContainer> results;
}
@Override
public Filter getFilter()
{
// implements Filterable
if (filter == null)
{
filter = new SearchFilter();
}
return filter;
}
private class SearchFilter extends Filter
{
SearchFilter()
{
// do nothing, needed for visibility
}
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults();
// Code left out here filters the list
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
{
if (results == null)
{
return;
}
if (results.values instanceof ResultList)
{
currentList = ((ResultList) (results.values)).results;
notifyDataSetChanged();
}
}
}
}
編集: ギャラリーの可視性を非表示に設定してから再度表示に設定すると、問題が解決しました。
view.post(new Runnable()
{
@Override
public void run()
{
view.setVisibility(View.INVISIBLE);
view.setVisibility(View.VISIBLE);
}
});
より良い解決策はありますか?これは私にはかなりハックに思えます。