Device screen dimension has weird effect on scaled ImageViews - android

Update:
The multiple device screen dimensions is a red herring - the problem is just that the image does not scale up properly to fill the screen - see comments on Ivan's answer.
I have a layout file with one image:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
Then I assign a drawable, which is small and must be scaled up:
setContentView(R.layout.image_story);
ImageView image = (ImageView)findViewById(R.id.image);
image.setImageDrawable(s.image);
Here is how it is rendered on two AVDs with different screen dimensions. These should be the same (detailed question at the bottom). Sorry for the large images.
with scaleType=centerCrop:
with centerInside
AVDs:
Edit:
With layout_height="fill_parent" and scaleType="centerInside"
I have a 2.1 AVD with the default values, so the screen is smaller, and this works exactly as expected- the image is scaled up to fill the width, and the view height is wrapped to the scaled height.
On my Droid Bionic with a longer screen, and on any AVD with the same screen dimensions, this doesn't work- the image is scaled to fill the width, but the view is wrapped to the original pre-scale image height, so the top and bottom are cropped off.
I have no idea why the device screen aspect ratio would have an effect on this. I've tried countless combination of layout parameters and scale types trying to get this to work on the Bionic. Everything works exactly as expected on the smaller screen, and not on the larger. If I set the image height explicitly in dp, it works as expected, but I never know what the dimensions of the image (or screen) will be. Any suggestions?

That is a very good question indeed.
Here's the reason it's behaving like that (from ImageView.onMeasure(int, int) [line 661]):
// Try adjusting height to be proportional to width
if (!done && resizeHeight) {
int newHeight = (int)((widthSize - pleft - pright)
/ desiredAspect) + ptop + pbottom;
if (newHeight <= heightSize) { // line 661
heightSize = newHeight;
} // line 663
}
What it does is it adjusts the height of the view only if the new height that is based on aspect ratio of the drawable and the adjusted width (in our case, that's exact width of the parent view) is smaller than the adjusted height (which at this poin is just drawable's native height plus padding in our case. Let me know if you want me to brake down this point further.)
What I don't get is why is there the restriction that new height must be smaller. It makes sense only if our heightSize is either EXACTLY or AT_MOST and has been set to the upper bound. In other cases it's not necessary for it to be so.
So actually instead of the whole piece 661 through 663 there should have been another call to
heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSpec);
to make sure we only use the height restriction when it should be restricted (ie. we got AT_MOST restriction in heightSpec and the height value in heightSpec is smaller than the new height. EXACTLY can't happen here unless we use variable width.)
Maybe, I missed something there. Guys, whoever is reading this, please comment if you see any flaws in that, especially if you're part of Android team at Google :)
PS As a workaround, I can suggest you implement a custom ImageView and override onMeasure(int, int) to set the bounds to your exact aspect ratio. Let me know if you need help on the actual code.
UPD I'm going to write out names to catch attention of smart android guys at Google (I'm hoping the guys have Google Alerts set up): Romain Guy, Roman Nurik, Reto Meier, please, take a look at this discussion.

As I understand, you need to scale the image maintaining its aspect ratio. scaleType="fitCenter" should give you the desired behavior:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
If it doesn't help, try adding this to the manifest file:
<supports-screens
android:resizeable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />

Related

FFImageloading xamarin android fit to parent

I am creating a android app in Xamarin with the mvvmcross framework.
Am trying to display pictures from the server to our users(the pictures are Urls). But the pictures refuse to scale to fill their parent.
How can I achieve the right fit for these images? , I use the FillParent on the Width tag. But the images refuse to scale to the size of the container.
My current setup
<FFImageLoading.Cross.MvxImageLoadingView
android:id="#+id/my_plannymap_listitem_title_picture"
android:layout_width="fill_parent"
android:layout_height="150dp"
local:MvxBind="DataLocationUri ImageUrl; Click OpenDetailCommand" />
above code creates(sorry for the volume thing), As you can see the images do not fill, they remain their "original" size
other activity (same problem here)
<FFImageLoading.Cross.MvxImageLoadingView
android:layout_width="fill_parent"
android:layout_height="150dp"
android:scaleType="fitCenter"
android:id="#+id/overview_image"
android:background="#580AB0"
local:MvxBind="DataLocationUri ImageUrl"
TransparencyEnabled="false"
DownSampleToFit="true" />
It sounds like you want to fix the height to 150dp, and fix the width to the width of the parent. If that is the case it can be done, but it will stretch any image that isn't the correct aspect ratio to begin with.
<FFImageLoading.Cross.MvxImageLoadingView
android:id="#+id/my_plannymap_listitem_title_picture"
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
local:MvxBind="DataLocationUri ImageUrl; Click OpenDetailCommand" />
(note I used match_parent since fill_parent is deprecated)
If you don't want your image to stretch in a strange way and you can't guarantee that the aspect ratio of incoming images matches that of your layout, you need to select one aspect (either width or height) to dictate the size of the other, in such a way that the ratio remains unchanged. You can do that with the following (in this case you're deciding the width, and calculating the height from it based on the image's aspect ratio):
<FFImageLoading.Cross.MvxImageLoadingView
android:id="#+id/my_plannymap_listitem_title_picture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
local:MvxBind="DataLocationUri ImageUrl; Click OpenDetailCommand" />
In almost all cases where you cannot guarantee the aspect ratio of the image you're scaling, the second option gives a better result than the first.

