【问题标题】:ListView custom filter gives wrong item selected when filteredListView 自定义过滤器在过滤时选择了错误的项目
【发布时间】:2016-02-21 20:21:47
【问题描述】:

我是 Android 编程新手,我有一个 ListView 过滤后总是返回列表中的第一项,那么我该如何解决这个问题?

例如,我的列表包含 A.A、A.B、A.C、B.C、B.D。当我想在列表中搜索以 B 开头的东西时,我会得到 B.C、B.D 但是当我单击 B.C 时,它会返回 A.A 和 B.D,它会返回 A.B

我正在寻找解决方案!请帮帮我!!

public class MainActivity extends Activity implements
    SearchView.OnQueryTextListener, AdapterView.OnItemClickListener {

ListView lv;
SearchView search_view;

String[] country_names , iso_codes ;
TypedArray country_flags ;

ArrayList<Country> countrylist ;
CustomAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lv = (ListView) findViewById(R.id.list_view);
    search_view = (SearchView) findViewById(R.id.search_view);

    country_names = getResources().getStringArray(R.array.country_names);
    iso_codes = getResources().getStringArray(R.array.iso_Code);
    country_flags = getResources().obtainTypedArray(R.array.country_flags);

    countrylist = new ArrayList<Country>();
    for (int i = 0; i < country_names.length; i++) {
        Country country = new Country(country_names[i] , iso_codes[i] ,
                country_flags.getResourceId(i, -1) );
        countrylist.add(country);
    }

    adapter = new CustomAdapter(getApplicationContext(), countrylist );
    lv.setAdapter(adapter);

    search_view.setOnQueryTextListener(this);
    lv.setOnItemClickListener(this);










}

@Override
public boolean onQueryTextChange(String newText) {
    adapter.getFilter().filter(newText);
    return false;
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

public void onItemClick(AdapterView<?> l, View v, int position, long id) {
    Log.i("HelloListView", "You clicked Item: " + id + " at position:" + position);
    // Then you start a new Activity via Intent
    Intent intent = new Intent();
    intent.setClass(this, ListItemDetail.class);
    intent.putExtra("position", position);
    // Or / And
    intent.putExtra("id", id);
    startActivity(intent);
}

列出项目详细信息

public class ListItemDetail extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_item_detail);

    Intent intent = getIntent();
    int position = intent.getIntExtra("position", 0);

    // Here we turn your string.xml in an array
    String[] myKeys = getResources().getStringArray(R.array.sections);
    String[] myKeys2 = getResources().getStringArray(R.array.testo2);

    String[] myKeys3 = getResources().getStringArray(R.array.testo3);

    String[] myKeys4 = getResources().getStringArray(R.array.testo4);



    TextView myTextView = (TextView) findViewById(R.id.my_textview);
    myTextView.setText(myKeys[position]);

    TextView myTextView2 = (TextView) findViewById(R.id.testo2);
    myTextView2.setText(myKeys2[position]);

    TextView myTextView3 = (TextView) findViewById(R.id.testo3);
    myTextView3.setText(myKeys3[position]);

    TextView myTextView4 = (TextView) findViewById(R.id.testo4);
    myTextView4.setText(myKeys4[position]);

自定义列表适配器

public class CustomAdapter extends BaseAdapter implements Filterable {

Context context;
ArrayList<Country> countrylist;
ArrayList<Country> mStringFilterList;
ValueFilter valueFilter;



CustomAdapter(Context context , ArrayList<Country> countrylist) {
    this.context = context;
    this.countrylist = countrylist;
    mStringFilterList = countrylist;
}

@Override
public int getCount() {
    return countrylist.size();
}

@Override
public Object getItem(int position) {
    return countrylist.get(position);
}

@Override
public long getItemId(int position) {
    return countrylist.indexOf(getItem(position));
}

@Override
public View getView(int position , View convertView , ViewGroup parent ) {

    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

    convertView = null;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.list_item, null);

        TextView name_tv = (TextView) convertView.findViewById(R.id.name);
        TextView iso_tv = (TextView) convertView.findViewById(R.id.code);
        ImageView iv = (ImageView) convertView.findViewById(R.id.flag);

        Country country = countrylist.get(position);

