Image ratio shows not properly - android

Into this adapter, I build dynamically the imageview size into the viewholder constructor:
ContentViewHolder(View view, Context context) {
super(view);
ButterKnife.bind(this, view);
// Set image width + height
mImageView.getLayoutParams().width = Math.round(UIUtils.getScreenWidth() / 4f);
mImageView.getLayoutParams().height = Math.round(
mImageView.getLayoutParams().width / Defines.FORM_LIST_FORMAT);
}
To show images, I use Glide (with crossfade effect; I tried without and the result is the same...).
And the result is not good: the first images have a bad image displaying...
Could you give some ways to fix it please?

Add android:scaleType="centerCrop" in your XML layout, or mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP) if you want to do it programmatically.

Related

How to make onBindViewHolder less expensive?[Android]

I read many articles about optimization and UI performance improvement of recyclerview. Their main point is make onBindViewHolder lighter.
List of issues I have :
My item layout has a frameLayout to show video with different width and height .I want to change the aspect ratio of frame layout according to video. My code inside onBindViewHolder is:
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) frameLayout.getLayoutParams();
if ((float) height / (float) width > (float) 1.25) {
params.dimensionRatio = "4:5";
} else {
params.dimensionRatio = width + ":" + height;
}
frameLayout.setLayoutParams(params);
This is the cause of lag. I can clearly observe. Tell me how instagram,Twitter show different ratio of video in their feed without lag
I have custom recylerView I'm creating a viewHolder instance inside it and performing some actions such as:
addOnChildAttachStateChangeListener(new OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(#NonNull View view) {
VideoAdapter.ViewHolder holder = (VideoAdapter.ViewHolder) view.getTag();
holder.styledPlayerView.setPlayer(exoPlayer);
holder.framelayout.addView(holder.styledPlayerView);
}
I'm doing this inside the recyclerView class. I think it is a part of onBindViewHolder as the action is on current instance of viewHolder. here adding view to frame layout is expensive. How to handle this?
I'm using 4 shape drawable,4 vector drawable & 3 custom styles. I can clearly see that when I'm using drawable it is lagging but after removing drawable the lag is decreasing to 40-50%

Google Ads MediaView not correctly resizing height to wrap_content when displaying image

I got an email from AdMob today saying:
Change to native ads policy: Native ads will require MediaView to
render the video or main image asset. In an effort to help you deliver
a better ad experience more easily, beginning October 29th, native ads
will require MediaView to render the video or main image asset. Ad
units not compliant by this date will stop serving ads, which could
impact your ad revenue.
I tried this out in my Android app, removing the separate handling of images with ImageView and video with MediaView, but I have found that the MediaView is not resizing the view's height according to the height of the image it displays.
In this codelab example from Google, a fixed height and width for the MediaView are used. I cannot do this, as this screen is responsive to the screen size, which will change depending on the device. The fact that the image can be dynamically resized is one of the main benefits for using UnifiedNativeAds instead of predefined ads such as banners.
This is how I need to be displaying the MediaView, using match_parent for width and wrap_content for height.
<com.google.android.gms.ads.formats.MediaView
android:id="#+id/ad_media"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:scaleType="fitXY"/>
This is what I am currently getting from the above code
This is what I need and expect it to look like from using wrap_content
In the previous case where we were able to render the images separately using ImageView, the wrap_content value correctly sized the image.
Does anyone have a workaround for this? How can I follow the new Google requirements without hardcoding the MediaView's height?
My full code can be found here, in my demo app on github.
mediaView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
#Override
public void onChildViewAdded(View parent, View child) {
if (child instanceof ImageView) {
ImageView imageView = (ImageView) child;
imageView.setAdjustViewBounds(true);
}
}
#Override
public void onChildViewRemoved(View parent, View child) {}
});
I was facing the same problem, after trying a lot with trial and error, I found that wrapping <FrameLayout...>(in which you are adding UnifiedNativeAdView) with ScrollView will resolve this problem.
If implementing Advanced Native Ads, use "imageScaleType" property of MediaView as suggested here in the official docs https://developers.google.com/admob/android/native/advanced#setting_imagescaletype
adView.mediaView.setImageScaleType(ImageView.ScaleType.CENTER_CROP)
or any other ScaleType as per requirement.
To ensure that all media are as wide as possible and that they respect a maximum height (so there are no surprises depending on the dimensions of the media).
XML
<com.google.android.gms.ads.formats.MediaView
android:id="#+id/ad_media"
android:layout_gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
JAVA
mediaView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
#Override
public void onChildViewAdded(View parent, View child) {
float scale = context.getResources().getDisplayMetrics().density;
int maxHeightPixels = 175;
int maxHeightDp = (int) (maxHeightPixels * scale + 0.5f);
if (child instanceof ImageView) { //Images
ImageView imageView = (ImageView) child;
imageView.setAdjustViewBounds(true);
imageView.setMaxHeight(maxHeightDp);
} else { //Videos
ViewGroup.LayoutParams params = child.getLayoutParams();
params.height = maxHeightDp;
child.setLayoutParams(params);
}
}
#Override
public void onChildViewRemoved(View parent, View child) {}
});
for (int i = 0; i < mediaView.getChildCount(); i++) {
View view = mediaView.getChildAt(i);
if (view instanceof ImageView) {
((ImageView) view).setAdjustViewBounds(true);
}
}
This works for me.I tried Richard's answer,But it didn't works well in a RecyclerView.

