[英]Bug with ArrayAdapter and Search function?
當我在名稱列表中搜索值時,它將返回相應的值。 但是,當我刪除該值時,我的ListView不再再次返回列表中的所有名稱,它們消失了。 如何解決呢? 任何想法?
TabelaActivity.java
代碼:
package com.akzonobel.malote.tabela;
import com.akzonobel.malote.R;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.ListView;
/*
* Very basic Activity, the only things it does
* are get the ListView reference from our layout.
* Create an Adapter, set the Adapter to the ListView
* and handle the onItemClick events for when the user
* clicks on a row.
*/
public class TabelaActivity extends Activity {
EditText inputSearch;
CSVAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabela);
//Lookup our ListView
ListView mList = (ListView)findViewById(R.id.mList);
inputSearch = (EditText) findViewById(R.id.inputSearch);
//Create Adapter. The second parameter is required by ArrayAdapter
//which our Adapter extends. In this example though it is unused,
//so we'll pass it a "dummy" value of -1.
mAdapter = new CSVAdapter(this, -1);
//attach our Adapter to the ListView. This will populate all of the rows.
mList.setAdapter(mAdapter);
/*
* This listener will get a callback whenever the user clicks on a row.
* The pos parameter will tell us which row got clicked.
*
* For now we'll just show a Toast with the state capital for the state that was clicked.
*/
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
TabelaActivity.this.mAdapter.getFilter().filter(cs);
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
}
CSVAdapter.java
代碼:
package com.akzonobel.malote.tabela;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
/*
* Very basic Custom Adapter that takes state name,capital pairs out of a csv
* file from the assets and uses those values to build a List of State objects.
* Overrides the default getView() method to return a TextView with the state name.
*
* ArrayAdapter - a type of Adapter that works a lot like ArrayList.
*/
@SuppressLint("DefaultLocale") public class CSVAdapter extends ArrayAdapter<State>{
private List<State> filteredModelItemsArray;
private Filter filter;
Context ctx;
//We must accept the textViewResourceId parameter, but it will be unused
//for the purposes of this example.
public CSVAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
//Store a reference to the Context so we can use it to load a file from Assets.
this.ctx = context;
//Load the data.
loadArrayFromFile();
}
@Override
public Filter getFilter() {
if (filter == null){
filter = new ModelFilter();
}
return filter;
}
/*
* getView() is the method responsible for building a View out of a some data that represents
* one row within the ListView. For this example our row will be a single TextView that
* gets populated with the state name.
* (non-Javadoc)
* @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
*/
@Override
public View getView(final int pos, View convertView, final ViewGroup parent){
/*
* Using convertView is important. The system will pass back Views that have been
* created but scrolled off of the top (or bottom) of the screen, and thus are no
* longer being shown on the screen. Since they are unused, we can "recycle" them
* instead of creating a new View object for every row, which would be wasteful,
* and lead to poor performance. The diference may not be noticeable in this
* small example. But with larger more complex projects it will make a significant
* improvement by recycling Views rather than creating new ones for each row.
*/
TextView mView = (TextView)convertView;
//If convertView was null then we have to create a new TextView.
//If it was not null then we'll re-use it by setting the appropriate
//text String to it.
if(null == mView){
mView = new TextView(parent.getContext());
mView.setTextSize(19);
mView.setTextColor(Color.WHITE);
}
//Set the state name as the text.
mView.setText(getItem(pos).getName());
//We could handle the row clicks from here. But instead
//we'll use the ListView.OnItemClickListener from inside
//of MainActivity, which provides some benefits over doing it here.
return mView;
}
/*
* Helper method that loads the data from the states.csv and builds
* each csv row into a State object which then gets added to the Adapter.
*/
private void loadArrayFromFile(){
try {
// Get input stream and Buffered Reader for our data file.
InputStream is = ctx.getAssets().open("states.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
//Read each line
while ((line = reader.readLine()) != null) {
//Create a State object for this row's data.
State cur = new State();
cur.setName(line);
//Add the State object to the ArrayList (in this case we are the ArrayList).
this.add(cur);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ModelFilter extends Filter
{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if(constraint != null && constraint.toString().length() > 0)
{
ArrayList<State> filteredItems = new ArrayList<State>();
for(int i = 0, l = getCount(); i < l; i++)
{
State m = getItem(i);
if(m.getName().toLowerCase().contains(constraint))
filteredItems.add(m);
}
result.count = filteredItems.size();
result.values = filteredItems;
}
else
{
ArrayList<State> allItems = new ArrayList<State>();
for(int i = 0, l = getCount(); i < l; i++)
{
State m = getItem(i);
allItems.add(m);
}
synchronized(this)
{
result.values = allItems;
result.count = allItems.size();
}
}
return result;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredModelItemsArray = (ArrayList<State>)results.values;
notifyDataSetChanged();
clear();
for(int i = 0, l = filteredModelItemsArray.size(); i < l; i++)
add(filteredModelItemsArray.get(i));
notifyDataSetInvalidated();
}
}
}
State.java
代碼:
package com.akzonobel.malote.tabela;
/*
* Basic Data class to hold a state name and the state capital.
*/
public class State {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
這是一個相當老的錯誤,Android從未解決過。 它首先在此處報道, 發行號為9666 ,然后關閉並重新開放為發行號69179 。 我不會在任何時候都屏住呼吸。 如果您想了解更多有關原因的詳細信息,我寫了一篇小博文談論它。
或多或少,如果您要過濾數據並添加,刪除,更新等部分數據,則需要擴展BaseAdapter並編寫自己的解決方案。 或者節省一些時間,並利用我的挫敗感反復進行多次,而我只是將所有這些都扔進了一個開源庫中。 解決所有的過濾錯誤,然后解決一些: Advanced-Adapters 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.