Filipe Gonçalves Filipe Gonçalves - 3 months ago 24
Android Question

Highlight an item from a gridview

I am trying to highlight an item from a gridview after it was pressed.
I saw some similar questions here on StackOverflow, but none of them could fulfill what i wanted with a possible way for my app (due to design restritions or minimum api).

My minimum API is 9, so i can't use a Multi_choice_listener.

Right now i am able to set the background with the color i want, but when i press one element, i also presses other elements in the same position of the screen (after i scroll the gridview).

For example, imagine this screen :

A B C
D E F

If i press B and then i scroll the screen it will show up :

G H I
J K L

And the H will also be highlighted (because he is in the same position as B).

Here is my getView method :

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

viewHolder = null;
if (convertView == null) {

viewHolder=new ViewHolder();

LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view=layoutInflater.inflate(R.layout.highwayappselectionitem,parent, false);

viewHolder.appImageIcon=(ImageView) view.findViewById(R.id.highwayGridViewItemIcon);
viewHolder.appNameLabel=(TextView) view.findViewById(R.id.highwayGridViewItemName);
viewHolder.appInfoButton = (ImageView) view.findViewById(R.id.highwayGridViewItemInfoButton);
viewHolder.linearLayout = (LinearLayout) view.findViewById(R.id.HighwayGridViewItem);

}else{
view= convertView;
viewHolder = (ViewHolder) convertView.getTag();
}


viewHolder.appNameLabel.setText(appsList.get(position).getAppName());
viewHolder.appImageIcon.setImageDrawable(appsList.get(position).getImageIcon());


view.setTag(viewHolder);

viewHolder.linearLayout.setOnClickListener(new MyOnClickListener(position,0));

return view;
}


Here is the listener (inside the adapter) where i set the background. Basically if i press an item from the gridview, I want THAT ITEM to change the background to a certain color, so that the person knows that they pressed it.

Here is my code for that listener :

public void onClick(View v) {

if(selectedView==0 || selectedView==1){

appName=appsList.get(position).getAppName();
filePath=appsList.get(position).getFilePath();
appLogo=appsList.get(position).getImageIcon();

v.setBackgroundColor(activity.getResources().getColor(R.color.light_grey));

System.out.println("Just pressed the app ... "+appName);
System.out.println("His filePath is ... "+filePath);

HighwayGridViewAppItem tmpSelectedItem= new HighwayGridViewAppItem(appLogo, appName, filePath);
selectedAppsList.add(tmpSelectedItem);

System.out.println("AppSelectionCUstomAdapter : Added a new application to the list of selected apps .!!!!!!!!!!!!!!!.........");
System.out.println("AppselectioncustomAdaptaer : The size of the selectedAppsList is now : "+selectedAppsList.size());

}else{
//pressed the info button
System.out.println("This will be implemented later, need access to the webservices");
}
}
}


The appslist is a list of my custom items of the gridview.

UPDATE : The solution is an adaptation of the selected answer.

Basically what was happening was that i was setting the background of the view well, but since it is being reused (because i am using a viewholder for effiency), and since that view had already the background on that color, when it was going to be reused, it would be reused WITH that background color. The solution was simply to write an else statement and put the background back to the 1st color.

Answer

You need to save selected item position not selected view. So code will look like so:

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
    /.../ 
    if (convertView == null) {
        /.../
        //click listener now common to all views
        viewHolder.linearLayout.setOnClickListener(this);
    } else {
        /.../
    }

    //bind possition to viewholder
    viewHolder.possition = possition;
    viewHolder.setHighlighted(possition == selectedItem);

    /.../
 }

 public void onClick(View v) {
      ViewHolder holder =(ViewHolder)v.getTag();
      selectedItem = holder.possition;
      notifyDataSetChanged();
 }

If you need multiple choises you could create Set<Integer> to hold selected positions. Like so :

@Override
public View getView(int position, View convertView, ViewGroup parent) {
     /..../
     viewHolder.setHighlighted(selectedItems.contains(position));
     /..../
}

public void onClick(View v) {
      ViewHolder holder =(ViewHolder)v.getTag();
      if (selectedItems.contains(holder.position)) {
          selectedItems.remove(holder.position);
      } else {
          selectedItems.add(holder.position);
      } 
      notifyDataSetChanged();
}