Image stretching - android

API 7 (2.1)
I'm implementing high resolution images for the drawable-hdpi folder of my app.
Along the bottom of my screen I have a LinearLayout with a fill_parent width. Inside, I have 3 LinearLayouts with a weight of 1. Inside these, I have an ImageView. In effect, I have 3 equally sized spaces for 3 images.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image1"
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="0dip">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image2"
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image3"
/>
</LinearLayout>
</LinearLayout>
When the phone is in landscape mode, everything looks fine.
When the phone is in portrait mode, the images are scaled down because their widths are too wide for their 1/3rd space on the screen. The images still look fine.
Here's my problem:
My images scale fine, but it appears the LinearLayouts wrapping each image do not scale their height.
In landscape mode, the top and bottom of the LinearLayouts wrapping the images share an edge. Meaning, the top of the ImageView is aligned with the top of the LinearLayout wrapping it, and the bottom of the ImageView is aligned with the bottom of the LinearLayout wrapping it. In other words, the height of the LinearLayout == the height of the ImageView.
In portrait mode, the top and bottom of the LinearLayouts wrapping the images have a bunch of space between them and the top and bottom of the images, almost like there is padding. In other words, the height of the LinearLayout > the height of the ImageView. This is not desirable.
Any ideas?
It's almost like it's sizing the LinearLayout and ImageView, then squishing the ImageView to fit, and then not resizing the LinearLayout...

You can try to design separate layouts for both orientations. In your project's res folder make a subfolder named layout-land. There copy or create a new layout with the same name. In this way you would have a complete control over the layout in any orientation.
Since you are using android:layout_weight="1" shouldn't linearLayouts equaly split the space hence an extra space would appear?
EDIT:
It seems that it is ImageView that expands its height when LinerLayout has weight set. Add this line to each of your ImageViews:
android:adjustViewBounds="true"

I know that this isn't answering the question you asked, but it seems like it would be better to avoid multiple problems by changing the orientation of your linear layout to vertical when the device orientation changes. I believe you can do that with an OrientationEventListener.

I suppose that its better to have another layout designed for the portrait mode.
Do not use the same layout for both portrait and landscape modes. It would be better to have different layouts for portrait and landscape modes so that the control of the design will be in our hands.

Related

Why does the orientation of a linearlayout determine the centering of a child element?

Why doesn't this center a button both horizontally and vertically on the screen?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_gravity="center"/>
</LinearLayout>
layout_gravity specifies alignment for the button within it's parent. But this only centers the button vertically, not horizontally. If I change the orientation of the linearlayout to vertical, the button is centered horizontally, not vertically. I don't see why the orientation matters here because I only have 1 child element.
I know I can achieve this by specifying the gravity in the LinearLayout with android:gravity="true" or using a RelativeLayout and have the Button android:centerInParent="true", but I'd like to know how android came up with the layout in the code above.
P.S. Why does the background color still show as gray if that's the hex code for white?
LinearLayout will only allocate the minimum amount of space needed for a view in the direction of its orientation. That's why you can't seem to center a view in the same direction as the orientation. LinearLayout generally assumes that you want to put multiple things adjacent to each other, not occupy an entire space unconditionally for a single item.
P.S. I see the entire background of the LinearLayout as white in my preview view in Android Studio, so I don't know what you mean in your P.S.
Don't use a linear layout to display items in the middle of the screen, as these are meant to list items in a row. Use a relative layout instead. So your code should look like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_centerInParent="true"/>
</RelativeLayout>

How to resize an ImageView within a given Layout in Android?

