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.
Related
I have a screen on which I need to display a number of images inside a horizontal LinearLayout.
I designed it for an xhdpi. I set the sizes of each ImageView to 100dp, and on an emulator (xhdpi 768x1280 4.7" screen) it looks something like
this while on a tablet emulator (xhdpi 1534x2048 9" screen) it looks like this.
In the latter, the images aren't scaled properly to look like it does on the smaller screen.
Is there a way to make it look the same on both screen sizes?
to make your layout adjust on different screen you need to design it to be responsive. Yes like what G.Dator said, you can use weight attribute. Here's the example :
<LinearLayout
android:layout_height="200dp"
android:layout_width="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="25"/>
<ImageView
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="25"/>
<ImageView
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="25"/>
<ImageView
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="25"/>
</LinearLayout>
Please let me know if you have further question.
Actually, the image is the same size in 2 devices. The problem is the difference between your dp width of your phone (384dp) and your tablet (767dp). There're few ways to resolve it:
using multiple layout files for sw360 and sw720. You can check this Google Guide
Using the same weight for all your ImageView with adjustViewBound=true to keep your image ratios.
Using code to set your ImageView size programmatically.
In addition to implementing a responsive layout structure (like what #Bhimbim mentioned), there is a library (https://github.com/intuit/sdp) which can be useful when you want to code once and use it on multiple different devices, it offers you sdp unit instead of dp which helps your view to scale better.
Example:
layout_width="#dimen/_30sdp"
layout_height="#dimen/_30sdp"
(Sorry i couldn't comment as i have registered recently).
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 am currently trying to adjust my Android App so it will look and feel similar on multiple screens/devices.
I know by now that a major part in this is to provide multiple image sizes for every image file according to the x1, x1.5, x2, x3, x4 ratios for mdpi, hdpi, xhpi, xxhdpi and xxxhdpi respectively, and I have finished doing so today.
After doing this, I have defined Density independent Pixel dimensions in the #dimen.xml values resource that correspond with the actual image sizes in pixels of the MDPI resources. Subsequently, i have set the imageviews in question's layout_width and layout_height to this dimension.
I am currently at a loss, however, as to why my application still looks significantly different on an MDPI emulator than it does on an HDPI emulator. To highlight what I mean, I'll provide the following screenshot showing the HDPI and MPDI emulator next to one another (left is HDPI (4" WVGA Nexus S) and right is MDPI (5.4" FWVGA)). I want both of them to look like the MPDI version, but what I've done so far apparently isn't working.
I have three theories of my own as to why this is not working the way I intend it to:
1. I am not supposed to set ImageView layout_width and layout_height to a dp value, but rather match_parent or wrap_content (?) (and change the structure of my .xml layouts in the process).
2. I am not only supposed to define multiple drawable resources, but also multiple layout resources for different screen sizes (?).
3. I have misunderstood the entire idea behind how this is supposed to work (?).
I will also give you an example of one of the list items that can be seen in the first screenshot (#drawable/phone_speed_icon is a 64 x64 pixel resource in MPDI and a 96x96 resource in HDPI, and #dimen/icon_attribute_size is 64dp):
<LinearLayout
android:id="#+id/llSpeed_PreSession"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingEnd="20dp"
android:paddingStart="20dp"
android:weightSum="100">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="#dimen/icon_attribute_size"
android:layout_weight="20"
android:weightSum="100">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="70"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="#dimen/icon_attribute_size"
android:layout_height="#dimen/icon_attribute_size"
android:src="#drawable/phone_speed_icon" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="30"
android:gravity="center_vertical"
android:paddingStart="10dp"
android:text="Speed"
android:textAppearance="#android:style/TextAppearance.Large"
android:textColor="#878787"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="80"
android:gravity="center">
<android.support.v7.widget.SwitchCompat
android:id="#+id/swSpeed_PreSession"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
In the end, I have four questions that I'd like answered:
1. How do I make the list items in screenshot 1 look the same on MDPI devices as HDPI devices? Does this have anything to do with one of the three theories I mentioned earlier?
2. Why is the header text ("What do you want to measure?") wrapped on one device, but not on the other? They use the sp unit (via android:style/TextApperance.TextApperance.Large)?
3. Shouldn't everything be more spaced out on an HDPI device (if anything) rather than less spaced out? The HDPI emulator looks as if it "has got way less pixels available", if you can understand what I'm saying even a little.
4. How do I make the Fragments on the second screenshot look the same? Or should i not even want this, because the HDPI is (for some reason) physically smaller, which is why the layout is less spread out?
Anyway, I have been at this all day and the more I read the more thouroughly confused I get, so any help is greatly appreciated!
You have the option to create multiple dimens.xml files depending on a variety of factors. Here you'll see what my current project looks like with the various dimens.xml files in Android Studio based on screen width.
However, you can have different requirements for each dimens file you want. For example, you can create dimens files for each density:
I have a layout that features six buttons. All of them have the size of 72x72dip, so they appear to be larger on small screens and vice versa.
How can I tackle this problem? I want the buttons to be relatively the same size (eg 10% of the screen's width), but I don't know how to do it.
This is how my layout looks:
The layout's sourcecode can be found here.
1 - Did you fix all you 'image views' to layout_width & height of 72dip ?
2 - Normally 72dip is the same thing on every screen size... But you still can have 3(or 4 if you support XHDPI) resolution of your images...
2 - Add 4 différent fonder for you Drawable :
2.1 drawable
2.2 drawable-ldpi
2.3 drawable-mdpi
2.4 drawable-hdpi
Consider the following ratio for your images :
ldpi is 3
mdpi is 4
hdpi is 6
So make sure to make HDPI images first, so you can isealy resize other images applying ration 1.5 and 2 (just divide by 2 for LDPI for example).
3.By the way, why did you just did it all by yourself ? Seems you are on android 4.0, why don't you just use the new "DashBoard" class from Android ?
I usually do this by setting the width and height to wrap_content and then tweaking the layout_weight on the ImageButton widgets so that each button takes up the same amount of space. I usually do scaleType="center_inside" to make them line up nicely. Then pad around the edges of the TableView with margins as necessary.
Few quick observations:
a. You do not need TableLayout, just use LinearLayout
b. You do not need separate ImageView and TextView, you can use Button and image to it using
android:drawableTop="#drawable/"
c. Never use absolute values in width/height of any views, so use wrap_content.
Sample Layout should be like this:
<LinearLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<!-- Row 1 -->
<LinearLayout
android:layout_height="0dp"
android:layout_width="fill_parent"
android:layout_weight="1.0"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0"
android:layout_weight="1.0"
android:text="Preferences"
android:drawableTop="#drawable/Preferences" />
<Button
android:layout_height="wrap_content"
android:layout_width="0"
android:layout_weight="1.0"
android:text="Preferences"
android:drawableTop="#drawable/Preferences" />
</LinearLayout>
.
.
.
</LinearLayout>
</LinearLayout>
I have read many documentation on supporting multiple screen sizes but still confused.
I have read like if specified in dp it will get automatically scaled.
In my sample i just have a single layout. there i have placed an edit text.
and given width , suppose 170 dp. suppose width wise it is half the screen in a 5 inch phone emulator.
What i was expecting is, if i show it on an tablet 7inch or 10 inch , there also it will be half the width of the screen (i.e it will get automatically scaled). But it didnt. in a 10 inch tablet it is only very small size.
what should i do to achieve this only through layout xml ( only single xml )
Dont set a Static width for the Textview as android will automatically scale it the the correct size using
android:layout_width="fill_parent"
android:layout_height="wrap_content"
Basically what this does is makes the TextView the full size of the width of the device, and wraps the Height only to the needed height of the text.
YOu could also do warp_content for width to if you wanted. This is the best way. If you set it statically, you will need to create different layouts using XML.
Learn to use layout weights, you can use them like a percentage of 100.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="50"
android:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight="50" />
</LinearLayout>
Here the textview takes up 50% of the screen width and the other view is a kind of invisible spacer taking up the other 50% of the screen width.
Which looks something like this (Eclipse XML preview):
As you can see the textview wraps when it gets to 50% of the screen. Working on all sizes of screen.