What about percentage usage? - android

So, i'm thinking about the usage of percent, example, in margins.
We can use overlay to separate our layout by dpi sizes, but why can't we use percentage?
Something like that:
Display display = getWindowManager().getDefaultDisplay();
float width = display.getWidth();
float height = display.getHeight();
//20% of left margin
float imageMarginLeft = ( width * 20 ) / 100;
And then set this margin to the image, or whatever element.
Is this bad? I just wanna discuss about it.
Thanks.

LinearLayout can do percentages by using weight.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="100">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="20"
android:text="Button" />
</LinearLayout>
Weight based layouts hinder performance if you use a lot of them, especially so when they're nested. Doing it programmatically will likely impact layout time as well.
Edit
Since you're looking for discussion, I would suggest that percentage based layouts are bad in general. The problem is that physical screen size varies so much with Android. Half the screen on an Incredible is much different than half the screen on a Galaxy S III, which is much different from half the screen on a Nexus 7, etc. The benefit of using dp units is that they're related to the physical size of things on the screen. It keeps buttons from being tiny (and hard to select) on tiny screens and it keeps them from being enormous (and ugly) on large screens.

Related

Why is widget small although using dp

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, ...)

density pixels(dp) is not working fine for all resolutions

<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.

Setting button images at run-time

I'm finding Android's choice of image resources for buttons based on screen-density to be unhelpful.
I'm developing an app for kids, and so I want it to have nice big obvious buttons, but at the same time I have to limit myself to the available screen real-estate.
Essentially I want to use image sizes appropriate to the screen-size that I have, not to it's density.
For example, lets say I want to fit 5 buttons down the side of the screen in landscape mode. I'd like to do something like this..
Get the height of the screen in PIXELS.
Calculate the height of each button (hButton), allowing for some space in between.
Load the appropriate image resource. I.e. the smallest one that is at least hButton pixels.
Scale the image to be hButton pixels high.
Something like that.
Does Android have a nice way of doing this, or do I have to code that myself? How do I access the appropriate images? (most of my buttons use two images - Up and Down)
Thanks
EDIT:
It seems I wasn't clear enough in my question. I don't need to know how to lay out buttons, and I have a good understanding of how Android chooses images based on density - THAT is the problem.
Consider these two devices -
1/ Galaxy I9000 phone - screen size 4" HDPI
2/ Samsung Tab 3 tablet - screen size 7" HDPI
Because both have the same screen density, both will show images at the same physical size. An icon that is 1" square on one will be 1" square on the other. THAT is the problem. I want the buttons to be proportional to the screen size.
I could try using size specific resources (e.g. drawable-small), but then there will be issues between small devices of different densities, which would then mean creating lots more directories, which seems like a bad idea.
I leaning towards putting a variety of sizes in the no-dpi directory, and then loading as needed.
you can ask you button how bit it is
int hButton = imageButton.getHeight()
then you can get the height of the button in the same way and so some simple school math:
getHeight()/buttonCount+(buttonCount*padding)
load the biggest image you have got and scale it down to your needs, since you don't know how big it is, unless you map it yourself. By that I mean that you can build something like a utils class that contains a map with the imageNames and their size in px
The layout XML in Android is very flexible and powerful. You can layout your buttons dynamically like below.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:text="Button A"/>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:text="Button A"/>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:text="Button A"/>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:text="Button A"/>
</LinearLayout>
As for image resources, if you think the standard Android image resource selection is not helpful, I'm sure you are misunderstanding something. It is not about the size of buttons. It is about the density of images.
If you are thinking about using simple shapes as buttons, you may want to know about ShapeDrawables.
https://developer.android.com/reference/android/graphics/drawable/ShapeDrawable.html
https://developer.android.com/guide/topics/resources/drawable-resource.html#Shape
for get screen runtime height and width
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
for button height
int buttonHeight = hButton.getHeight():
then get the smallest button height
calculate image height and set it as image resource.
if u r asking for image resizing code
then chek here.
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);

dip is not stretching properly according to screen resolutions in android phones

I have used dip(eg: width = 30dip, scroll bar till the middle of screen) , as parameter But in 3.5 inches phone it looks fine, in 5 inches screen phones its not at all coming till middle, here goes below middle. why?
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="450dip"
android:paddingLeft="10dip">
<ImageView
android:id="#+id/gdi_arrow_up"
android:layout_width="27dip"
android:layout_height="27dip"
android:layout_marginLeft="10dip"
android:scaleType="fitCenter"
android:layout_marginBottom="-8dip"
android:src="?attr/asListArrowUp" />
<include layout="#layout/main_menu"/>
<ImageView
android:id="#+id/gdi_arrow_down"
android:layout_width="27dip"
android:layout_height="27dip"
android:scaleType="fitCenter"
android:layout_marginBottom="-8dip"
android:layout_below="#android:id/list"/>
</RelativeLayout>
dip stands for density independent pixel, this means 2 screens with the same size but different density will treat that value the same, however 2 screens of different size (large vs normal) will treat the value differently.
your 5 inch phone may be reported as large and your 3.5 inch phone as normal causing the issue but I'm not sure.
also in your realative layout I'd recommend using match_parent for the height, you usually will not use set widths for viewGroups.
Set the LayoutParameters of the RelativeLayout dynamically as screenWidth/2..it will work on all devices..
In your onCreate do something like this:-
RelativeLayout rel = (RelativeLayout) findViewById(R.id.rel1);
int screenHeight = getWindowManager()
.getDefaultDisplay().getHeight();
rel.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, screenHeight/2));
Hope this helps.

Android layouts - button size

This is my code for the button. Thing is, it's the same size on all devices. It's big on small ones and small on big ones. How do I alter its size relatively? Here's my code.
<Button
android:id="#+id/button1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_margin="3dp"
android:background="#drawable/blue_gradient"
android:layout_alignRight="#+id/relativeLayout1"
android:layout_alignTop="#+id/relativeLayout1"/>
I would like the size to be consistent, depending upon the device's resolution.
EDIT
I want the buttons to be square.
You are specifying the width and height in dp, or density-independent pixels. This unit of measure is designed to produce the same physical size on all devices regardless of pixel density, because pixel density varies by device. You can also use either of the following values for layout_width and layout_height:
wrap_content makes the view large enough to hold its content.
match_parent uses the corresponding dimension (width or height) of its parent view.
Also with any of these you can stil specify padding and margins, a la the typical box model.
Android currently does not support percentage style measurements, like making the width be 60% of the available width. The closest you can get to that is using a LinearLayout and specifying layout_weight values for its child views.
If you want finer control over the size of a view, you can subclass it and override the onMeasure method, which is where you would calculate the size of the view and set its width and height by calling setMeasuredDimension(w, h). Here's an example of someone doing just that: https://stackoverflow.com/a/3147157/1207921
the best way is to use
android:layout_width="wrap_content"
android:layout_height="wrap_content"
It manages size for all devices very well.
For square buttons you need to set width/height in the code. this will help you.
You might want to try using image buttons with different sized images according to screen resolution (Android, (newbie) different res imagebuttons).
If you use LinearLayout with android:weightSum="2.0" and you set all of your image buttons with android:layout_weight="1" you will have their width/height exactly 50% of the LinearLayout according to the LinearLayout orientation.

Categories

Resources