Android自定义适配器的ListView多选问题

3

我想让一个列表视图项被选中并将文本“选择”更改为“已选”,但是当我点击一个项目时,如果我在位置0选择一个项目,则会选择多个项目,这些项目会以一种模式选择,即0、7、14、21,如果我将视图更改为横向,则为0、5、10、15等。

我的主要活动是:

public class two extends Activity implements OnQueryTextListener,OnItemClickListener {
GroupAdapter grpAdapter;
public static ArrayList<GroupsModel> arrayOfList;
public static ListView listView;
public static String base_url = "myurl";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.two);
    arrayOfList = new ArrayList<GroupsModel>();
    listView = (ListView) findViewById(R.id.group_listview);
    listView.setOnItemClickListener(this);
    listView.setTextFilterEnabled(true);
    new ProgressTask(two.this).execute();
}  

private class ProgressTask extends AsyncTask<String, Void, Boolean> {
    private ProgressDialog dialog;
    @SuppressWarnings("unused")
    private two activity;
    public ProgressTask(two two) {
        this.activity = two;
        context = two;
        dialog = new ProgressDialog(context);
    }
    private Context context;
    protected void onPreExecute() {
        this.dialog.setMessage("Progress start");
        this.dialog.show();
    }
    @Override
    protected void onPostExecute(final Boolean success) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
            grpAdapter = new GroupAdapter(two.this, R.layout.two_row,arrayOfList);
        listView.setAdapter(grpAdapter);
    }
    protected Boolean doInBackground(final String... args) {
        //arrayOfList = new ArrayList<GroupsModel>();
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        //params.add(new BasicNameValuePair("",""));

        JSONParser jp = new JSONParser();
        JSONArray groups_obj = jp.makeHttpRequest(base_url + "groups/all", "GET", params);
        for (int i = 0; i < groups_obj.length(); i++) {
            GroupsModel group = new GroupsModel();
            try {
                JSONObject grp = groups_obj.getJSONObject(i);
                group.setGroupId(grp.getInt("id"));
                group.setGroupname(grp.getString("name"));
                arrayOfList.add(group);
            }
            catch (JSONException e) {
                e.printStackTrace();
            }

        }
        return null;
    }
}

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      SearchManager searchManager = (SearchManager) getSystemService( Context.SEARCH_SERVICE );
      SearchView searchView = (SearchView) menu.findItem(R.id.menu_item_search).getActionView();
      searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
      searchView.setSubmitButtonEnabled(false);
      searchView.setOnQueryTextListener(this);
      return super.onCreateOptionsMenu(menu);
 }

 @Override
 public boolean onQueryTextChange(String newText)
 {
      // this is your adapter that will be filtered
      if (TextUtils.isEmpty(newText))
      {
            listView.clearTextFilter();
      }
      grpAdapter.getFilter().filter(newText.toString());  
      return true;
 }

 @Override
 public boolean onQueryTextSubmit(String query) {
  // TODO Auto-generated method stub
  return false;
 }

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
    // TODO Auto-generated method stub
    view.setBackgroundColor(Color.CYAN);
}}

我的适配器是:

public class GroupAdapter extends ArrayAdapter<GroupsModel> implements Filterable{
    private Context activity;
    private ArrayList<GroupsModel> items ;
    private List<GroupsModel> arrayList;
    private ArrayFilter mFilter;
    private int resource;

    public GroupAdapter(Activity act, int resource, ArrayList<GroupsModel> arrayList) {
            super(act, resource, arrayList);
            this.activity = act;
            this.resource = resource;
            this.items = new ArrayList<GroupsModel>();
            this.items.addAll(arrayList);
            this.arrayList = new ArrayList<GroupsModel>();
            this.arrayList.addAll(arrayList);
    }

     public View getView(final int position, View convertView,final ViewGroup parent) {
                final ViewHolder holder;
                LayoutInflater inflater = ((Activity) activity).getLayoutInflater();
                if (convertView == null) {
                    convertView = inflater.inflate(resource,parent, false);
                    holder = new ViewHolder();
                    holder.group_name = (TextView) convertView.findViewById(R.id.group_name);
                    holder.select = (TextView) convertView.findViewById(R.id.select);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }
                try{
                    GroupsModel groups = items.get(position);

                    holder.group_name.setText(groups.getGroupName());
                }catch(Exception e){
                    e.printStackTrace();
                }
                holder.select.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View arg0) {
                        // TODO Auto-generated method stub
                        holder.select.setText("my new text");
                    }
                });
                return convertView;
            }

    public class ViewHolder {
            public TextView group_name,select;
    }

    @Override
    public int getCount() {
        // Total count includes list items and ads.
        return items.size();
    }

    @Override
    public GroupsModel getItem(int position)
    {
        // TODO Auto-generated method stub
        return items.get(position);
    }
    @Override
    public long getItemId(int position)
    {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new ArrayFilter();
    }
    return mFilter;
}

