Android 自定义Listadapter可筛选无结果
我正在为这个问题挣扎一段时间。我正在用edittext建立一个可过滤列表。列表最初填充得很好,但一旦我在edittext字段中键入了一些内容。整个列表将消失,并且不会返回任何结果。以下是我的代码 注意:我的代码主要基于sacoskun的 ThreedListViewActivity.javaAndroid 自定义Listadapter可筛选无结果,android,filter,arraylist,hashmap,custom-adapter,Android,Filter,Arraylist,Hashmap,Custom Adapter,我正在为这个问题挣扎一段时间。我正在用edittext建立一个可过滤列表。列表最初填充得很好,但一旦我在edittext字段中键入了一些内容。整个列表将消失,并且不会返回任何结果。以下是我的代码 注意:我的代码主要基于sacoskun的 ThreedListViewActivity.java public class ThreedListViewActivity extends ActionBarActivity { // All static variables static final St
public class ThreedListViewActivity extends ActionBarActivity
{
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
ThreedListAdapterFilterable adapter;
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
EditText filterText = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.threed_listview);
setTitle(R.string.view_3d);
list=(ListView)findViewById(R.id.list);
adapter = new ThreedListAdapterFilterable(this, songsList);
new MyAsyncTask().execute();
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
adapter.getFilter().filter(s.toString());
}
};
public class MyAsyncTask extends AsyncTask<Void,Void,Void>{
private final ProgressDialog dialog=new ProgressDialog(ThreedListViewActivity.this);
@Override
protected Void doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
return null;
}
@Override
protected void onPreExecute()
{
dialog.setMessage("Loading ...");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected void onPostExecute(Void result)
{
if(dialog.isShowing() == true)
{
dialog.dismiss();
}
// Getting adapter by passing xml data ArrayList
list.setAdapter(adapter);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_items, menu);
return true;
}
}
ThreedListAdapterFilterable.java
public class ThreedListAdapterFilterable extends BaseAdapter implements Filterable {
private Activity activity;
ArrayList<HashMap<String, String>> mDataShown;
ArrayList<HashMap<String, String>> mAllData;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public ThreedListAdapterFilterable(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
mDataShown= (ArrayList<HashMap<String, String>>) d;
mAllData = (ArrayList<HashMap<String, String>>) mDataShown.clone();
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return mDataShown.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.threed_listrow, null);
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView artist = (TextView)vi.findViewById(R.id.artist); // artist name
TextView duration = (TextView)vi.findViewById(R.id.duration); // duration
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
HashMap<String, String> song = new HashMap<String, String>();
song = mDataShown.get(position);
// Setting all values in listview
title.setText(song.get(ThreedListViewActivity.KEY_TITLE));
artist.setText(song.get(ThreedListViewActivity.KEY_ARTIST));
duration.setText(song.get(ThreedListViewActivity.KEY_DURATION));
imageLoader.DisplayImage(song.get(ThreedListViewActivity.KEY_THUMB_URL), thumb_image);
return vi;
}
public Filter getFilter() {
Filter nameFilter = new Filter() {
@SuppressWarnings("unchecked")
@Override
public String convertResultToString(Object resultValue) {
return ((HashMap<String, String>)(resultValue)).get(ThreedListViewActivity.KEY_TITLE);
}
@Override
protected FilterResults performFiltering(CharSequence s) {
if(s != null)
{
ArrayList<HashMap<String, String>> tmpAllData = mAllData;
ArrayList<HashMap<String, String>> tmpDataShown = mDataShown;
tmpDataShown.clear();
for(int i = 0; i < tmpAllData.size(); i++)
{
if(tmpAllData.get(i).get(ThreedListViewActivity.KEY_TITLE).toLowerCase().startsWith(s.toString().toLowerCase()))
{
tmpDataShown.add(tmpAllData.get(i));
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = tmpDataShown;
filterResults.count = tmpDataShown.size();
return filterResults;
}
else
{
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence s,
FilterResults results) {
if(results != null && results.count > 0)
{
notifyDataSetChanged();
}
}};
return nameFilter;
}
}
编辑:
这是一个更新的适配器,将筛选我的列表。但是,当我将输入文本中的文本退格时,它不会更新我的列表
public class ProjectListAdapter extends BaseAdapter implements Filterable{
private Activity activity;
ArrayList<HashMap<String, String>> mDataShown;
ArrayList<HashMap<String, String>> mAllData;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
HashMap<String, String> song = new HashMap<String, String>();
ArrayList<HashMap<String, String>> filteredItems;
public ProjectListAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
mDataShown= (ArrayList<HashMap<String, String>>) d;
mAllData = (ArrayList<HashMap<String, String>>) mDataShown.clone();
filteredItems = mDataShown;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mDataShown.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi;
if(convertView==null){
vi=new View(activity);
vi = inflater.inflate(R.layout.recents_listrow, null);
}else{
vi = (View)convertView;
}
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView artist = (TextView)vi.findViewById(R.id.company); // artist name
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
title.setText(filteredItems.get(position).get(RecentsFragment.KEY_TITLE));
artist.setText(filteredItems.get(position).get(RecentsFragment.KEY_COMPANY));
imageLoader.DisplayImage(filteredItems.get(position).get(RecentsFragment.KEY_THUMB_URL), thumb_image);
return vi;
}
public Filter getFilter() {
Filter nameFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if(constraint != null && constraint.toString().length() > 0) {
constraint = constraint.toString().toUpperCase();
ArrayList<HashMap<String, String>> filt = mDataShown;
ArrayList<HashMap<String, String>> tmpItems = mAllData;
filt.clear();
for(int i = 0; i < tmpItems.size(); i++) {
if(tmpItems.get(i).get(RecentsFragment.KEY_TITLE).toLowerCase().startsWith(constraint.toString().toLowerCase()))
{
filt.add(tmpItems.get(i));
}
}
FilterResults filterResults = new FilterResults();
filterResults.count = filt.size();
filterResults.values = filt;
return filterResults;
}else{
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mDataShown = (ArrayList<HashMap<String, String>>)results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return nameFilter;
}
}
我正在尝试实现的列表片段:RecentsFragment
public class RecentsFragment extends ListFragment {
// All static variables
static final String URL = "http://www.sundancepost.com/ivue/projects.xml";
// XML node keys
static final String KEY_PROJECT = "project"; // parent node
static final String KEY_TITLE = "title";
static final String KEY_COMPANY = "company";
static final String KEY_THUMB_URL = "thumb_url";
int mCurCheckPosition = 0;
ListView list;
ProjectListAdapter adapter;
ArrayList<HashMap<String, String>> projectsList = new ArrayList<HashMap<String, String>>();
EditText filterText = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recents_list, container, false);
list = (ListView)view.findViewById(android.R.id.list);
filterText = (EditText)view.findViewById(R.id.filter_box);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(null == savedInstanceState){
ConnectivityManager cMgr = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
if (cMgr.getActiveNetworkInfo() != null && cMgr.getActiveNetworkInfo().isConnectedOrConnecting()) {
new MyAsyncTask().execute();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Please check your internet connection");
builder.setTitle("Failed to download resources");
builder.setCancelable(false);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
return;
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
adapter = new ProjectListAdapter(getActivity(), projectsList);
list.requestFocus();
list.setTextFilterEnabled(true);
filterText.addTextChangedListener(filterTextWatcher);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtra("title",projectsList.get(position).get(KEY_TITLE));
intent.putExtra("company", projectsList.get(position).get(KEY_COMPANY));
startActivity(intent);
}
});
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putInt("workaround", mCurCheckPosition);
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
adapter.getFilter().filter(s);
}
};
@Override
public void onDestroy() {
super.onDestroy();
filterText.removeTextChangedListener(filterTextWatcher);
}
public class MyAsyncTask extends AsyncTask<Void,Void,Void>{
private final ProgressDialog recents_dialog = new ProgressDialog(getActivity());
@Override
protected Void doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_PROJECT);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_COMPANY, parser.getValue(e, KEY_COMPANY));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
projectsList.add(map);
}
return null;
}
@Override
protected void onPreExecute()
{
projectsList.clear();
recents_dialog.setMessage("Loading ...");
recents_dialog.show();
recents_dialog.setCancelable(false);
}
@Override
protected void onPostExecute(Void result)
{
if(recents_dialog.isShowing() == true)
{
recents_dialog.dismiss();
}
// Getting adapter by passing xml data ArrayList
list.setAdapter(adapter);
}
}
}
公共类FriendsStactivity扩展了活动实现OnClickListener{ 私人经理人; 静态最终字符串键\u ID=ID; 静态最终字符串键\u NAME=NAME; 静态最终串键\u已安装=已安装; 静态最终字符串KEY\u THUMB\u URL=picture; 受保护的列表视图好友列表; 受保护的静态JSONArray JSONArray; Friendslistatadapter适配器; ArrayList>friendslist; 编辑文本过滤器文本; 字符串响应; 按钮播放,邀请
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.friends_list);
friendslist = new ArrayList<HashMap<String, String>>();
mHandler = new Handler();
ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
actionBar.setTitle("Facebook Friends");
actionBar.setHomeAction(new IntentAction(this, TruthorDareActivity
.createIntent(this), R.drawable.ic_home));
friendsList = (ListView) findViewById(R.id.friendsList);
filterText = (EditText) findViewById(R.id.searchBox);
filterText.addTextChangedListener(filterTextWatcher);
friendsList.setTextFilterEnabled(true);
friendsList.requestFocus();
play = (Button) findViewById(R.id.play);
invite = (Button) findViewById(R.id.invite);
play.setOnClickListener(this);
invite.setOnClickListener(this);
Bundle extras = getIntent().getExtras();
apiResponse = extras.getString("API_RESPONSE");
callPlayList();
}
@Override
public void onBackPressed() {
super.onBackPressed();
this.finish();
}
@Override
protected void onResume() {
super.onResume();
friendsList.requestFocus();
}
public void callPlayList() {
try {
jsonArray = new JSONObject(apiResponse).getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json_data = jsonArray.getJSONObject(i);
if (json_data.has("installed")
&& json_data.getBoolean("installed") == true) {
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_ID, json_data.getString("id"));
map.put(KEY_NAME, json_data.getString("name"));
map.put(KEY_THUMB_URL, json_data.getString("picture"));
map.put(KEY_INSTALLED, json_data.getString("installed"));
friendslist.add(map);
}
}
} catch (JSONException e) {
showToast("Error: " + e.getMessage());
return;
}
adapter = new FriendsListAdapter(FriendsListActivity.this, friendslist);
friendsList.setAdapter(adapter);
}
public void callInviteList() {
try {
jsonArray = new JSONObject(apiResponse).getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json_data = jsonArray.getJSONObject(i);
if (!json_data.has("installed")) {
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_ID, json_data.getString("id"));
map.put(KEY_NAME, json_data.getString("name"));
map.put(KEY_THUMB_URL, json_data.getString("picture"));
map.put(KEY_INSTALLED, "false");
friendslist.add(map);
}
}
} catch (JSONException e) {
showToast("Error: " + e.getMessage());
return;
}
adapter = new FriendsListAdapter(FriendsListActivity.this, friendslist);
friendsList.setAdapter(adapter);
}
public void clearAdapter(String params) {
friendslist.clear();
adapter.notifyDataSetChanged();
adapter.notifyDataSetInvalidated();
if (params.equals("invite")) {
callInviteList();
} else {
callPlayList();
}
}
public class PostDialogListener extends BaseDialogListener {
@Override
public void onComplete(Bundle values) {
final String postId = values.getString("post_id");
if (postId != null) {
showToast("Message posted on the wall.");
} else {
showToast("No message posted on the wall.");
}
}
}
public void showToast(final String msg) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(FriendsListActivity.this, msg,
Toast.LENGTH_LONG);
toast.show();
}
});
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
adapter.getFilter().filter(s);
}
};
@Override
protected void onDestroy() {
super.onDestroy();
filterText.removeTextChangedListener(filterTextWatcher);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play:
clearAdapter("play");
break;
case R.id.invite:
clearAdapter("invite");
break;
default:
break;
}
}
}
下一部分是我在单独的类文件中使用的适配器类
}在getFilter方法中,尝试以下操作 @凌驾 受保护的void publishResultCharsSequence约束, FilterResults结果{
mDataShown = (ArrayList<HashMap<String, String>>)results.values;
ProjectListAdapter.this.setListData(mDataShown);
ProjectListAdapter.this.notifyDataSetChanged();
};
}) 使用调试器。在适配器中放置一些断点。过滤器是否实际返回任何结果?是否调用过publishResults?我认为发布的结果不会传递到getView函数中。因此,该列表不会更新。谢谢你的提醒,@Christopherryi肯定会测试这个。谢谢你的作品@ParkerHi,@Parker..我想知道你在publishResults方法中把'data'变量应用在哪里?您是否也修改了getView方法?@Victor Yew。我在这里编辑了代码,因为我试图放回您的原始代码,但忘记了我使用的是数据而不是MDataShowed。如果你需要我发布更多,我会的。我修改了lazylist适配器类的模型,使这段代码可以工作。你现在应该使用MDataShowed而不是数据。嗯……我用MDataShowed替换了数据,就像你一样。最初,列表填充得很好,但当我开始在文本输入中键入内容时,它崩溃了。如果你能给我看更多的代码就太好了。谢谢。我更新了更多代码供您尝试。相信你的过滤代码中的s.toString是它崩溃的原因。嗨,谢谢你的回答。但是,setListData函数是继承的吗?不,它不是继承的,我已经创建了在自定义适配器中设置列表的方法。
mDataShown = (ArrayList<HashMap<String, String>>)results.values;
ProjectListAdapter.this.setListData(mDataShown);
ProjectListAdapter.this.notifyDataSetChanged();
};
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(s.toString().equalsIgnoreCase(""))
{
adapter.setListData(projectListdata)
adapter.notifyDataSetChanged();
}
else
adapter.getFilter().filter(s);
}