0

When implementing Palette with my GridView, I am having trouble with scrolling.

Basically, here's the situation: Each one of the items in the GridView has a title bar and an Image that loads. Using the Palette, the title bar is supposed to change to the extracted color that the Palette extracts.

But what happens is that every time I scroll down the Grid View, and then scroll back up, the positioning changes with the bar background color.

Here's an example:

enter image description here

Then when I have scrolled down and scrolled up again:

enter image description here

Also, the coloring doesn't seem to be quite right either does it? for some reason it looks like it just selects the last color that was loaded, and sometimes it doesn't even load at all as you can see looking at the bars.

I am doing this in my Album Adapter, here's the code and hopefully someone can guide me in the right direction.

public class AlbumAdapterNew extends ArrayAdapter<String> {

ArrayList<String> names;
Activity context;
ArrayList<String> coverPaths;
String coverPath;
Drawable img;
Bitmap bitmap;
ViewHolder mViewHolder = null;
ImageLoader imageLoader = ImageLoader.getInstance();
private RelativeLayout background;

static class ViewHolder {

    private TextView text;
    private ImageView image;

}

public AlbumAdapterNew(Activity context, ArrayList<String> names,
        ArrayList<String> coverPaths) {
    super(context, R.layout.albums_row, names);

    this.names = names;
    this.context = context;
    this.coverPaths = coverPaths;

    DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()

    .displayer(new FadeInBitmapDisplayer(500))

    .build();
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
            context)

    .defaultDisplayImageOptions(defaultOptions)

    .build();
    ImageLoader.getInstance().init(config); // Do it on Application start

}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    if (convertView == null) {
        mViewHolder = new ViewHolder();
        LayoutInflater vi = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.albums_row, parent, false);
        mViewHolder.text = (TextView) convertView
                .findViewById(R.id.albumTextView);
        mViewHolder.image = (ImageView) convertView
                .findViewById(R.id.album_photo);
        background = (RelativeLayout) convertView
                .findViewById(R.id.containerText);
        convertView.setTag(mViewHolder);

    }

    else {

        mViewHolder = (ViewHolder) convertView.getTag();

    }

    mViewHolder.text.setText(names.get(position));

    if (coverPaths.get(position) != null && !coverPaths.isEmpty()) {

        mViewHolder.image.setScaleType(ScaleType.CENTER_CROP);

        Glide.with(context).load("file:///" + coverPaths.get(position))
                .asBitmap()
                .into(new BitmapImageViewTarget(mViewHolder.image) {
                    @Override
                    protected void setResource(Bitmap resource) {
                        // Do bitmap magic here

                        Palette.from(resource).generate(
                                new Palette.PaletteAsyncListener() {
                                    public void onGenerated(Palette palette) {
                                        Palette.Swatch vibrantSwatch = palette
                                                .getVibrantSwatch();
                                        if (vibrantSwatch != null) {

                                            background
                                                    .setBackgroundColor(vibrantSwatch
                                                            .getRgb());

                                        }
                                    }
                                });

                        super.setResource(resource);
                    }
                });

    } else {

        mViewHolder.image.setScaleType(ScaleType.CENTER_INSIDE);

        imageLoader.displayImage("drawable://" + R.drawable.music_record,
                mViewHolder.image);

    }

    return convertView;
}

}
Jack
  • 2,043
  • 7
  • 40
  • 69
  • Does your code run through `if (coverPaths.get(position) != null && !coverPaths.isEmpty())` for every cell when scrolling up? Maybe not, and that might be the problem (since `Palette` is only used there). – shkschneider Jul 02 '15 at 15:43
  • Why wouldn't it go through that again? it doesn't make much sense to me. – Jack Jul 02 '15 at 15:46
  • My idea was that the recycled view was wrong, or that the source image was wrong. But that was just an idea, I don't have a precise answer, hence the simple comment :) – shkschneider Jul 02 '15 at 15:48
  • hmm yeah, that's the only might be the only logical explanation for the wrong colors as well. I'm not sure what I can do. – Jack Jul 02 '15 at 15:51
  • I have also found another question that hasn't been answered with the exact same problem as I am having - http://stackoverflow.com/questions/27498142/palette-library-changing-colors-while-scrolling-in-gridview – Jack Jul 02 '15 at 15:56