private class ArrayFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence prefix) {
        FilterResults results = new FilterResults();
        if (arrayList == null) {
            synchronized (this) {
                arrayList = new ArrayList<GroupsModel>(items);
            }
        }
        if (prefix == null || prefix.length() == 0) {
            ArrayList<GroupsModel> list;
            synchronized (this) {
                list = new ArrayList<GroupsModel>(arrayList);
            }
            results.values = list;
            results.count = list.size();
        } else {
            String prefixString = prefix.toString().toLowerCase();

            ArrayList<GroupsModel> values;
            synchronized (this) {
                values = new ArrayList<GroupsModel>(arrayList);
            }

            final int count = values.size();
            final ArrayList<GroupsModel> newValues = new ArrayList<GroupsModel>();
            for (int i = 0; i < count; i++) {
                final String value = values.get(i).getGroupName();
                final String valueText = value.toLowerCase();
                // First match against the whole, non-splitted value
                if (valueText.startsWith(prefixString)) {
                    newValues.add(values.get(i));
                } else {
                    final String[] words = valueText.split(" ");
                    final int wordCount = words.length;
                    // Start at index 0, in case valueText starts with space(s)
                    for (int k = 0; k < wordCount; k++) {
                        if (words[k].startsWith(prefixString)) {
                            newValues.add(values.get(i));
                            break;
                        }
                    }
                }
            }
            results.values = newValues;
            results.count = newValues.size();
        }
        return results;
    }

    @SuppressWarnings("unchecked")
            @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
       items = (ArrayList<GroupsModel>) results.values;
       if (results.count > 0) {
            notifyDataSetChanged();
        } else {
            notifyDataSetInvalidated();
        }
    }
}}

我无法解决这个问题,请帮助我。

我不明白这个问题如何帮助我的上下文。 - sharath
1
抱歉,我不小心设置了那个标记。它本意是针对另一个问题的。 - DroidDev
5个回答

1
你需要在适配器中维护所选项目,并使用它来更改文本:

适配器代码

 private int selectedIndex;
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        final ViewHolder holder;
                    LayoutInflater inflater = ((Activity) activity).getLayoutInflater();
                    if (convertView == null) {
                        convertView = inflater.inflate(resource,parent, false);
                        holder = new ViewHolder();
                        holder.group_name = (TextView) convertView.findViewById(R.id.group_name);
                        holder.select = (TextView) convertView.findViewById(R.id.select);
                        convertView.setTag(holder);
                    } else {
                        holder = (ViewHolder) convertView.getTag();
                    }
        if(selectedIndex!= -1 && position == selectedIndex)
        {
            convert_view.setBackgroundColor(Color.CYAN);
           holder.select.setText("selected");

        }
        else
        {
            convert_vie.wsetBackgroundColor(default_color);
           holder.select.setText("Select");
        }
                //Your other code      .....

        return convertView ;
    }

   public void setSelectedIndex(position)
   {
       selectedIndex = position;
   }

当列表项被点击时,现在设置selectedIndex变量。

public class MainActivity extends Activity implements OnItemClickListener
{
    // Implemented onItemClickListener

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        adapter.setSelectedIndex(position);
    }
}

1
你可以在GroupsModel中添加一个名为"checked"的成员变量,并将其初始化为false;
在activity中,
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
  final boolean isChecked = listView.getItem(position).isChecked();
  listView.get(position).setChecked(!isChecked);
}

在适配器中的getView()方法中:
public View getView(...) {
    ...
    if(getItem(position).isChecked()) {
        // You must set root view in holder
        holder.getBackground().setBackgroundColor(Color.CYAN);
    }
    ...
}

0

你的问题是Android正在重用你的视图,所以当你滚动时,第一个视图会消失,并以相同状态出现在底部。

你需要做的是每次检查一个项目时,你需要存储已选项目的id/位置(也许是ArrayList<Integer>),这样每次调用你的getView方法时,你将查看你创建的这个类/结构,并查看该行是否需要被选中。

注意:如果该行未被选中,则必须调用myCheck->setChecked(false);以确保该行处于一致状态。


我该怎么做呢?你能分享一个例子吗? - sharath

0

你必须使用数组或选项对象来记录所选位置。

并在适配器的getView()方法中检测数组或选项对象。

因此,你需要将代码“view.setBackgroundColor(Color.CYAN)”移动到getView()方法中。


你能给我一个在我的代码中如何使用它的例子吗? - sharath

0

你遇到了所谓的“重复利用”问题。
当重复使用你的视图时,这种问题就会发生。
有几种方法(例如在ArrayList中保存选中的位置等)可以解决它,但我认为最简单和直接的解决方案是使用标签。 setTag()getTag() 这里有一个tutorial使用它。
希望能帮到你。


你能给我一些建议让我的代码正常工作吗? - sharath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接