        name_tv.setText(country.getName());
        iso_tv.setText(country.getIso_code());



        Picasso
                .with(context)
                .load(url[position])
                .fit() // will explain later
                .centerCrop()
                .into(iv);
    }
    return convertView;
}

@Override
public Filter getFilter() {
    if (valueFilter == null) {
        valueFilter = new ValueFilter();
    }
    return valueFilter;
}

private class ValueFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();

        if (constraint != null && constraint.length() > 0) {
            ArrayList<Country> filterList = new ArrayList<Country>();
            for (int i = 0; i < mStringFilterList.size(); i++) {
                if ( (mStringFilterList.get(i).getName().toUpperCase() )
                        .contains(constraint.toString().toUpperCase())) {

                    Country country = new Country(mStringFilterList.get(i)
                            .getName() ,  mStringFilterList.get(i)
                            .getIso_code() ,  mStringFilterList.get(i)
                            .getFlag());

                    filterList.add(country);
                }
            }
            results.count = filterList.size();
            results.values = filterList;
        } else {
            results.count = mStringFilterList.size();
            results.values = mStringFilterList;
        }
        return results;

    }

    @Override
    protected void publishResults(CharSequence constraint,
                                  FilterResults results) {
        countrylist = (ArrayList<Country>) results.values;
        notifyDataSetChanged();
    }

}

挑战

public class Country {

String name;
String iso_code;
int flag;

Country(String name, String iso_code, int flag) {
    this.name = name;
    this.iso_code = iso_code;
    this.flag = flag;
}

public String getIso_code() {
    return iso_code;
}

public void setIso_code(String iso_code) {
    this.iso_code = iso_code;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getFlag() {

    return flag;
}

public void setFlag(int flag) {

    this.flag = flag;
}

【问题讨论】:

    标签: android listview filter


    【解决方案1】:

    我注意到您正在使用该职位作为ListItemDetail 活动的输入。这会给您带来问题,因为给定项目的位置会随着列表被过滤而改变。

    您应该将项目值放入Intent,然后使用这些值,而不是在ListItemDetail 中查找任何内容

    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
    
        Country country = (Country) ((CustomAdapter ) l.getAdapter()).getItem(position);
    
        Intent intent = new Intent(this, ListItemDetail.class);
        intent.putExtra("name", country.getName());
        intent.putExtra("iso_code", country.getIso_code());
        intent.putExtra("flag", country.getFlag());
        startActivity(intent);
    }
    

    现在更改您的 ListDetailActivity 以使用这些值:

    public class ListItemDetail extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_item_detail);
    
            Intent intent = getIntent();
            String name = intent.getStringExtra("name");
            String iso_code = intent.getStringExtra("iso_code");
            int flagResId = intent.getIntExtra("flag");
    
            // make a TextView in activity_list_item_detail.xml called "name"
            TextView nameTextView = (TextView) findViewById(R.id.name);
            nameTextView .setText(name);
    
            // make a TextView in activity_list_item_detail.xml called "iso_code"
            TextView isoCodeTextView = (TextView) findViewById(R.id.iso_code);
            isoCodeTextView .setText(iso_code);
    
            // make an ImageView in activity_list_item_detail.xml called "flag" 
            ImageView flagImageView = (ImageView) findViewById(R.id.flag);
            flagImageView.setImageResource(flagResId);
        }
    }
    

    请注意,在您按照 cmets 中的建议更新您的 activity_list_item_detail.xml 之前,此活动将不起作用

    【讨论】:

    • 感谢您的评论!!我写了这个,但是当操作该项目时,应用程序总是显示相同的字符串 (1)
    • Country country = (Country) ((CustomAdapter) l.getAdapter()).getItem(position); intent.putExtra("title", country.getName());
    • 请发布您的 CustomAdapter 的代码,以及您的 Country 类
    • 我添加了 customadapter 和国家。谢谢帮忙!
    • 我看到 ListItemDetail 需要一个 int 而不是字符串。 (getName 是一个字符串)。我在 Country 中使用 int 创建 getTitle,但应用程序崩溃并出现此错误“Caused by: java.lang.ArrayIndexOutOfBoundsException: length=4; index=-1”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多