i have a image that on mDPI is 360dp and that takes up the entire width of the screen. But when i view the image on nexus 5x api 23 xxhdpi scren it does not take up the entire width of the screen. I thought 1dp equals 1px on MDPI so i could use that as a standard. so then 360dp on MDPI is max width therefore it will be max width on all densities ? what am i missing ?
This is what i have tried. Compare this screens size:
giving this full screen output:
this this one with the same 360dp:
giving a output with the image not taking up the full screen, why :
is this why constraintLayout is recommended , using ratios ?
i finally figured this out. this is one reason constraintLayout was built to rectify these issues. in this particuular case it was about aspect ratio in a view i was using. so to make it take up the entire space of the activity left and right i did the following and the aspect ratio is maintained. keep i mind i wanted a 360 x 500 ratio:
<com.mobile.myapp.customViews.SwippableViewPager
android:id="#+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
app:layout_constraintDimensionRatio="H,360:500"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
this overview was very useful for me to learn constraintLayout.
also the other way to guarantee this would be to use a viewgroup somewhat forgotten now as its deprecated: android percentRelativeLayout
Related
I'm developing an app and my Constraint Layout isn't compatible with any screen size.
I have a button with the following width and height:
android:layout_width="283dp"
android:layout_height="57dp"
Here's how it look using a Google Pixel.
And here's how it looks using a Nexus S
I also sent the apk to a person that has an Galaxy J7 (1280x720, 5.5'), and my buttons, textviews and imageviews don't fit well in the screen, just like the Nexus S (800x480, 4').
After reading the documentation and other sources, I got that I can create different layouts for different screens (hdpi, for example, which is the case of the Nexus S).
But it looks that the problem is more related to the display inches than with the device dpi.
Because the Nexus S has an 800x480, hdpi and 4' screen. But when I change to a 800x480, mdpi and 5.1' screen (1.1' more inch), it looks way better than in the Nexus S, even with a lower dpi (mdpi). It also looks better than in the Galaxy J7 real device, even with a lower screen size (5.1' x 5.5') and resolution (800x480 vs 1280x720).
So, how can it fit well in a 800x480 5.1' mdpi screen, but not in a 1280x720 5.5' Galaxy J7 and in a 800x480 4.0' hdpi screen (Nexus S)?
Also, if I create a virtual device with the same screen specs of the Galaxy J7 real device (1280x720 and 5.5'), It fits really well, unlike the real phone.
I advise you to use Adobe XD and use it to determine the size
android:layout_width="283dp"
android:layout_height="57dp"
and after that extract the pictures for all sizes
Then make the width and height wrap_content
In the XML file
You can replace your fixed size (what you are currently giving to your views) with something more responsive.
If this was your non responsive button:
<Button
android:layout_width="200dp"
android:layout_height="400dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Just replace it with this:
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.3"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
For every phone, small or large this button will adjust according to the screen size and will take 30% of the screen width and 50% of the screen Width.
This is how you can make one screen responsive to all screen sizes and not create a lot of layouts for different screens.
These images are OK, it's not a problem itself. That's usually what happens when you set the width and height manually.
Best thing you can do is set the right constraints and then set width and/or height to 0dp. This will make your view expand as much as possible without breaking any constraint. This way you will still get different widths and heights, but hopefully less noticable ones.
Be aware that if you set top and bottom constraints to parent, and you set the height to 0dp, it will expand to fill its contraints, it will fill your whole parent.
And for positioning you can use guidelines if you want. A a horizontal guideline in 50% will be in the middle of the screen in every phone. So you can constrain views to that as well.
Sounds like a basic question but I have no idea why this behaviour is that way
I am using a button that is 200 dp by 60dp and with 15sp text size
It looks good on my phone, emulator and multiple other 5 even low 6 inches phones
However on note 10+ which is 6.8 inches, the button looks smaller and the text is smaller
I thought when using dp and sp, it will occupy the same size on all phones given that it is in terms of density independent pixels
Why is this behaviour?
Thank you
Update:
Based on this page about dp size of devices and the link provided at the top of it, I've reached to this article how to calculate metrics of any device including dp. Based on my calculations Note 10+(3040*1440 pixel, 495 ppi) is a 465 * 982 dp device. Google pixel you can see from the first link is a 411 * 731 dp device. So, if you create a size 200 dp layout it would be smaller on the note 10 + than on the google pixel for example. To be honest I thought all small screen devices are something close to a 360 width dp and expected that one design by dp would be seen roughly the same on all devices. I was wrong apparently. It seems if the layout is supposed to be seen exactly the same width on all devices there is no way but to set its width by a percentage of screen width. Google doc has it too: converting pixel to dp.
This image from Support different pixel densities lead me to incorrectly think that designing by dp would be seen the same on all devices. But it would be seen the same only on same dp devices.
It looks good on my phone, emulator and multiple other 5 even low 6 inches phones,
As #Mr. Patel mentioned in his comment, you can use ssp and sdp but I want to offer another solution.
First - why is this happening:
You have a lot of different phones with a lot of different screen sizes, when you are using dp you are actually using a fixed size value - it can not be scaled for large screen.
How to fix it:
You can use ConstraintLayout
with percentage to make your views scale according to the screen size.
Example:
Let`s have a look at this layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="200dp"
android:layout_height="400dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
It will look like this:
In this layout, the button size is 200dp and 400dp.
This may look good on one phone but will not look good on another phone, because as I have mentioned before:
different phones = different screen sizes.
Let`s take a look at how to make your layout responsive according to the screen size:
All I need to do Is to change my layout to this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.3"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And now the layout will look like this:
Looks... kind of the same?
Well, the new layout is actually looking not so different from the original but now because I have added those attributes:
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.3"
app:layout_constraintHeight_percent="0.5"
For every phone, small or large this button will adjust according to the screen size and will take 30% of the screen width and 50% of the screen Width.
Another tools that can help in the prosses of making some screen responsive:
chains
barriers
How to add different weight to ConstraintLayout views
Autosizing TextViews
dp is base on screen resolution (px) and dpi.
Example:
1280x720px screen of xhdpi (x2)(320dpi) will have 640x360 dp => 1dp = 2 px in that screen.
640x360px screen of mdpi (1x)(160dpi) will have 640x360 dp => 1dp = 1 px in that screen.
The result will look the same for 2 devices
But when the device have a smaller dpi (240) but remain the same resolution: 1280x720px it will have ~854x480 dp
=> 1 = 1.5px in that screen => Your button and text will look smaller.
To make your button look the same on multi screen, you have to provide many dimens file for many screen.
You will have to use many dimens file to make your button show the correct size on other screen. (ssp and sdp is use this way) - (My project have tons of dimens file for each 10dp different screen size to make sure app show the same on any device)
Or you have to use percent supported layout (ConstraintLayout, PercentRelativeLayout, ...)
I am having an image in imageview of size 5.64mm.
As android having different resolution,image is varying for different devices.
In my case image should not vary at any device.
please help me with some code for drawing the image or setting the imageview Fixed size.
you have to create the same image for different resolutions and put those images in the hdpi,xhdpi etc folders.
Lets assume your image is 100 x 100 in pixel size, so a device with 320 x 480 pixel will show it big but a device with 1280 x 800 will display your picture smaller.
In other words the more pixels a device has in its per square inch space the smaller space your icon will take.
so you have to create multiple versions of your image so that it size remains relatively same.
Do this way. Use dp unit to specify height and width.
<ImageView
android:id="#+id/ImageThumb"
android:layout_width="55dp"
android:layout_height="60dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="10dp"
android:background="#color/icms_white"
android:padding="1dp"
android:scaleType="fitXY" />
use
android:layout_width="5.64mm"
android:layout_width="6.15mm"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/gray"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/darkgray"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="#+id/attenders"
android:layout_width="110dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="#color/gray"
android:layout_marginRight="8dp"
android:text="Attenders" />
<Button
android:id="#+id/send"
android:layout_width="110dp"
android:layout_height="40dp"
android:layout_marginLeft="8dp"
android:layout_gravity="center"
android:background="#color/gray"
android:text="Send IM" />
</LinearLayout>
</LinearLayout>
this is my code but the dp is not working fine for all screen resolutions.
suggestions plz, plz tell me if i am doing anything wrong
problem is that when i use dp for setting height or width of a button
it does not gets fits to all resolutions i-e on small screens it looks
big and on big screens it looks small, whereas i know that when we use
dp for setting height and width of any component it automatically
converts/adjusts according to screen resolution
What I understand from this is that you thought using dp instead of px (or in, or cm) will magically work such that they will all have the same physical size on all devices, regardless of that device's density (ppi).
That's not the case.
dp, or dip, as explained here, is
An abstract unit that is based on the physical density of the screen.
These units are relative to a 160 dpi (dots per inch) screen, on which
1dp is roughly equal to 1px.
A screen with more dpi (denser, meaning more pixels are packed into a square area of the screen), will essentially draw a physically smaller image compared to a screen that has 160dpi when tasked to draw the same, say, 100x100 dp image.
When running on a higher density screen, the number of pixels used to
draw 1dp is scaled up by a factor appropriate for the screen's dpi.
Solution
There are two easy ways to have your app look proportionally the same on different screen sizes.
The first is to use different layout folders (layout-ldpi, layout-mdpi, etc.). This technique is well-explained here. A much more recommended way would be to use different style values for each density, so you can still maintain one layout folder and refer to the styles instead for measurement. This can be done using the same technique, but instead you will have values-ldpi, values-mdpi, etc. This is useful for having standard sized UI elements across screen sizes.
The other way is to use weights all over your layout. Weights adjust automatically regardless of screen size of density. This will help a lot if you want, say, three columns that have varying width -- you can easily use weights to tell the layout that column A needs to occupy 40% of the available width of the screen, and B and C will have 30% each. This is useful for having a standard layout across screen sizes.
A clean-looking, nicely coded app will implement both.
It is beacause you are giving fixed dimensions which can only be fit for a particular screen size which you are using. So try avoiding static dimensions and make use of match_parent,wrap_content and fill_parent so that you can get your layout fit for every screen size.
I am trying to understand something. A weird thing that I see is that when I put wrap_content in the width and hight, the image is bigger than the the real px (pixel) size of the image which is inserted. Why is that so?
My code with wrap_content:
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="false"
android:src="#drawable/header" />
and thats my code with exact pixel size of the image:
<ImageView
android:id="#+id/imageView1"
android:layout_width="378px"
android:layout_height="155px"
android:adjustViewBounds="false"
android:src="#drawable/header" />
As you can see, thats the exact pixel size:
Why is that? I thought that wrap_content should wrap the view to the content size so why is it bigger on screen?
If you really need to use the image's pixels as-is, and use the screen actual pixels do the following:
1) Create a res/drawable-nodpi and move your fixed-pixel non-scaling images in there.
2) You then can use wrap_content as layout_width and layout_height, and image pixels will match the device pixels with no upscaling because of dpi.
From http://developer.android.com/guide/practices/screens_support.html, the definition of nodpi :
Resources for all densities. These are density-independent resources. The system does not scale resources tagged with this qualifier, regardless of the current screen's density.
A very nice explaintaion for supporting the multiple screens is given at
http://developer.android.com/guide/practices/screens_support.html.
you need to put images in respective folders after scaling.
e.g. if you want 100*100 image then place
75*75 in drawable-ldpi for Low density devices
100*100 in drawable-mdpi for Medium density devices
150*150 in drawable-hdpi for High density devices
200*200 in drawable-xhdpi for Extra High density devices
wrap_content means that you want the image as it as its original size is. i.e if the size of the image is 200*200 then it will show 200*200 and if the image size is 400*400 it will show of the size 400*400.
So the reason you are getting a larger image then what you actually get when you hard code it with real pixels is because of the LARGE SIZE of the image. i.e image is actually large.
From my experience I can say that wrap_content always utilize maximum available size possible. So sometimes it stretch the image & sometimes reduce the size of the image. To use exact image use android:scaleType="fitXY"
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="false"
android:scaleType="fitXY"
android:src="#drawable/header" />
Update after 1st 2 comments:
as per android docs :
You can specify width and height with exact measurements, though you probably won't want to do this often. More often, you will use one of these constants to set the width or height:
wrap_content tells your view to size itself to the dimensions required by its content
fill_parent (renamed match_parent in API Level 8) tells your view to become as big as its parent view group will allow.
In general, specifying a layout width and height using absolute units such as pixels is not recommended. Instead, using relative measurements such as density-independent pixel units (dp), wrap_content, or fill_parent, is a better approach, because it helps ensure that your application will display properly across a variety of device screen sizes. The accepted measurement types are defined in the Available Resources document.
I found the term size itself is important, it autometically resizes the images. thats why I told that from my experience I found sometimes it stretch the image & sometimes reduce the size of the image
You need to see where you put the image. If its in hdpi it will look bigger on screen then if its in hdpi when ising wrap_content. so, in order for it to be the exact size, put it in right library.