1 Answers1

0

When you create your Palette, you should save it to your ViewHolder in the callback. Apart from Palette being expensive to create, this always keeps your Palette instances in sync with the grid item being handled as you bind the data from the ViewHolder.

EDIT: As requested, a sort-of example. I didn't have a computer with the SDK handy, so this is from memory, but it should get you going in the right direction!

    public class AlbumAdapterNew extends ArrayAdapter<String> {

    ArrayList<String> names;
    Activity context;
    ArrayList<String> coverPaths;
    String coverPath;
    Drawable img;
    Bitmap bitmap;
    ImageLoader imageLoader = ImageLoader.getInstance();

    static class ViewHolder {

        private TextView text;
        private ImageView image;
        private Palette palette;
        private RelativeLayout background;

    }

    public AlbumAdapterNew(Activity context, ArrayList<String> names,
                           ArrayList<String> coverPaths) {
        super(context, R.layout.albums_row, names);

        this.names = names;
        this.context = context;
        this.coverPaths = coverPaths;

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
            .displayer(new FadeInBitmapDisplayer(500))
            .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
            .defaultDisplayImageOptions(defaultOptions)
            .build();
        ImageLoader.getInstance().init(config); // Do it on Application start

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // This should be local so you don't get conflicts
        ViewHolder viewHolder;

        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater vi = LayoutInflater.from(parent.getContext());
            convertView = vi.inflate(R.layout.albums_row, parent, false);
            viewHolder.text = (TextView) convertView
                    .findViewById(R.id.albumTextView);
            viewHolder.image = (ImageView) convertView
                    .findViewById(R.id.album_photo);
            viewHolder.background = (RelativeLayout) convertView
                    .findViewById(R.id.containerText);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.text.setText(names.get(position));

        if (coverPaths.get(position) != null && !coverPaths.isEmpty()) {
            viewHolder.image.setScaleType(ScaleType.CENTER_CROP);
            Glide.with(context)
                    .load("file:///" + coverPaths.get(position))
                    .asBitmap()
                    .into(new BitmapImageViewTarget(viewHolder.image) {
                        @Override
                        protected void setResource(Bitmap resource) {
                            // Do bitmap magic here

                            if(viewHolder.palette != null) {
                                setViewBackgroundColor(viewHolder)
                            } else {
                                Palette.from(resource).generate(
                                    new Palette.PaletteAsyncListener() {
                                        public void onGenerated(Palette palette) {
                                            viewHolder.palette = palette;
                                            setViewBackgroundColor(vh);
                                        }
                                    });
                            }
                            super.setResource(resource);
                        }
                    });
        } else {
            mViewHolder.image.setScaleType(ScaleType.CENTER_INSIDE);
            imageLoader.displayImage("drawable://" + R.drawable.music_record,
                    mViewHolder.image);
        }

        return convertView;
    }

    private void setViewBackgroundColor(ViewHolder vh) {
        Palette.Swatch swatch = vh.palette.getVibrantSwatch();
        if(swatch != null) {
            vh.background.setBackgroundColor(swatch.getRgb());
        }
    }
}
berwyn
  • 986
  • 7
  • 23
  • Good point indeed (Palette is *still* expensive), but I guess that should be a comment as it does not solve the OP's problem. – shkschneider Jul 02 '15 at 16:14
  • Yeah, the expensive part was an aside, but caching the Palette and using it from the ViewHolder should solve the issue, since that doesn't have to recalculate on the fly and use stale references to views – berwyn Jul 02 '15 at 16:16
  • Could you give me an example on how I can use it from my View Holder please? – Jack Jul 02 '15 at 17:13
  • Also, if you do that, then the Palette isn't going to be accessed in a static way like it says. – Jack Jul 02 '15 at 18:19
  • I've edited my response with a code sample that should get you started! – berwyn Jul 02 '15 at 19:14
  • @atomicrat2552 Thank you very much for the example. I have tried this code and the problem still persists when I scroll up :(. – Jack Jul 03 '15 at 11:07