yayaa/ParallaxRecyclerView

Images being displayed at halfsize with Picasso.

Closed this issue · 21 comments

I'm using Picasso to load images in to my recycler view but the images are not the size i want. I have a set height of 180dp and match_parent of my ImageView yet the images are half the size, floating inside each row. It's very weird.

It's not on every image, but it's on the majority, the first image in the list always seems to be load fine, as you scroll though, all the images are half their size.

I have 3 different view types in my RecyclerVIew but i also have 3 ParallaxImageViews defined with the same id so it shouldn't be a problem.

The parallax works, but the images are totally messed up. I'm calling viewHolder.getBackgroundImage().reuse() at the top of my onBindVIewHolder.

I'm pretty sure it's to do with Picasso. I tried a local image and it went to the correct size.

This is my Picasso command:

Picasso.with(this).load(imageUrl).tag(this).placeholder(R.color.background).into(viewHolder.image);

Edit: Will add a screenshot

Screenshot

Edit 2: I tried using UniveralImageLoader and the same thing happens.

yayaa commented

Would you mind to try viewHolder.getBackgroundImage().reuse() at the end?

Because it will try to doTranslate the image onMeasure when it's once visible back in recyclerView, but since you're lazyLoading image it will try to getDrawable and return null then switch the reuse flag back off, before the image is loaded. Then when image is ready to display, it won't try to translate because reuse flag was already turned off.

See here to understand better.

I will try when I have some time. Sorry been a bit busy with other things. Would love to get this working so I'll try to find some time.

yayaa commented

Please keep me informed once you tried...

Just had some time to play with it. I moved the code to the bottom of my onBindViewHolder and I'm still getting the same issue.

yayaa commented

Ok, i don't know if that was a typo or not but in your original question you described your image loading as below:

Picasso.with(this).load(imageUrl).tag(this).placeholder(R.color.background).into(viewHolder.image);

So i guess you have a ParallaxImageView in your layout but you are trying to find it by yourself which you shouldn't do since the library has to access it by its structured.

You are returning resId in getParallaxImageId method right? If so, library already has the access to parallaxImageView so you need to load image into viewHolder.getBackgroundImage() not an instance that you populated by yourself because library has a listener on required instance and does some calculations to have parallax happened.

See ViewHolder for more information.

Hey, sorry for the late reply. I can't seem to get this to work so it's dropped in priority. I've got some time today to play with it.

I just tried your suggestion. Using viewHolder.getBackgroundImage() and I've still got the same problem. Half size images.

yayaa commented

Allright, since we are not able to get into same point, i updated the sample project with Picasso implementation. Please compare your code with the sample.

Strange. I tried your images in the exact same way and I got a better result, images were the same size, however they still didn't fit the width of the view. I tried a few bigger images off the internet (bigger width) and they did get the width closer.

So I thought great it's probably just image sizes. However I then used my URLs that I posted in my original image, and I got the same issue as my original post. The top image fits perfectly, the second one is tiny, and the third is bigger but not full width.

Maybe it is to do with image sizes? When you ran your sample app, did it's images match the width of the view? If they did then it's nothing to do with image sizes, however if you had the same issue then maybe we need a minimum size for this to work.

Edit: The only image that fits correctly, is one that has not been optimised by our designer... it's size is 2048 x 1467 and the optimized ones are 1242 x 815. I'll post a screenshot.

https://i.imgur.com/lWmoY6C.jpg - When using my images, top one is just taken from google, others are optimized.
https://i.imgur.com/YzfesdA.jpg - When using your images.

Ok I cloned your sample and ran it on my phone (Nexus 6P) and this was the result: https://i.imgur.com/ArVpEsW.jpg

So I think this is to do with image size, or maybe it's getting the height/width ratio wrong?

yayaa commented

Ok i see the problem now. I used scaleType Matrix to handle postTranslation, so it doesn't actually work like centerCrop and it will not adjust image's width and crop its height. Instead it'll just position centered height. So it's up to you to provide images to fit screen.

And i would suggest you to keep images same size. If you check, all images that i used in sample 1080 x 1560 because back then i created the library 1080 was the biggest screenWidth for phones... Your Nexus 6P has 1440 x 2560 that's why it's not fit in it.

The best solution would be having a backend which provides multiple sized images up to screen width of the device runs your application.