Center-crop an image into an ImageView with variable size?

I have a recycler view that has items with variable sizes. Now, I'm loading images using Picasso and I'd like to resize the pictures to fill the ImageView, preserving aspect ratio and by cropping the image so that it fits the ImageView perfectly. However, the width of the ImageView is 0 during the time the view holder is bound. How do I get the size?
The code looks something like this:
#Override
public void onBindViewHolder(ViewHolder holder, final int position)
{
Foo foo = mFoos.get(position);
// Get the size - THIS IS WHAT I WANT TO FIND OUT
int width = ...;
int height = 100;
// Load the image using Picasso
Picasso.with(mContext)
.load(foo.getImageURL())
.centerCrop()
.resize(width, height)
.into(holder.image);
}
That's because view measurement has not jet been made. So at that point width is actually 0.
You need to implement ViewTreeObserver
Take a look at some of these examples:
How to get the width and height of an Image View in android?
How to get the width and height of an android.widget.ImageView?

Setting ImageView width and height before drawing in a ListView adapter

I have an adapter to a ListView is a list of ImageViews. I am using a stretch to make the image fil the imageview so I can take smaller images and make them larger on the screen, however the ImageView normally just uses wrap_content and this is an issue because the images just show up as their normal width and height. Is there any way I can set the height and width of a view before drawing it because as in this case I do not have control over the view after it has been drawn. Here is my aapter method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String currentImage = getItem(position);
ScaleType scaleType = ScaleType.FIT_CENTER;
float screenWidth = parent.getResources().getDisplayMetrics().widthPixels;
if (convertView == null) {
convertView = new ImageView(parent.getContext());
}
// WHAT I WOULD LIKE TO BE ABLE TO DO, but this returns null pointer exception
// convertView.getLayoutParams().width = (int) screenWidth;
// convertView.getLayoutParams().height = (int) ((float)(screenWidth/currentImage.getWidth())*currentImage.getHeight());
((ImageView) convertView).setScaleType(scaleType);
((ImageView) convertView).setImageBitmap(MainActivity.cache.getBitmap(currentImage));
return convertView;
}
How about something like someView.setHeight() and someView.setWidth()? Or someView.setLayoutParams()? You could add either of these to the overridden getView() callback and it should take care of your problem.
You could also Create a Custom View and override something like getMeasuredWidthAndState(). (I think that's one of the right methods, but I'm not one hundred percent sure.) You could create a width class variable and a height class variable that all instances of your custom ImageView would use. However, that might be a bit much if you just want to set the layout width and height though.

How to make an Image as large as possible while maintaining aspect ratio

I have an image which is smaller than the container I would like it to fit inside of. I would like the image to stretch, keeping it's aspect ratio, to it's largest possible size.
To illustrate this problem:
<ImageView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/thumbnail"
android:scaleType="fitXY"
android:adjustViewBounds="true"/>
The ImageView above would be stretched to fill the width of the container. The #drawable it contained would also stretch along the x axis to fit the width of ImageView which is perfect. The problem however is that the dimension labelled wrap_content, in this case height, remains the same size as the #drawables initial height.
I have read the documentation regarding ScaleType here and can't find the answer there.
The following image describes the above code:
Current behaviour Desired Behaviour
Edit
An ImageView given scaleType="fitCenter" will accurately expand/shrink the #drawable inside of it to grow as large as possible while retaining it's aspect ratio.
The ImageViews dimensions are defined before the #drawable is scaled in any way. The ImageView dimensions are not effected by scaling of it's contained #drawable.
XML
The only solution to this in XML is to use "match_parent" or a discrete maximum value instead of "wrap_content" where possible. This will ensure the ImageView is the correct size, which will then meaning adding scaleType="fitCenter" will ensure the #drawable will then scale correctly.
Programatically
It's ugly, but you can resize the ImageView after it's dimensions have been given discrete values:
final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail);
ViewTreeObserver thumbnailViewVto = thumbnailView.getViewTreeObserver();
thumbnailViewVto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
private boolean changed = false;
#Override
public void onGlobalLayout() {
if(!changed) {
Drawable image = getResources().getDrawable(R.drawable.thumbnail);
float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight();
int height = thumbnailView.getHeight();
thumbnailView.setLayoutParams(
new LayoutParams(
(int) (height * heighToWidthRatio), height));
changed = true;
}
}
});
EDIT
final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail);
thumbnailView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Remove the GlobalOnLayout Listener so it only fires once.
thumbnailView.getViewTreeObserver().removeGlobalOnLayoutListener(this)
// Find the images Height to Width ratio
Drawable image = getResources().getDrawable(R.drawable.thumbnail);
float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight();
// Use this ratio to discover the ratio of the ImageView to allow it to perfectly contain the image.
int height = thumbnailView.getHeight();
thumbnailView.setLayoutParams(new LayoutParams(
(int) (height * heighToWidthRatio), height));
}
});
Looks like you want fitCenter, which uses Matrix.ScaleToFit CENTER.

Categories

Resources