How to auto fit ImageView in ScrollView as Screen Height as - android

I use ScrollView with multiple Views but I have an ImageView on the top. What I need is auto fitting image height as screen height as.
My current layout starts like this :
<LinearLayout
android:orientation="vertical"
android:id="#+id/layout_dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/toolbar_dashboard_layout" />
<ScrollView
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
Thanks.

To make sure ImageView adjusts its height, use attribute adjustViewBounds for example:
<ImageView android:id="..."
android:adjustViewBounds="true" ... />

Your screen dimensions cannot be known in a resource file, as the Android system takes these files and then renders them to the given device screen.
So, to make any View proportional to the screen size, we need to set its parameters programmatically. Luckily, Android gives us Display, which holds data about our display. Use this object to retrieve the height of the display, then set the height of our View to that:
ImageView imageView = (ImageView) findViewById(R.id.image_view);
Display display = getWindowManager().getDefaultDisplay();
//We need to store the dimensions in a Point object.
Point point = new Point();
display.getSize(point);
//Now, set the width and height.
profileImage.getLayoutParams().width = point.x;
profileImage.getLayoutParams().height = point.y;

Related

XML Layout weight not working in a ScrollView on android API23

I am doing an Android project in AndroidStudio where a ScrollView contains a vertical LinearLayout and within that LinearLayout there is an ImageView and another LinearLayout. I am trying to set the ImageView to be 10 times smaller than the LinearLayout, the result is showing up correct in the Preview window but not on my phone (Xperia Z3 with API23).
This is what I see in the preview window and what I want to achieve
But on my phone the image fills the width of the screen and the image height is proportional to the original image(almost fills half the screen, so far from what it should be according to the weights)
The app worked like it is supposed to on a Google Pixel 7.1.1 with API25.
Here is a part of the code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:fillViewport="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_weight="1"
android:adjustViewBounds="true"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:id="#+id/image"
android:scaleType="fitCenter"
android:src="#drawable/bjj2" />
<LinearLayout
android:layout_weight="10"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp">
<LinearLayout
...rest of the app
</LinearLayout>
</LinearLayout>
</ScrollView>
Here is the full code https://github.com/IvarsGoldingen/Bjjscorekeeper/blob/master/app/src/main/res/layout/activity_main.xml
Can someone please tell me what I'm doing wrong.
One should understand how dimensions are calculated.
Let's look one by one.
1) ScrollView is fill_parent/fill_parent (actually one can change this to match_parent/match_parent as fill_parent is deprecated as far as I remember, but it doesn't matter in this case).
So, ScrollView is shown fits whole screen (width and height).
2) LinearLayout inside ScrollView is match_parent/wrap_content. And that is correct. One should use wrap_content for views that inside ScrollView.
The reason why - is that ScrollView is used to wrap long views with usually unknown height (like lists). Imagine here match_parent as height - height of LinearLayout would be calculated based on height of scroll view, which is whole screen height, and LinearLayout height can be greater that screen height. Just not logical. But everything is OK till now. Move on.
3) Items inside LinearLayout. You want them to be 1/10 and 9/10 of height of parent layout. Also, you set height for inner items to 0 to show that you want height to be calculated from weights.
And here you got a cycle of dependencies. LinearLayout height is wrap_content and depends on sum of heights of inner elements.
And inner elements' height is calculated from parent LinearLayout height.
Additionally, you want ImageView to be 1/10 of the LinearLayout height. But actually seems like you want ImageView to be 1/10 of the screen's height, as LinearLayout height can be greater than screen's height (and looks like this is what you get on your device).
You say, that everything is OK in preview in Android Studio.
To demonstrate that not everything is OK try this:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:fillViewport="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_weight="1"
android:adjustViewBounds="true"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:id="#+id/image"
android:scaleType="fitCenter"
android:src="#drawable/bjj2" />
<LinearLayout
android:layout_weight="10"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp">
<View
android:layout_width="match_parent"
android:layout_height="1000dp"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
Just put some big (bigger than screen's height) view inside your inner-inner LinearLayout and you will see that in preview your image is bigger than 1/10 of screen's height. But it is 1/10 of LinearLayout's height.
How to solve your issue?
I think the only way is to calculate 1/10 of the screen's height and resize bitmap with image you want to have and set that bitmap to ImageView.
Or any other way to set exact height to ImageView.
Or review your layout and create something different.
we can set height of the image view at run time by avoiding layout_weight using display metrics .
e.g
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
yourImageView.getLayoutParams().height = height / 5;
yourImageView.getLayoutParams().width = width / 4;

How to set height proportional to width according to device dpi in android

I would like to fix the height of imageview but according to different devices and dpi's.
<ImageView
android:id="#+id/imgFood"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:src="#drawable/ic_no_img" />
As of now I fixed the height to 200dp, but I want to keep it ratio of 1:2 instead of fix size. I know android works on dp but I am unable to figure out how can i keep the ratio for all devices. Width will be match parent (fit device width) but height needs to be changed accordingly.
Any idea/suggestion?
You can set your height dynamically like this.
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
ll.getLayoutParams().height = width/2;
ll.getLayoutParams().width = width;
ll.requestLayout();
You can set height or width ratio of views inside LinearLayout using the layout_weight property, for example:
<LinearLayout
android:weightSum="3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<View
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<View
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</LinearLayout>
This will cause the inner Views of the LinearLayout to take one and two thirds of its width, respectively.
Otherwise, if you have to use a different layout, there is currently no way to do this in .xml files, and the option is to fall back to setting the size programmatically, like in Hussnain Azam's answer (you don't always have to call for size of the display though).