I have a problem to make a proper layout for a special case. I experimented on that already for a while both in the designer and in code, but I couldn't find a solution, that's why I need your help.
I have to create a layout which should have a structure like pictured in the images below. It is mainly a combination of several linearLayouts. The problem I have is, that the picture can only be added within the code, because this layout is a detail view that displays information about items from a list.
On the top is the layout without an image place holder (no loaded picture - indicated in black), here the width of "linearLayout_BigLeft" is given by the width of the two buttons and the textView (which all have content) in the "linearLayout_BelowImage".
In the middle you see the layout after the picture has been loaded (image indictated in orange) in code. Depending on the aspect ratio of the android device the black colored gaps differ. I can't get the image to resize to the whole available height and adjusting its width accordingly. The "linearLayout_BelowImage" adjusts itself to the image size (the textView in it is getting wider).
On the bottom is the layout which shows the ideal state. The image always should use the whole available space in height and resize accordingly in width. The "linearLayout_BelowImage" adjusts itself to the image size (the textView in it is getting wider).
Question:
How can I get a layout (after the image is loaded in code) that looks like the bottom picture? The image, after loaded in code, has to resize itself, so it uses the whole available height and resizes its width accordingly. The "relativeLayout_Top" and the "linearLayout_BelowImage" have both fixed heights. The "scrollView_BigRight" adjusts itself based on the space that the "imageView_OrangeImage" doesn't need for itself.
I can deal with solutions that adjust the layout in code, after the image has been added, or solutions that makes the layout.xml itself flexilbe enough to deal with this situation.
Any help is highly appreciated. If you need any more information please let me know.
Below is the main content of my layout.xml, that is needed for this problem.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/white">
<RelativeLayout
android:id="#+id/relativeLayout_Top"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#color/blue" >
</RelativeLayout>
<LinearLayout
android:id="#+id/linearLayout_Big"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:background="#color/transparent" >
<LinearLayout
android:id="#+id/LinearLayout_BigLeft"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/transparent" >
<ImageView
android:id="#+id/imageView_OrangeImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/black" />
<LinearLayout
android:id="#+id/linearLayout_BelowImage"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/blue_white_blue" >
<Button
android:id="#+id/btn1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/blue" />
<TextView
android:id="#+id/textView_BelowImageMiddle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#color/white" />
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/blue" />
</LinearLayout>
</LinearLayout>
<ScrollView
android:id="#+id/scrollView_BigRight"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/grey" >
</ScrollView>
</LinearLayout>
</LinearLayout>
android:adjustViewBounds="true"
This one’s a manual fix for “optimized” code in scaleType="fitCenter". Basically when Android adds an image resource to the ImageView it tends to get the width & height from the resource instead of the layout. This can cause layouts to reposition around the full size of the image instead of the actual viewable size.
AdjustViewBounds forces Android to resize the ImageView to match the resized image prior to laying everything else out. There are times where this calculation won’t work, such as when the ImageView is set to layout_width="0dip". If it’s not working, wrap the ImageView in a RelativeLayout or FrameLayout which handles the 0dip flexible size instead
get it from this site
OR
Mode android:scaleType="centerCrop" uniformly stretches the image to fill the entire container and trims unnecessary.
You can change the way it default scales images using the android:scaleType parameter. By the way, the easiest way to discover how this works would simply have been to experiment a bit yourself!
get it here

Two view at same spot, with same height and width in XML

In my widget I've an image of a refresh icon and circular progress bar (CPB) that is showed when the refresh icon is pressed (obviously only one view can be showed in the same time).
The CPB is too big, so I try to set scaleX and scaleY to 0.7 and my CPB is smaller, but this had the side effect that there is empty space where there was a bigger CPB.
How do I set this 2 view in the same position with the same height and width?
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="right"
>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/navigation_refresh" />
<ProgressBar
android:id="#+id/progressBar1"
android:scaleX="0.7"
android:scaleY="0.7"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</FrameLayout>
I can remove the scale and force the frame layout width and height to 28dp for example, and in this way it works fine, but I'm not sure if this is the best practice to do.
(For example in this way in a tablet with a big screen maybe the images will be a little big bigger because I'm using "dp", but not of the right size. Am I wrong?)
I managed to set views at the same location UNINTENTIONALLY using relative layout.
Try surround the views you want to be on top of each other with relativelayout.

Drawable: making it fit the screen, and scrollable

I have a drawable which i want to display. I want it to fit the screen horizontally, and to be scrollable vertically (when its height is bigger than the screen), while keeping it scaled.
I'm putting the drawable into a ImageView. The drawable is changeable (pictures of different heights and widths). I could scale every drawable to fit to the width of the screen, but when I do the drawable's higher than the screen will get cut of at the top, and i get a black bar at the bottom of my ScrollView.
I've tried every combination of ScrollView and ImageView I could think of, but the Image is either stretched or part of it falls out. Any help is much appreciated!
My current code:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" >
<ImageView
android:id="#+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center" />
</ScrollView>
<ImageView
android:id="#+id/iv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:adjustViewBounds="true"
/>
But I am not sure this is able to make image bigger than parent height. If this don't help I try to find in my archive working solution.

android layout scaling with fixed aspect ratio on different phones

I have a layout with two ImageView inside. Each image has a fixed aspect ratio, for example first image is 320x160, second is 320x320. Layout is aligned vertically. I want this two images be glued together and scale to fit one of the screen sides (width or height) and scale the other side proprotionally.
I tried to use scaleType=fitCenter, but the problem is that on different phones with different aspect ratio, images are not together, there is a black area between them.
It seems that I can not use layout:weight because the screens have different ratio (480x854 and 480x800) and I need my layout stays the same scaled proportion.
Any help is appreciated.
Here is my layout for now:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView android:src="#drawable/im_menu"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:layout_weight="0.7"
>
</ImageView>
<ImageView android:src="#drawable/im_field"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:layout_weight="0.3"
>
</ImageView>
</LinearLayout>
You can use:
android:adjustViewBounds="true"
and set fill_parent to height for example
<ImageView
...
android:layout_height="fill_parent"
...>
adjustViewBounds for my details
You can use layout weight with relative values too. For example, if you want a field with 30% and other with 70%, just set the children views weight with 0.3 and 0.7, and don't specify width nor height in children.
It is explained in the developer guide (tip section):
developer guide - linear layout
Also you may have to use RelativeLayout instead of LinearLayout.

Categories

Resources