您的位置:首页 > 其它

解决使用SearchView和Filter时出现搜索词悬浮窗问题

2013-10-31 16:18 567 查看
在andorid开发中,有时候会遇到这样的情况,界面中有一个SearchView,需要在其中输入内容来过滤ListView中的内容

大致的做法如下:

1. ListView的adpter实现Filterable接口

/**
* Adapter for exam/project list in session view.
*
*/
public class SessionSimpleAdapter extends SimpleAdapter implements Filterable {

private static final String TAG = "SessionSimpleAdapter";
private final Context mContext;

/**
* point to the data associated with the ListView, this should not be
* changed, otherwise method "notifyDatasetChanged" would make no sense.
*/
private ArrayList<HashMap<String, String>> data;

/**
* store the whole data, be used to search matched data.
*/
private ArrayList<HashMap<String, String>> mOriginData;
private int resource;
private String[] from;
private int[] to;

private MyFilter myFilter;

public SessionSimpleAdapter(Context context,
List<? extends Map<String, ?>> data) {
super(context, data, 0, new String[] {}, new int[] {});
this.mContext = context;
this.data = (ArrayList<HashMap<String, String>>) data;
this.mOriginData = new ArrayList<HashMap<String, String>>(this.data);
}

class ViewHolder {
ImageView icon;
TextView[] showTv;
ProgressBar downloadProgressBar;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
HashMap<String, String> map = data.get(position);
String type = map.get("type");
String uuid = map.get("uuid");
String title = map.get("name");
String description = map.get("description");

final ViewHolder holder;
if (convertView == null) {
Log.d(TAG, "convertView == null");
holder = new ViewHolder();

convertView = inflater.inflate(R.layout.material_item, null);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);

holder.showTv = new TextView[2];
holder.showTv[0] = (TextView) convertView.findViewById(R.id.name);
holder.showTv[1] = (TextView) convertView
.findViewById(R.id.description);

convertView.setTag(holder);
} else {

Log.d(TAG, "convertView != null");
holder = (ViewHolder) convertView.getTag();
}

if (type.equals("p")) {
holder.icon.setImageResource(R.drawable.project_icon);
holder.showTv[0].setText("Project - " + map.get("name"));
// need to clear the listener which might be associated with the
// view last time.
convertView.setOnClickListener(null);

} else {
holder.icon.setImageResource(R.drawable.exam_icon);
holder.showTv[0].setText("Exam - " + map.get("name"));

convertView.setOnClickListener(mExamListener);
}
holder.showTv[1].setText(map.get("description"));

return convertView;

}

@Override
public Filter getFilter() {
if (myFilter == null) {
myFilter = new MyFilter();
}
return myFilter;
}

class MyFilter extends Filter {

@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();

// filter the origin data to get result.
ArrayList<HashMap<String, String>> newResult = new ArrayList<HashMap<String, String>>();
for (Iterator iterator = mOriginData.iterator(); iterator.hasNext();) {
HashMap<String, String> hashMap = (HashMap<String, String>) iterator
.next();
if (hashMap.get("name").contains(constraint)
|| hashMap.get("description").contains(constraint)) {
newResult.add(hashMap);
}
}
results.values = newResult;
results.count = newResult.size();
return results;
}

@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
data.clear();
data.addAll((Collection<? extends HashMap<String, String>>) results.values);
Log.d(TAG, "search over, size:" + data.size());
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}

}
}

private OnClickListener mExamListener = new OnClickListener() {

@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(mContext, ExamActivity.class);
mContext.startActivity(intent);
}
};
}

实现Filterable接口后该列表中的数据就可以按照规则过滤了。

2. 在Activity中为SearchView设定SearchView.OnQueryTextListener监听,在其回调方法中直接用如下代码实现对adapter数据源的过滤

@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
mMaterialListView.clearTextFilter();
} else {
mMaterialListView.setFilterText(newText.toString());
}
return true;
}


这样用户在SearchView中输入string时,就可以按照之前adpter中设定的过滤规则来过滤,同时更新视图(在 Filter的publishResult方法中实现)。

上述的代码有一个问题:当用户在SearchView中输入字符时,确实可以过滤并更新列表,不过界面中始终有一个悬浮窗在显示过滤字符,在SearchView等类中均没有发现相关的方法去屏蔽掉该悬浮窗。

解决方法很简单,将过滤方法的调用从ListView交给filter本身就可以:

@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
mMaterialListView.clearTextFilter();
} else {
// below code committed will lead to a popup window when entering
// search word, use the next line to work around the problem.
// mMaterialListView.setFilterText(newText.toString());
adapter.getFilter().filter(newText);
}
return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