I finished the java codes and function of my little project. At the end, i check to support a big amount of android devices according to their size. But it was fail.
While researching, i understand that i should use sp for textsizes and dp for all other parameters. The layout -xml- is existed via sp and dp. But it is not like that i expected.
I create a new project for example.
My xml; (in ConstraintLayout)
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:text="Hello World!"
android:textSize="105sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="144dp"
android:text="Check"
android:textSize="160sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
For 1080 x 1920 xxhdpi; Click here to see layout
For 1440 x 2960 hdpi(samsung galaxy s8 ) Click here to see layout
In galaxy s8, elements are really small and there is problem in view. I guess that i misunderstand a basic concept. Can you clear up my mind please?
You're missing something here: when you set android:layout_marginTop="72dp" the 72dp wil lbe interpreted the same way in both layout files.
A solution is to use dimens instead of values directly in your xml file.
Watch here : https://stackoverflow.com/a/32861248/5778152
Hope it helps.
You have to be careful at screen size and pixel density.
The best way to treat all screen sizes is to use ConstraintLayout, or weightSum in LinearLayout (but it slows UI performance). This will help you keep the same position of the elements on all screens.
Pixel density is harder to treat. For text size, for example, I find it useful to use different dimens files.
Right click values folder and click Values resource file, put the name dimens and then choose Density from the left. There you can select what density you like to treat. In each file you make you can make a text size with the same name, like this:
<dimen name="normal_text_size">15sp</dimen>
and each time you set a text size use this tag. This way depending on the phone density the appropriate text size will be automatically selected.
You can read about ConstraintLayout here
Read about screen size here
And about pixel density here
Related
When I see on the XML layout file in the android studio I can see the padding is there but on the device, I can not see it. I am not adding padding programmatically on that button. I only set the background of the button programmatically.
In Android Studio
In Device
Here is my button code
<Button
android:id="#+id/LoadBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="0dp"
android:minWidth="0dp"
android:layout_marginTop="16dp"
android:background="#color/colorAccent"
android:foreground="?android:attr/selectableItemBackground"
android:text=" LOAD MAP "
android:textAlignment="viewStart"
android:textColor="#android:color/white"
android:textSize="30sp"
android:textStyle="bold"
android:paddingStart="7dp"
android:paddingEnd="7dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
app:layout_constraintStart_toStartOf="#+id/fileTypeRadioGroup"
app:layout_constraintTop_toBottomOf="#+id/fileTypeRadioGroup" />
Here is the java code that I am doing with that button.
loadBtn = findViewById(R.id.LoadBtn);
loadBtn.setEnabled(false);
loadBtn.setBackground(ContextCompat.getDrawable(getApplicationContext(), R.drawable.disabled_button_background));
loadBtn.setEnabled(true);
loadBtn.setBackground(ContextCompat.getDrawable(getApplicationContext(), R.color.colorAccent));
Try setting the text of the button to dp, instead of sp. Sp will scale the text based on the device's preferences, while dp will not. It looks based on the example that they are just differently sized texts.
It could be that inside your android studio you are watching a display of one phone but when you run it you actually run it on another phone with a totally different screen resolution.
So you may see it as you would like to in your preview but this screen preview and your phone screen are different, and because different phones got different screen sizes and pixel densities you are seeing this differently.
When using a fixed size (7dp) value for padding for example for larger screens you will need to use more than 7dp if you want it to look like the preview or less if you are using a smaller screen than what you have in your android studio preview.
A good solution could be to use sdp library:
From the library github page:
An android lib that provides a new size unit - sdp (scalable dp). This size unit scales with the screen size. It can help Android developers with supporting multiple screens.
How to use:
You will first need to implement this:
dependencies {
implementation 'com.intuit.sdp:sdp-android:1.0.6'
}
And now on your layout file simply add the wanted padding:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="Text"
android:textSize="30sp"
android:textStyle="bold"
android:padding="#dimen/_18sdp"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Button>
And it will look like this:
Something extra
If you want to make your texts scale in size as well according to the screen size (as I just showed for dp) you can use
AutosizingTextViews or you can even use
ssp library
In my Android app I have the following layout:
<android.support.v7.widget.CardView
android:id="#+id/difficultyCardView"
app:layout_widthPercent="60%"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardUseCompatPadding="true"
android:layout_centerHorizontal="true"
android:layout_above="#+id/noHighScoresCardView">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/yellow"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="10dp"
android:src="#drawable/pushpin" />
<TextView
android:id="#+id/diffNameTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="12dp"
android:maxLines="1"
android:singleLine="true"
android:text="FÁCIL"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
</android.support.v7.widget.CardView>
In my Nexus 5, setting the text size to 20sp as shown above, makes text occupy, approximately, 75% of CardView's width. The problem is that, when I test this on a smaller phone, it adds ellipsis to the text.
What I want to achieve is that, on EVERY screen size and resolution, the text will exactly occupy 75% of the card with.
So, how can I solve this problem, creating multiple scale folders (ldpi, mdpi, ...) and adjusting font size in each of them, calculating it via code as a percentage, or any other solution?
Thank you.
Get the card width on the specific device and multiply by .75, then set the text size to that value.
if you want textview to take 75% of cardview with textsize 20sp then text will spilt into multiple lines.
android:maxLines="1"
android:singleLine="true"
remove these properties there is no need and allow textview for multiline
Will the text always be the same? If so the solution is pretty simple.
int ratio = 15;
int width = difficultyCardView.getWidth();
diffNameTv.setTextSize(width/ratio);
Adjust the ratio till the size is where you want it, then the text will be the same relative size compared to the card no matter what the screen size is.
What you want to do is to create a responsive layout. To do so create additional layout folders in the res directory. Add the pixel density name at the end of the folder name, separating the text "layout" and the density using a dash (e.g. layout-hdpi, layout-mhdpi, layout-xhdpi etc.) Within these folders, create the layout you want for each density. You can then resize the textview to 75% of each of the different screen sizes based on the pixel density. Therefore if 20sp fills 75% of the hdpi layout then you might need to increase the text size for a the mhdpi to fill 75% of the card.
Android will automatically select the correct layout for a particular device based on the screen size.
I have a fragment that takes up the whole screen, with Buttons and a SeekBar which scale to fit it, as well as fixed size TextViews. I use linear horizontal and vertical layouts with weights to achieve this.
The problem is I can't get the button text large enough without it making the buttons expand in size. For some reason, any text size greater than about 35sp makes the button expand, no matter how big the button is. This screen shot shows the button sizes have plenty of space for the text:
Ideally I would like the "<" and ">" characters to fill the buttons. (I was going to programmatically change the font size according to the button size, e.g. for different screen sizes) but haven't tried since I can't even get the static layout to work.
Edit: I would like to avoid images, since if I had 15 buttons, and 8 buckets, that would be 120 images I need!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/VerticalLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp" >
<!-- ........ -->
<TextView
android:id="#+id/trackTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2" >
<Button
android:id="#+id/trackPreviousButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="#string/button_track_previous"
android:textSize="35sp" />
<Button
android:id="#+id/trackNextButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="#string/button_track_next"
android:textSize="35sp" />
</LinearLayout>
<SeekBar
android:id="#+id/seekBar"
style="#style/tallerBarStyle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!-- ........ -->
</LinearLayout>
I have tried adding the following line to Buttons, but it only makes a small difference, if any:
android:padding="0dp"
Advice on getting the font height to fill the buttons without padding is my primary question. (But if the problem of dynamically sizing the text to fill the buttons for different screen sizes can be solved at the same time, that would be brilliant).
Edit: it turns out that using larger font sizes affects the effect of weighting for the height of the linear layouts, which is why there seemed to be padding - larger font size increased the button size, not because of the padding (which was 0) but because of the weighting
Button is not the right widget for your purpose. Use an ImageButton (or even an ImageView) instead.
I was going to programmatically change the font size according to the button size, e.g. for different screen sizes
Your current approach will land you in a lot of problems regarding proper sizing of your UI components. Given the plethora of android devices out there, screen size is just one aspect of the problem. You will also be dealing with varying screen densities. Best approach would be to put size/density buckets (drawable-mdpi/hdpi/xhdpi) to use. Help android in working for you.
Use drawables to indicate next and previous. If you're worried about the drawables being too small for tablet screens, create appropriate drawable resources/folders:
// Phones - 4 to 7 in
drawable-ldpi
drawable-mdpi
drawable-hdpi
drawable-xhdpi
drawable-xxhdpi
// Tablets - 7 to 10 in
drawable-large-mdpi
drawable-large-hdpi
// Tablets - 10 in
drawable-xlarge-mdpi
This list may not be exhaustive. Consider doing some research before finalizing your size/density buckets.
Output:
# drawable size 32dp:
# drawable size 64dp
Now it becomes quite straightforward - finalize drawable size by visual inspection on a phone, on a 7 inch tablet, and on a 10 inch tablet. Then use density scales to create and store appropriately sized drawable in the folders I mentioned above. Let android deal with what bucket to pick from.
The problem is by default buttons include a minHeight attribute. I had the same problem and solved it with just a single line of code in my XML file:
android:minHeight="0dp"
There is a quick and easy solution to your problem!
Auto-sizing text in Android is fiendishly difficult in my experience, especially when padding is involved. I would advise that instead of using an angle bracket character, you use a drawable - there are plenty of arrow icons available online - and an ImageButton. For example:
<ImageButton
android:id="#+id/trackNextButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#drawable/left_arrow"
android:scaleType="fitXY"
android:padding="0dp"
android:textSize="35sp" />
By using different ScaleTypes you can alter the stretching of the image. Even better, the screen sizes problem is solved because you can add different drawables for different densities.
Use minWidth="0" or "1" to reduce the horizontal padding on a text Button.
In Html we could use em, and it would adjust the size and format of everything to the appropriate size despite Resolution. Does android have a unit of measurement that adjusts views to its appropriate sizes and formats despite the different screen resolutions?
Android uses scalable points or SP
here is a sample
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample Text - 26sp"
android:textSize="26sp" />
Reference
You normally use dp for View sizes.
And sp for font sizes.
you can normally use dp,sp, for ref
I'm trying to make application run on each device and I come to a problem of making layouts and drawable folders. So, as I'm understanding ratio dpi is following - mdi:hdpi:xhdpi:xxhdpi - 1:1.5:2:3. DPI stands for dots per inch and this dots are actually presenting "DP" as density pixels which we put into XML attribute like: android:layout_width="150dp". (Please, correct me if I'm mistaking)
Problem occurs that some devices can have let's say 240x320 with xhdpi and there can be device 720x1280 also with xhdpi. Even if i would make separated pictures with already mentioned ratio, I would still need to make separated layouts in which:
layout-small would have something like this for ImageView:
<ImageView
android:id="#+id/slikaPitanja"
android:layout_width="150dp"
android:layout_height="100dp"
android:visibility="gone"
android:layout_below="#+id/sadrzajTekstualnogPitanja"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:contentDescription="Country flag" />
and layout-large where I would have the same code for ImageView except I would have these lines:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
(Actually I could have layouts separated with sw_ _ _dp format).
Is that right to do it like this? Am I missing point somewhere? Something tells me that it's never good to manually determine dps in width and height as I would for layout-small.
Try to NOT use static dpi for your layout, Instead use "wrap_content , fill-parent and gravity". this will make your layout to spread dynamically depending on the screen size