Search code examples
javaandroidlistviewselectorselected

Every fourth list view item get marked by using selector instead of just the choosen one android


Hey Guys I am working right now on a University project and have some problems which I found out randomly. Actually, I have to create an app (android) for an upcoming event where the user can see all the events in an overview and can tag his favorite ones.

I have a listview object, which is displaying all the items from a List<> I wanna give the opportunity that the user can tag his favorite events which shall appear in a new fragment but I have problems with the changing icon. When you tag the first item in the list, it also tags every fourth item in the list additionally. I don't know why and it would be great if you can help! :)

the selector for the Image View

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_selected="true" android:drawable="@drawable/ic_bookmark_black_24dp_copy_3" />

    <item android:state_selected="false" android:drawable="@drawable/ic_bookmark_border_black_24dp_copy_3" />

    <item android:drawable="@drawable/ic_bookmark_black_24dp_copy_3" />
</selector>

the adapter including the activating function to change the icon

public class CustomArrayAdapter extends BaseAdapter{

    private List<EventItem> listData;

    private LayoutInflater layoutInflater;

    private Context context;

    static class ViewHolder {
        TextView titleView;
        TextView descriptionView;
        TextView authorView;
        TextView reportedDateView;
        TextView locationView;
        ImageView favorite;
    }

    public CustomArrayAdapter(Context context, List<EventItem> listData) {
        this.context = context;
        this.listData = listData;
        Collections.sort(listData);
    }

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

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

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null) {
            layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.list_event_item, null);
            holder = new ViewHolder();

            holder.titleView = (TextView) convertView.findViewById(R.id.title);
            holder.authorView = (TextView) convertView.findViewById(R.id.author);
            holder.descriptionView = (TextView) convertView.findViewById(R.id.description);
            holder.locationView = (TextView) convertView.findViewById(R.id.location);
            holder.reportedDateView = (TextView) convertView.findViewById(R.id.time);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }
            holder.titleView.setText(listData.get(position).getTitle());
            holder.authorView.setText(listData.get(position).getAuthor());
            holder.descriptionView.setText(listData.get(position).getDescription());
            holder.locationView.setText(listData.get(position).getLocation());
            holder.reportedDateView.setText(getTime(position));

        holder.favorite = (ImageView) convertView.findViewById(R.id.bookmark);

        holder.favorite.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(view.isSelected()) {
                System.out.println("Position: ");
                view.setSelected(false);
            }else{
                view.setSelected(true);
            }
        }
    });

        return convertView;
    }

    private String getTime(int position) {

        Date start = listData.get(position).getStartTime();
        Date end = listData.get(position).getEndTime();
        String startTime = start.toString();
        String endTime = end.toString();

        return String.format("%1s%2s%3s", start.toString().substring(11, 19), " - ", end.toString().substring(11, 19));
    }
}

And here my Image view out of the xml file where all the other views where styled

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/description"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_marginEnd="8dp"
    android:src="@drawable/bookmark_icon_selector"
    android:tint="@color/colorDhdPrimary"
    android:id="@+id/bookmark"
/>

and here the list view in the separate XML.

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:id="@+id/list_container">

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/list_event"
    app:layout_constraintBottom_toBottomOf="@+id/list_container"
    app:layout_constraintLeft_toLeftOf="@+id/list_container"
    app:layout_constraintRight_toRightOf="@+id/list_container"
    app:layout_constraintTop_toTopOf="@+id/list_container"
    />


Solution

  • Solution can be multiple . One way to do this is just add a boolean in your EventItem POJO.

     class EventItem{
        boolean isSelected;
    }
    

    Now toggle this boolean onClick.

    final int pos=position;
            holder.favorite.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    listData.get(pos).isSelected=!listData.get(posi).isSelected;
                    notifyDataSetChanged();
                }
            });
    

    And in onBindViewHolder just check for boolean.

    if(listData.get(position).isSelected){
     holder.favorite.setSelected(true);
     }else{
     holder.favorite.setSelected(false);
    }