我有一个带有自定义适配器的 ListView 。 我的 Activity 中有一个编辑 TextView ,用户可以在其中键入以过滤 ListView 中的内容。
假设我在 ListView 中有两个项目。过滤后,ArrayList 减少为一个元素。 问题是 getView 方法仍然为前两行执行。
这是我的代码。
列表 Activity :
public class TeamsListActivity extends ListActivity {
private ArrayList<Team> teams = new ArrayList<Team>();
private TeamsListAdapter teamsListAdapter = null;
private EditText searchInput = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teams_list);
// get association id from the intent.
int afId = getIntent().getExtras().getInt("afId");
Log.i(MainActivity.TAG, "id_association =" + afId);
// get the teams from the association.
this.teams = TeamsDAO.getInstance(getApplicationContext())
.getTeamsByAssociation(afId);
// inits the list adapter
teamsListAdapter = new TeamsListAdapter(this, teams);
setListAdapter(teamsListAdapter);
// gets the search input view
searchInput = (EditText) findViewById(R.id.teams_list_search_box);
searchInput.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
Log.d(Constants.TAG,"Teams search: " + s.toString());
teamsListAdapter.getFilter().filter(s);
}
});
}
}
我的适配器
public class TeamsListAdapter extends ArrayAdapter<Team> implements Filterable {
private ArrayList<Team> teams = null;
private Context context = null;
public TeamsListAdapter(Context context,
ArrayList<Team> objects) {
super(context, R.layout.teams_list_row, objects);
this.context = context;
this.teams = objects;
}
@Override
public View getView(int position, View v, ViewGroup parent) {
if (v == null) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.teams_list_row, null);
}
Team t = teams.get(position);
if (t != null) {
TextView txtTeamName = (TextView) v.findViewById(R.id.teams_list_team_name);
txtTeamName.setText(t.getName());
ImageView ivTeamLogo = (ImageView) v.findViewById(R.id.teams_list_team_logo);
ivTeamLogo.setImageResource(R.drawable.af_braga);
}
return v;
}
@Override
public Filter getFilter() {
return new Filter() {
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.d(Constants.TAG, "**** Search RESULTS for: " + constraint);
teams = (ArrayList<Team>) results.values;
Log.d(Constants.TAG,"size:"+teams.size());
TeamsListAdapter.this.notifyDataSetChanged();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.d(Constants.TAG, "**** PERFORM TEAK FILTERING for: " + constraint);
ArrayList<Team> filteredResults = getFilteredResults(constraint);
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
}
/**
* filters the teamsList
* @param constraint String The text to search
* @return ArrayList<Team>
*/
private ArrayList<Team> getFilteredResults(CharSequence constraint) {
ArrayList<Team> teams = TeamsListAdapter.this.teams;
ArrayList<Team> filteredTeams = new ArrayList<Team>();
for(int i=0;i< teams.size();i++){
if(teams.get(i).getName().toLowerCase().startsWith(constraint.toString().toLowerCase())){
filteredTeams.add(teams.get(i));
}
}
return filteredTeams;
}
};
}
}
问题的澄清。
1.假设我的列表开始显示两个元素。 2. 用户在编辑文本中插入一些文本来过滤列表内容,这导致更新后的 arrayList 只有一个与查询匹配的元素。 3. 在调用 notifyDataSetChanged 之后,getView 仍然被调用,就像在执行 Team t = teams.get(position) 时数据集中有两行导致 IndexOutOfBoundsException 因为 arrayList 现在只有一个元素所以当 position = 1 => get (职位)失败。
希望现在晴朗。
最佳答案
好吧,我解决了我的问题。 我需要像这样覆盖我的适配器中的几个方法。
@Override
public int getCount() {
return teams.size();
}
@Override
public Team getItem(int position) {
return teams.get(position);
}
@Override
public long getItemId(int position) {
return teams.get(position).getId();
}
现在我发现我的搜索实现存在问题。因为我正在更新原始数据集,所以搜索只能进行一次。如果我尝试返回到原始列表,我不能,因为我的原始数据数组已被修改。使用数据库查询很容易解决,而不是过滤数组列表。
关于android自定义 ListView 适配器不更新getView中的 View 数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8771173/