Resize Android ImageView on Keyboard open, keep aspect ratio - android

I am having some issues with setting some image as the background in an Android application. The problem is that I want the image to fill in the space in the middle of the layout, but when the keyboards opens, it gets stretched and doesn't keep the aspect ratio.
Here are 2 diagrams explaining the layout :
Here is my current code related to this problem :
layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/background_image">
</ImageView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/itemsSetup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#color/colorDarkLighter"
android:orientation="vertical">
...
</LinearLayout>
AndroidManifest.xml
<activity
android:windowSoftInputMode="adjustResize">
...
</activity>
I can't use
android:windowSoftInputMode="adjustPan" or android:windowSoftInputMode="adjustNothing" because I want the bottom to be higher than the keyboard as it opens and also keep the header, as shown on the diagrams above.
I have tried setting the background image programatically as explained in other threads with
getActivity().getWindow().setBackgroundDrawableResource(R.drawable.background_image);
The problem is that when doing so, the image gets stretched and doesn't keep the aspect ratio.
Has anyone been able to combine both, resizing the layout with everything still on the screen and keeping the aspect ratio of an image ?
Thanks.

Related

ImageView vertically centred in MaterialCardView

Objective: I am trying to make a MaterialCard with an Image inside it, as well as some text below the Image. This current layout will serve as a "menu" for the application, where the user can select where to navigate to.
Problem: The ImageView is appearing vertically centred in the MaterialCardView. I would like the ImageView to "stick" to the top of the MaterialCardView. There are large sections of MaterialCardView above and below the ImageView.
My XML Code:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".MainActivity"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true"
android:id="#+id/appBar">
<Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#color/design_default_color_primary_dark"
app:layout_scrollFlags="enterAlways">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/application_title"
android:textColor="#color/colorWhite"
android:textSize="24sp"/>
</Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:id="#+id/mealPlannerCardView"
android:contextClickable="true"
android:focusable="true"
app:cardBackgroundColor="#color/colorWhite">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:src="#drawable/wedding_dinner"
android:contentDescription="#string/wedding_background_cont_desc"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="#string/mealPlannerTextView"
android:textColor="#color/design_default_color_primary_dark"/>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
output
I tried to use layout_gravity="Top" but it made no difference.
EDIT
android:scaleType="fitStart" made the Image "stick" to the TOP of the MaterialCardView, but now very large space beneath the ImageView that requires scrolling to get to end.
Add the line below in your xml
android:layout_gravity="start|top"
See if this repositions the image for you. Worry about centring later if this works.
You might get the result you want by setting a scaleType for the image view.
Checkout this link: https://thoughtbot.com/blog/android-imageview-scaletype-a-visual-guide
It shows examples of each scaleType, it will help you to choose the right one to achieve the appearance you need.
This is happening because the Android framework is trying to maintain the aspect ratio in the face of your height and width constraints and default scale type.
There are more than one solutions to your problem and its for you to choose based on whose results are acceptable to you. All these solutions revolve around helping the framework with ImageView's aspect ratio. Let me try to put down the possible solutions that I can think of.
First solution can be as simple as changing the scale type on your ImageView as below:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="#drawable/wedding_dinner"/>
That will take away the white spaces but crop your image.
A slight variation of the above, where you can define a fixed height of the image. This is a surprisingly widely used solution as it provides a certain
<ImageView
android:layout_width="match_parent"
android:layout_height="240dp"
android:scaleType="centerCrop"
android:src="#drawable/wedding_dinner"/>
Finally, a more elegant and better solution is to provide a fixed aspect ratio to your images using a ConstrainLayout.

DP is display different layout in different screen

I have created a layout and define following Xml in layout file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.kirmani.myapplication.MainActivity"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/colorPrimary"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#color/colorPrimaryDark"
/>
<ImageView
android:layout_width="405dp"
android:layout_height="260dp"
android:background="#color/colorAccent"
/>
</LinearLayout>
This is filling my whole screen perfectly in Nexus 4 screen. but when i preview all screens, its giving very weird look in some screens.
I am using DP, it should maintain same display according all screens, but it is not working like that. Kindly guide me..
Actually dp maintains same display according all screens. It's because every device are not supposed to be same width in dp. Some devices has 480dp, some of them 360dp etc.
If you want to your image fit your width, you must use
<ImageView
android:layout_width="match_parent"
android:layout_height="260dp"
android:background="#color/colorAccent"
/>
do not use fixed dp.
EDIT:
If you want to height fill up, use this:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorAccent"
/>
Your 3rd imageview width should be match parent. Like this
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorAccent"
/>
instead of
<ImageView
android:layout_width="405dp"
android:layout_height="260dp"
android:background="#color/colorAccent"
/>
We are talking Android ABC here. You need to understand how this works instead of looking for concrete answers to concrete problems, as I already recommend you here.
Every device has an specific dimension in DPs. Nexus 4 is 384x640 but is the only one in your image with those dimensions. Please realize that is not that "is looking weird on some screens", in fact is gonna look weird on all screens that are not 384x640. For instance, the Nexus One in your image (which is 533dp x 320dp) is not working as expected, but is more difficult to realize because what is wrong is outside your view, but the views are bigger than the screen. Same with the Nexus S.
If you are trying to get a view from edge to edge (all the screen width), then use match_parent. Do not specify a size in DPs.
If you are trying to distribute views horizontally or vertically, please use an specific ViewGroup and/or weights, or you can use the Percent Support Library for doing things like this or this. Take a look at this tutorial for more.
Anyway, here you have your copy&paste code.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/colorPrimary" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.5"
android:background="#color/colorPrimaryDark"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2.6"
android:background="#color/colorAccent"/>
</LinearLayout>

