Question

I want to make a listview item selected and the text "select" to be made to "selected", but when i click an item mutiple items get selected if I select an item at position 0 , items get selected at at a pattern, that is 0,7,14,21 and if i change the view to landscape: it will be 0 ,5,10,15, etc.

my main activity is:

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);
}}

My adapter is:

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();
        }
    }
}}

I cant figure this out. Please help

Was it helpful?

Solution

You need to maintain the selected item in adapter and use it to change the text :

Adapter Code

 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;
   }

Now set the selectedIndex variable when a list item clicked.

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

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

OTHER TIPS

You can add a member "checked" in GroupsModel, and initial it assign false;

In 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);
}

In getView() in adapter:

public View getView(...) {
    ...
    if(getItem(position).isChecked()) {
        // You must set root view in holder
        holder.getBackground().setBackgroundColor(Color.CYAN);
    }
    ...
}

Your problem is that Android is reusing your views, so when you scroll, the first view disappears and appears at the bottom with the same state.

What you need to do is everytime you check an item, you need to store de id/position of the item checked (maybe ArrayList<Integer>), this way everytime your getView method is getting called you will look at this class/structure you have created and see it the row needs to be checked or not.

Note: If the row is not checked you will have to call to myCheck->setChecked(false); in order to assure that the row is in a coherent state.

You must use a array or option object to record which position is selected.

And detect the array or option object in getView() in adapter.

So, your need move the code: "view.setBackgroundColor(Color.CYAN)" to getView() method.

You have been bitten by what they say "recycling" issues.
When re-using your views, this kind of problems happens.
There are several methods(for example saving checked positions in an arraylist, ...) to deal with it, but in my opinion the simplest and straight forward solution is using tags. setTag() and getTag() Here is a tutorial using it.
Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top