ImageView Scaling: fix height variable width with maxWidth

I am going to show some images, but my constraint is as title. I want to make all images have same height but according to their width they must have different width. I just do not want to lose any part of the image when scaling. here is my code:
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/ImageView_IssueFirstLookActivity_magas"
android:layout_width="wrap_content"
android:layout_height="170dp"
android:layout_marginLeft="32dip"
android:layout_weight="2"
android:maxWidth="40dp"
android:adjustViewBounds="true"
android:scaleType="fitStart" />
I tried all I could with different values of android:scaleType but get nowhere.
here is a figure that what I want but when I play with those properties it dose not scale it as I want for example some time it dose not show image width completely and it crops it badly. Another try for example is android:scaleType="fitStart" which cause the width of my images to be fine but the heights are not fit anymore. Any idea?
andriod ImageView attributes does not support the requirement you said just by statically choosing combination of width,height and saleType in the layout xml.
Instead you can do it in the java code by actually finding the width for the image for a given fixed height and setting them programattically to each view in dp(make sure you do the pixel to dp calculation for achieving right output, salable across devices)
If you don't mind an extra dependency, you can do it with Picasso
Picasso.get()
.load(R.drawable.my_image_resource)
.placeholder(R.drawable.ic_image_placeholder)
.error(R.drawable.ic_broken_image)
.resize(0, (int) imagefixedHeight)
// optional:
// .centerInside()
.into(myImageView);

Android 2.3 & above: How to draw 2 squares of biggest size in either portrait or landscape mode

My Android app is for Gingerbread and above. It creates screen output of a graph and a text table. Each is square in shape and drawn using an imageview. These are placed with the layout xml separately within a linear layout. I want the squares the same size and as large as possible. In portrait mode they are stacked and in landscape mode they are side by side. There is nothing else drawn by the app.
I use this code to get a notion of what size squares to draw:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
height = metrics.heightPixels;
width = metrics.widthPixels;
....
landscape=width>height;
//use fudge factor for vertical display (account for title bar, etc.)
if (!landscape)
graphSize=(int) (0.9f*(float)height/2.0f);//reduce by 10%
if (landscape)
graphSize=width/2;
I use graphSize to set the size of the imageviews for output.
Recognizing that the width and height provided by the metrics only gives an approximation (for numerous reasons I do not wish to get into), I simply reduce the height by a fudge factor when sizing my squares. In landscape mode using width over 2 as the square size gives a good display which makes fairly good use of the available screen space. In portrait mode using height/2 works poorly: the second drawn square is diminished in size. So I reduce the height by 10% then divide by two to get the square size. This works but does not make good use of the available space. Any suggestions?
Might be you want something like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<ImageView
.
.
.
android:layout_weight="1" />
<ImageView
.
.
.
android:layout_weight="1" />
</LinearLayout>

Photo: wrap_content, but max_width = layout width

I have a normal "read an article" type page with a single large photo at the top.
I'd like it to:
not scale larger than the source imgae
not be larger than the screen
not be CRAZY long vertically
side things I already have working
border (via padding), center crop (would rather top crop, but seems not avail)
The main issue I'm having is - I can either have it fill_parent (ie full width) OR wrap_content (ie as large as the original image). And nothing I have done so far allows the image to be normal size (ie keep from enlarging).
Is there a "norm" for this kind of thing? I'm sure there's some kind of sweet spot or combination of attributes for this that works - I just can't find them.
My current attempt:
<ImageView
android:id="#+id/article_photo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/super_light_gray"
android:scaleType="centerCrop"
android:contentDescription="#string/articlePhoto"
android:cropToPadding="true"
android:layout_marginBottom="20dp"
android:padding="1dp"/>
You can write some code in the Activity to get the image size and display size.
If the image size exceeds display size set width to display, if not set to image size. If you want to be fancy you can find the ratio between the x and y and scale vertically also.

android image view in list will not scale to width

New to Android, bad with layouts so this is probably a simple solution but I can't find it. I am adding an image to a ListView, the ListView is defined like this:
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
Image is added like this:
ImageView image = new ImageView(context);
image.setScaleType(ImageView.ScaleType.FIT_CENTER);
image.setAdjustViewBounds(true);
image.setImageDrawable(drawable);
return image;
in the ListAdapter. I want the Image to scale so the width fills the screen and the height adjust proportionally. What is happening is the image is scaling down so the height fills the list row but there is plenty of room for the width to be bigger. I had this working earlier but can't figure out what changed. Why is the image shrinking to some seemingly arbitrary height and how do I get it to fill the screen by width?
Edit:
So this happened when I started building for 1.6 instead of 1.5, probably a resolution thing. I guess the image is a bit sharper when it's small but I want it larger, it's almost unusable smaller and I am not able to get a larger image, it's from the web.
I think there is no really "simple" solution, but it's already answered here (without list's, but i don't think it matters):
Android: How to stretch an image to the screen width while maintaining aspect ratio?
Have you tried ImageView.ScaleType.FIT_XY ?
Scale Types

Categories

Resources