Using dp for same dimension is not working for different phones of different resolutions but same dimention

I am working on an app which must support all the sizes. Since the 1920x1080 is wider than 480x800, I am unable to give the best fit for both at same time for landscape view. Where as they lie under same dimension. There is no problem with the portrait view cause it has really a small amount of difference on portrait view but when turning it to landscape view the entire thing is not coming in the screen.
This is the view of 1920x1080.
This is the view of 480x800
Both these sizes are accessing their xml file from layout-sw320dp-land
I'm only facing this problem for hdp screens that is layout-sw320dp screens since it has a very small space to work with. And there is no such problem for higher screen sizes since we have enough space to decorate.
Can anyone help me to sort out this problem?
We have many questions and answers for this problem but I'm unable to get the perfect solution for this.
Thanks in advance.
In case the problem only happens in this screen consider using LinearLayout with weights, that will give you a responsive design that is independent from the screen size or resolution - instead it will render by percentage making the views take the same percentage of the screen no matter what the screen size is.
Attached is an XML sample for a weighted screen.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="90"
android:background="#8000ff00"
android:orientation="vertical" >
<!-- This is the green view -->
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="10"
android:background="#80ff0000"
android:orientation="vertical" >
<!-- This is the red view -->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:background="#800000ff" >
<!-- This is the bottom blue view -->
</LinearLayout>
</LinearLayout>
This worked for me more than perfect. layout-sw320dp-land-hdpi and layout-sw320dpi-land-xhdpi

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

Image in background without resizing the parent layout

I've got a linear layout with layout_height set to wrap_content, so that the layout height is depending of the number of text lines in it.
The problem (that has driven me crazy all morning) is that I want to set an image as background of the layout, but to be sure the image can be used whatever the layout size, I've made the image quite big in height. The goal is for the image to be cropped in height if the layout is small. But I can't manage to do that: whatever I try, the layout is resizing according to the image height.
So, how can I set an image as background of something, but cropping itself so that it doesn't reisze parent layout (of course, I don't know the parent layout size because it depends on the text inside).
As english is not my first language, hope my question is clear...
Thank you in advance.
Edit: some code sample and screenshots:
This is the original card, without the image in background.
This is the code with the image view added:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/drill_background_img" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
... [Card Content Here]
</LinearLayout>
</FrameLayout
... and the result is my card is stretched to the height of my image. But I don't want that. I want the card the same size. But I cannot reduce image height, because, the card can have more text and be more tall, and so my image will have to be taller.
This is code for a Linear Layout that will be in center and adapt the size of text inside.
I have tested it .
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical"
android:layout_centerHorizontal="true"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvInfo"
android:textColor="#ffffff"
android:background="#drawable/toast_frame"
android:gravity="center" />
</LinearLayout>
Give it a try it should work. Here I am using an Image that is small enough to fit the smallest size. Android will automatically strech it. I use 9patch Images for such cases. To know more about 9patch visit this Link from developer.android.com
Simple online tool to generate 9patch
Also check this SO Answer
I have uploded toast_frame.9.png file here so that you can test it with the code I have given above
**EDIT **
change
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/drill_background_img" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
... [Card Content Here]
</LinearLayout>
</FrameLayout>
to
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/drill_background_img">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
... [Card Content Here]
</LinearLayout>
</FrameLayout>
I hope this will work.
I don't think you can crop the image when using it as "background" attribute for any view.
Image will always be stretched to fill the whole background. Normally for background you should use Nine Patches. Get familiar with it and maybe you can change your functionality or UI spec to use them instead of normal images.
The only way I know of cropping the image is in the ImageView and it's image set by "src", not "background".
I would generally avoid using fixed size images in the components that can change size. You also have to remember that in Android almost everything change size when you think about different orientations, screen sizes, screen densities.
I think that background is always resized to fit container size. But you can use FrameLayout or RelativeLayout and ImageView.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
...your content here...
</LinearLayout>
</RelativeLayout>

Categories

Resources