Ahmet K
Ahmet K

Reputation: 813

Change one element of ListView

I want to change one item (ImageView) in a specific row of a ListView. Now I tried it to change it through the onItemClickListener provided View to change it. It also works !

But somehow when I scroll up and down other listview rows getting also changed. I found something about the problem "view recycling" but I really didnt find a solution for it.

Someone can help ?

EDIT: Some code here :

My Listener :

LV.setOnItemClickListener(new AdapterView.OnItemClickListener() {

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

The function which should change it

private void updateEQAnimation(int index, View view){

   ColorStateList sColorStatePlaying;
   ColorStateList sColorStateNotPlaying;

   sColorStatePlaying = ColorStateList.valueOf(context.getResources().getColor(R.color.colorPrimary));

    if(view == null)
        return;
    AnimationDrawable animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.anim_current_song);
    ImageView EQ_ANIM = (ImageView) view.findViewById(R.id.imageView_eq_animation);
    EQ_ANIM.setVisibility(View.VISIBLE);
    EQ_ANIM.setImageDrawable(animation);
    EQ_ANIM.setImageTintList(sColorStatePlaying);
    animation.start();}

getView method :

 @Override
public View getView(int position, View view, ViewGroup parent) {
    View rview = view;
    holder = null;

    if (rview == null)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        rview= inflater.inflate(R.layout.row_song, null, true);
        holder = new ViewHolder(rview);
        rview.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) rview.getTag();
    }

    mArtLoader.loadBitmap(AL_songlist.get(position).getAlbumArtPath(), holder.imgAlbumart);
    holder.txtTitle.setText(AL_songlist.get(position).getTitle());
    holder.txtArtist.setText(AL_songlist.get(position).getArtist());

    if(Main.songService.svc_mpcontroller != null && Main.global_music_controller != null) {
        if (AL_songlist.get(position).getID() == Main.global_music_controller.get_current_id()) {
            ColorStateList sColorStatePlaying;
            ColorStateList sColorStateNotPlaying;

            sColorStatePlaying = ColorStateList.valueOf(context.getResources().getColor(R.color.colorPrimary));
            AnimationDrawable animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.anim_current_song);
            holder.imgEQAnimation.setVisibility(View.VISIBLE);
            holder.imgEQAnimation.setImageDrawable(animation);
            holder.imgEQAnimation.setImageTintList(sColorStatePlaying);
            animation.start();
        }
    }

    return rview;
}

Upvotes: 0

Views: 230

Answers (1)

Dom
Dom

Reputation: 8372

First I will explain view recycling then I will get to your issue. Say you can see 8 list items on the screen at one time. When you scroll the list down and item number 1 goes off screen and item number 10 comes on screen, item number 10 will reuse item number 1s view. This means that item number 10 will look exactly like item number 1 unless you update it accordingly in your adapters getView method.

Now that we understand View recycling you can see why other items will have your new drawable even though you didn't click them. You will have to store in your dataset that you use for your adapter which items have that image, whether it be an ArrayList in the Adapter or it be a custom object that the Adapter uses. Then in the getView of your adapter you could do the following:

if(hasImage)
{
    ColorStateList sColorStatePlaying;
    ColorStateList sColorStateNotPlaying;

    sColorStatePlaying = ColorStateList.valueOf(context.getResources().getColor(R.color.colorPrimary));
    AnimationDrawable animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.anim_current_song);
    ImageView EQ_ANIM = (ImageView) view.findViewById(R.id.imageView_eq_animation);
    EQ_ANIM.setVisibility(View.VISIBLE);
    EQ_ANIM.setImageDrawable(animation);
    EQ_ANIM.setImageTintList(sColorStatePlaying);
    animation.start();
}
else
{
    // Set the default image
}

Edit: You should add an else statement in your getView

    if(Main.songService.svc_mpcontroller != null && Main.global_music_controller != null) {
        if (AL_songlist.get(position).getID() == Main.global_music_controller.get_current_id()) {
            ColorStateList sColorStatePlaying;
            ColorStateList sColorStateNotPlaying;

            sColorStatePlaying = ColorStateList.valueOf(context.getResources().getColor(R.color.colorPrimary));
            AnimationDrawable animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.anim_current_song);
            holder.imgEQAnimation.setVisibility(View.VISIBLE);
            holder.imgEQAnimation.setImageDrawable(animation);
            holder.imgEQAnimation.setImageTintList(sColorStatePlaying);
            animation.start();
        }
    }
    else
        holder.imgEQAnimation.setVisibility(View.GONE);

Upvotes: 1

Related Questions