RecyclerView not displaying layout

I have a recycler view which is not displaying a specific layout. I know that the layout is the problem, because I've tried with different layouts and they are being displayed. I don't get any errors in the console for the bad layout.
That layout is structured as follows:
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="#000"
android:layout_height="match_parent">
<android.support.percent.PercentRelativeLayout 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="match_parent"
android:background="#color/border_color"
app:layout_heightPercent="30%">
</android.support.percent.PercentRelativeLayout>
</android.support.percent.PercentRelativeLayout>
I see it rendered properly, but probably is something wrong with it. I want that each of my recycler's items to have 30% height, that's why I'm using app:layout_heightPercent="30%". If I remove the outer layout the inner layout will take all the space. How can I achieve this 30% height, because clearly this is not working.
Try this:-
I have set height as 100dp for parent PercentRelativeLayout. It is working for me.
<android.support.percent.PercentRelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="#000"
android:layout_height="100dp">
<android.support.percent.PercentRelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#888888"
app:layout_heightPercent="30%">
</android.support.percent.PercentRelativeLayout>
</android.support.percent.PercentRelativeLayout>
For anyone having the same problem, give an id to the outer layout, or whatever layout your recycler items might have outer,
define it in your holder:
outer = (PercentRelativeLayout) view.findViewById(R.id.outer);
and inside your onBindViewHolder set your height programatically:
Display display = ((Activity)ctx).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
//int width = size.x;
int height = size.y;
((MyRecyclerHolder) holder).outer.getLayoutParams().height = height/3;(or whatever ratio you want)

Position textareas and buttons in % of the screen

I started yesterday with developing for Android. I already know Java, so you don't have to explain general Java things for a beginner.
Information:
IDE: Android Studio (latest)
Minimum API: 10
I want to code a fun app where the user types a countdown in a C4 Bomb UI and the bomb's ticking after the input.
I have now the problem that I can not position the elements margin in % of the screen.
Here's an image with the text field, buttons and the margins I calculated with the image dimensions.
How can I do this?
You could use the following algorithm:
//declare two variables for width and height of the screen, that you could use later
private int screenWidth;
private int screenHeight;
//first get the size of the screen - call this method in the onCreate method of your Activity
private static void getScreenResolution(Context context){
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
}
//then use dynamically positioning of the elements as you use LayoutParameters for your elements like this:
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); //width, height
params.setMargins(11*screenWidth/100, 34*screenHeight/100, 0, 0);//left, top, right, bottom - here you could use the % like 11% from screenWidth = 11*screenWidth/100 (all the digits are for example)
//get the element which you want to be positioned at the current position (for example an ImageView)
ImageView myImage = (ImageView)findViewById(R.id.myImage);
myImage.setLayoutParams(params);
P.S. If your layout is RelativeLayout, you should use RelativeLayout.LayoutParams instead of Linearlayout.LayoutParams (just change the word)
You could use weighted layout(empty layout on left and right side of your image then wrap it again for vertical). Let say I want to create an image with margin 25% on both side, then the weight for each empty layout is 1, and for the image is 2.
UPDATE:
here's a little example, the "view" component is just a placeholder for margin
The top and bottom margin is 25% of height, while the left and right margin is 20% of screen's width.
<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" >
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />

Resizing image to fill width of screen

I am trying to set an Image that I am downloading from the web. I am using a library to help me do this called ion. The problem is that I need to resize the image to fit my screen and keep the aspect ration. The height seems to be working fine however I want to set the width of the bitmap to fit the whole width of the devicewhile keeping the aspect ratio. But it is not working and the image is cut short on both sides...
<ImageView
android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="#dimen/_height" />
Code:
DisplayMetrics metrics = getResources().getDisplayMetrics();
mWidth = metrics.widthPixels;
mHieght = (int) getResources().getDimension(R.dimen._height);
Ion.with(imageView).resize(mWidth, mHieght).load(url)
Edit:
This is with android:scaleType="centerCrop"
ImageView has scale type feature. Check ImageView.ScaleType. I think centerInside or fitCenter is what you are looking for.
Update
Sorry didn't realize you have a fixed height at first. centerCrop should be the answer.
If you have a known max size for your images, you can set the width of your layout equal to the largest width of your images set, then take all centered. This worked for me:
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="1920px"
android:layout_height="fill_parent"
android:layout_gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:background="#drawable/your_image" />
</RelativeLayout>
</FrameLayout>
Where 1920px is the largest width of your images set.
The result is acceptable, EDIT: Image is perfectly centered.
I achieved this using "paddingLeft" and "paddingRight" on parent layout; while apply a negative value to padding and margins to the child layout / ImageView. "android:clipToPadding" flag must be false to prevent the clipping.
<LinearLayout
...
android:paddingLeft="10sp"
android:paddingRight="10sp"
android:clipToPadding="false"
...>
<ImageView
android:layout_marginLeft="-10sp"
android:layout_marginRight="-10sp"
android:paddingRight="-10sp"
android:paddingLeft="-10sp"
...>

Categories

Resources