I have a RecyclerView (It is actually a chat). The users can send images and text. The problem is when I scroll it feels laggy because the images are being loaded (If I go down and up, it takes to much time to Picasso to bring the image back again). And I'm using this line of code to do it.
Picasso.with(itemView.getContext())
.load(((ChatMediaMessage) message).getUrl())
.into(imageView);
If I use the resize option is not laggy at all, but the images lose the image ratio obviously.
Picasso.with(itemView.getContext())
.load(((ChatMediaMessage) message).getUrl())
.resize(400, 400)
.into(imageView);
The layout of the ViewHolder looks like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp">
<com.stfalcon.chatkit.utils.ShapeImageView
android:id="#id/messageUserAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_marginRight="8dp" />
<com.google.android.flexbox.FlexboxLayout
android:id="#id/bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/message_incoming_bubble_margin_right"
android:layout_toRightOf="#id/messageUserAvatar"
android:orientation="vertical"
app:alignContent="stretch"
app:alignItems="stretch"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerInside" />
<TextView
android:id="#id/messageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#id/messageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/messageText"
android:layout_marginLeft="8dp"
app:layout_alignSelf="center" />
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>
Don't use adjustViewBounds for dynamically-loaded images, because it will trigger a full relayout after each image completes loading. Set a fixed size to your ImageViews instead, and use centerInside scale mode if you want to preserve aspect ratio, or centerCrop if you prefer to crop the image. This tip applies to any image library.
Furthermore, when the ImageView has a fixed size, Picasso or Glide allows you to resize the image to it automatically, which reduces memory usage and improves performance. For Picasso, use:
Picasso.with(itemView.getContext())
.load(((ChatMediaMessage) message).getUrl())
.fit()
.centerCrop()
.into(imageView);
You can also use centerInside() instead of centerCrop().
Glide has a similar API. It will provide slightly better performance than Picasso because it caches the resized images to disk as well, while Picasso only caches the full-size images to disk and will have to resize them each time they are loaded back from disk.
Have you try Glide? Give it a try. Just add the library on dependencies and only replace the Picasso word.
Is your image size bigger, like 2Mb above? Try resizing or optimizing the image before upload it anywhere.
Is your image JPG? You can use RIOT http://luci.criosweb.ro/riot/
to optimize your JPG/PNG.
Or it's advisable to convert your JPG images into WebP. Android Studio has the built in converter to try. WebP loads faster and smaller in size.
Related
I am making a chat application. For that, if the message is of image type, I want to wrap the height and fix the width. But the problem is that since image takes some time to load, there is a shift in chat messages until the image is loaded and so there is a jerk. How do I handle this?
<android.support.constraint.ConstraintLayout
android:id="#+id/parent_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/send_message_box"
android:maxWidth="228dp">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/iv_message"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="200dp"
android:layout_height="0dp"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:padding="11dp"
android:visibility="gone" />
</android.support.constraint.ConstraintLayout>
This is the image layout I am using.
You could fix the height and display a placeholder image till the image gets loaded. You get this functionality of displaying a placeholder image(till the image gets loaded) with Picasso, check this https://square.github.io/picasso/
You can set up an initial height using a default image while your images are getting downloaded. After the image is downloaded, it will take the height of the image if you set the height as wrap_content. Hence you need to modify your ImageView like the following.
<ImageView
android:id="#+id/iv_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#mipmap/ic_image_loader_placeholder" />
Please modify the ImageView as per your requirement.
You might also look at this Github project where I have implemented a similar idea. I had to call an API of Flickr and load the images into the RecyclerView. Hope that helps!
I am working with an application in which I have more work with images. I want to show profile pictures and Article images in my app. For article images I have tried scale type of ImageView to "fitcenter or centercrop or fitxy" but nothing works fine. My image pixel's are distorted. I am using Glide library to show image on sever. I have even tried .fitcenter() etc. Glide methods but nothing works so that my image work fine with ImageView.
Code:
<ImageView
android:id="#+id/imgArticle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#drawable/blank_image" />
Glide Code:
Glide.with(context).load(articleList.get("article_image"))
.thumbnail(0.5f)
.placeholder(context.getResources().getDrawable(R.drawable.blank_image))
.fitCenter()
.into(imgBanner);
I have tried various methods i.e. fitcenter, centercrop etc. but nothing works.
android:scaleType="fitXY" will stretch your image. You can try this code so that image will not stretch.
<ImageView
android:id="#+id/imgArticle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/blank_image" />
Or you can adjust the height and width as per your UI
<ImageView
android:id="#+id/imgArticle"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/blank_image" />
I am implementing something called InApp messages, now I am trying to fit ImageView to image size after resizing.
This is my imageView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="40dp"
android:padding="6dp">
--other components--
<ImageView
android:id="#+id/middleLayoutImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/border"
android:padding="5dp"
app:layout_constraintBottom_toTopOf="#+id/middleLayoutText"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/topWrapper"
app:layout_constraintVertical_chainStyle="packed" />
--other components--
</android.support.constraint.ConstraintLayout>
To download img and put into this view I am using Picasso:
Picasso.with(getApplicationContext())
.load(inputurl)
.into(imageView);
Now my activity looks like this:
Before fitting
Now I want to resize it with aspect ratio to width of the parent Layout. I've tried a lot od combinations with no success:
android:scaleType="fitXY" - stretched img
picasso fit().centerCrop() - centerCrop
picasso fit().centerInside() - centerInside
and more combination with android:adjustViewBounds scaleTypes etc.
I want to achieve something like this: Resized correctly - in this case, I've used picasso: .resize(2000,500).centerInside() - but it will work only in this case.. How to do it automatically ?
Thanks in advance for help:)
edit:
ImageView imageView = (ImageView) findViewById(R.id.middleLayoutImage);
String inputurl = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQtqf1EUqH4eQNNqYFbSawpiR5bypfOhvlatgS0mC3Ve1nk2adbw"; //http://www.gatesms.eu/img/android.png";
Picasso.with(getApplicationContext())
.load(inputurl)
.resize(2000,500)
.centerInside()
.into(imageView);
For Picasso to fit your Image correctly you should know the size of your Image. But for this case You do not know the size of the Image then for good UI design you should have a placeholder (An image to show while Picasso is loading another) keep that image in your drawable folder lets call it placeholder and set it as a src or alternatively using Picasso itself like this:
Picasso.with(getActivity())
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.resize(screenWidth, imageHeight)
.fit()
.centerCrop()
.into(imageView);
Now what?
Now because you have another Image in the imageView Picasso now knows the height and width so that It can fit your Image well. But if you do not provide any image then the results are very small images or improperly stretched ones. I have also added an optional error image that will be displaced if Picasso fails to make the request like my be No network Connection you can omit it if you want.
Do not forget the android:adjustViewBounds in XML too.
Hey everyone I have been running into an issue with Picasso. I am trying to load an image from sound cloud but it keeps appearing stretched or very small. Here is my XML
<ImageView
android:id="#+id/album_cover_art"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="#dimen/fragment_content_item_top_margin"
android:scaleType="centerInside"
android:contentDescription="#string/content_description_image_placeholder"
android:src="#drawable/placeholder" />
I tried to use picasso's resize and center inside but the image appears small.
Picasso.with(getContext()).load(mSelectedTrack.getArtworkURL()).resize(800,300).centerInside().into(mAlbumCoverArt);
Using picasso's resize and center crop maintains the image view size but leads to the image appearing stretched.
Picasso.with(getContext()).load(mSelectedTrack.getArtworkURL()).resize(800,300).centerCrop().into(mAlbumCoverArt);
Any ideas on a way to do this that is easier than writing a function to resize it myself ?
I avoided image stretching using :
.resize(800,0)
Passing 0 as second parameter it preserved the image proportions.
Hope it helps
try this:
for your imageview:
<ImageView
android:id="#id/img"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" //add this
android:scaleType="fitCenter" />
And in picasso use .fit().centerCrop()
Picasso.with(getContext()).load(mSelectedTrack.getArtworkURL()).resize(800,300).fit().centerCrop().into(mAlbumCoverArt);
Try setting height or width to fixed and other to wrap content and load Picasso with .fitXY and don't use . resize.
Give a try to Glide.
https://github.com/bumptech/glide
Glide.with(this)
.load(imageUrl)
.centerCrop()
.override(300, 300)
.into(imageView);
I try to display 3 images medium size.
The problem is that they display in low quality and it damages the UI a lot,I checked over the internet and the best solution is to use is Piccaso,but I want to know how can I display the image in it's full quality without third-library?
I load images like this:
<ImageView
android:id="#+id/btnring"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/itayring1"
/>
and I also tried this:
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.itayicon);
b1.setImageBitmap(bb);
When I used Eclipse I could load images easly. There must be a way to do in Android Studio too,
Thanks.
Put Images in xhdpi drawable image only and try this code :
<ImageView
android:id="#+id/btnring"
android:layout_height="50dp"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:src="#drawable/itayring1"
/>