Right ok, that makes sense. Quite a big task to get this working in that case. I can see why parallax is not a big thing on Android now. Bigger images also means more memory taken up, which is why as you say it's needs to be done smartly on the backend and only the image size a device requires is sent across.

yayaa commented

Yes, unfortunately... But beauty comes with price :)
Since we elaborate the issue, and there is no suitable fix closing this one.

Is it worth adding something to readme? So others know that image sizes that are big enough is a requirement?

yayaa commented

Sure, adding it right away :) Thanks

I think this issue should be reopened. I did a bit more testing, and I was able to reproduce the issue when feeding a image URL to Picasso via a data object. Even when the image was the correct size. So it can't be the image size that causes this bug.

However when using a String[] array like in your sample, everything works fine.

See my screenshots:

Images when using a String array

Images when using an Object.get(position).getUrl()

Is it the way the reference to the ParallaxImageView is being held maybe? With a normal ViewHolder and ImageView, the images appear correctly in Picasso.

Also note that two images are the same size in those screenshots. The first one, that is not displaying correctly and the third one, which does display correctly (although cut off in the screenshot).

Let me know what you think.

yayaa commented

Hi @MiralDesai,

I guest the best way to handle this to scale image if it's smaller than screenWidth, i didn't want to do it so because that may cause performance issues but since it's a most likely a problem i implemented that feature based on this gist.

It is possible to deactivate centerCrop feature by calling setCenterCrop(false) in code or in layout app:center_crop="false".

But still i would suggest you to have same sized images to avoid having different parallax effects on images, because they will have same value (as default it's 1.2f) but different heights the calculated tranlate will be different one from another. You can try by adding this image into sample images "http://yayandroid.com/data/github_library/parallax_listview/test_image_0.jpg".

Alternatively you can try to resize the image within Picasso library then set it to parallaxImageView, that may also solve this issue. (Didn't try though.)

Please give v1.1 a try and let me know if that fixes or not.

I've just given v1.1 a try and it's working. Can't fully test because my office has terrible internet right now, but so for so good.

The only thing I noticed was that the parallax ratio is now a lot smaller. I know it's 1.2f, but 1.2f seems to do less now. The parallax effect is diminished a fair bit, but I guess I can change that myself anyway.

In regards to the image sizes, that was just me testing with random images. My production data has the images at the same size, so I'll give it a test on there too.

Seems like cropping to the centre is what was needed.

I'm off on holiday until Monday now but I'll continue to test when I get back and confirm this issue has been resolved. 👍

yayaa commented

Yes, cropping the center was the trick but i was thinking that might have caused memory or performance issues... As i checked memory allocation, GPU and CPU usage there is no significant change, but still i am a bit nervous about scaling images :) So i tried a lot to make it more optimised, and it is possible to disable center_crop if you are sure that you can handle it by only providing screenWidth sized images.

And yes, because images' scale changes the parallax ratio will be different from first solutions but you can change it from directly layout file or in java code.

Looking forward your feedbacks, and thanks a lot for baring with me to find out this issue :)

Happy to help. I've noticed two issues. Pretty small ones.

  1. The first is that the last image in my list had moved off it's position. I use CardViews behind my images, and on the last image I can see the CardView, because the image has moved. See the screenshot: https://i.imgur.com/2htAwrp.png

Notice how between the two images there is some white, that is the CardView showing because the image has moved. I have not experienced this where in my production app (with lots more images), only in my testing app with about 5 images. So it's a weird one.

  1. The second issue is that when I pull to refresh at the top of my RecyclerView all the images "pop" back to their original states. I assumed that when you scroll down and then back up the parallax would just be reversing itself so this wouldn't be an issue but maybe it is? I don't think this is a big issue, but it doesn't look great. I guess the parallax is different when scrolling up compared to scrolling down?
yayaa commented

First thing that you mentioned is probably because of your images height being different from each other but still having same parallaxRatio... Because in your production app, all images have the same height and the ratio, there is no problem. So i don't consider this as an issue, please state if this is not the case.

And the second one is about how you implement pullToRefresh, i would say nothing related to this library. Parallax is not up to moving up or down, it changes up to recyclerView's current scroll position so it re-calculate on any scroll.

If you confirm that the main issue is fixed, then i close this one... But please feel free to open up a new one, if you find a bug.

You're probably right about the first issue. I don't consider it a high priority.

Yeah main issue is fixed. Glad we got to the bottom of that