当我在名单列表中搜索一个值时,它会返回相应的值。但是当我删除这个值时,我的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;
}
}
答案 0 :(得分:0)
这是一个相当老的错误,Android从未解决过。它首先在此处报告Issue 9666,然后关闭并重新打开为问题69179。我不会屏住呼吸,很快就会被修好。如果你想了解更多关于原因的细节,我写了一篇小blog post来谈论它。
或多或少,如果您想过滤数据并添加,删除,更新等部分内容......您需要扩展BaseAdapter并编写自己的解决方案。或者节省一些时间,并利用我一次又一次多次这样做的挫折,我把它全部扔进了一个开源库。解决所有过滤错误,然后解决一些:Advanced-Adapters。