In my android application, I have a RelativeLayout which contains some Fragments. However, this layout does not scale to different screen sizes. Consider this screenshot when the screensize is 5.2" diagonally, 1080x1920 resolution 420dpi: (Desirable output)
When I change the phone to a 5.0", 1080x1920 resolution xxhdpi, I get this display:
As you can see the buttons on the two right-hand columns are overlapping, which is the problem I am asking about.
Here is the main activity XML file, which contains the various fragments
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:style="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp">
<!--This is the box appearing at the top of the layout-->
<TextView
android:id="#+id/window"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#drawable/window_border"
android:fontFamily="monospace"
android:minLines="1"
android:text=""
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textIsSelectable="true"/>
<!--This is the first row of buttons, there are 4 of them-->
<fragment
android:id="#+id/screenOps"
android:name="net.magnistudio.deskcalculator.ScreenOps"
android:layout_width="wrap_content"
android:layout_alignEnd="#+id/digits"
android:layout_height="wrap_content"
android:layout_below="#+id/window"
tools:layout="#layout/layout_screen_ops"/>
<!--This is the 3x3 rectangle appearing directly below the screenOps
frag -->
<fragment
android:id="#+id/digits"
android:name="net.magnistudio.deskcalculator.Digits"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout="#layout/layout_digits"
android:layout_alignBottom="#+id/basicOps"/>
<!--This is the rightmost fragment-->
<fragment
android:id="#+id/basicOps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="net.magnistudio.deskcalculator.BasicOps"
tools:layout="#layout/layout_basic_ops"
android:layout_alignParentEnd="true"
android:layout_below="#+id/window"/>
<!--Lower fragment, it is 6x4-->
<fragment
android:id="#+id/scientific"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="net.magnistudio.deskcalculator.Scientific"
tools:layout="#layout/layout_scientific"
android:layout_below="#+id/digits"/>
</RelativeLayout>
Each button has this style
<style name="calcBtnAppearance">
<item name="android:textSize">14sp</item>
<item name="android:textColor">#color/calcBtn</item>
<item name="android:textStyle">normal</item>
<item name="android:textAllCaps">false</item>
<item name="android:layout_width">0dp</item>
</style>
I think one solution would be to adjust programatically the sizes of the layouts based on the size of the current phone, but maybe that is just sweeping some other problem (of the layout itself) under the rug?
Also, each button is located within a LinearLayout, which is inside of the LinearLayout for the fragment. Consider this sample excerpt from a fragment layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3">
<Button
android:id="#+id/dig7"
style="#style/calcBtnAppearance"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=""/>
more buttons
</LinearLayout>
<LinearLayout>
In the RelativeLayout the children are arranged according to their relative form to each other. As far as I remember, the RelativeLayout does not scale the contained elements if the resolution or the screen size changes.
Maybe you should take a look here:
[https://stackoverflow.com/a/21381065/6908102
][1]
A possible solution:
To adjust the size of the buttons to the respective resolutions, create a separate "values" folder for each resolution. (See also picture 2 marked blue).
- Picture 2 -
Then create a new "dimens.xml" file in each of these folders.
As an example:
res/values/dimens.xml:
<resources>
<!-- ButtonSize -->
<dimen name="dimenButtonHeight">15dp</dimen>
<dimen name="dimenButtonWidth">25dp</dimen>
</resources>
res/values-xxhdpi/dimens.xml:
<resources>
<!-- ButtonSize -->
<dimen name="dimenButtonHeight">10dp</dimen>
<dimen name="dimenButtonWidth">20dp</dimen>
</resources>
Of course, you still have to adjust the size specifications to your layouts.
res/values/style.xml:
In your Style.xml file you have to add the following lines:
<style name="calcBtnAppearance">
<item name="android:textSize">14sp</item>
<item name="android:textColor">#color/calcBtn</item>
<item name="android:textStyle">normal</item>
<item name="android:textAllCaps">false</item>
<item name="android:layout_height">#dimen/dimenButtonHeight</item>
<item name="android:layout_width">#dimen/dimenButtonWidth</item>
</style>
Maybe that will solve your problem. Otherwise, you can, as shown in Figure 2 well, synonymous for each Resolution create a separate "layout" folder. Then copy the files from the standard layout folder into the newly created folder and adjust them or you can also position the items in a different order. But is a little more work.
Related
Recently, I stunned with a problem. On my android phone elements of the list or scroll views with the same elevation have different shadows related to their positioning. For example, views on the top of the screen have a small light shadow, whenever views on the bottom of the screen have more dark and strong shadow. Here is a screenshot from Google Keep application:
So, I thought that this is because of exactly Google Keep application. Maybe guys from Google decided to do that trick with shadows for their application. Thus, I created a sample application.
My layout:
<?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="vertical">
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
<TextView
style="#style/AppButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Test"/>
</LinearLayout>
My styles:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="AppButton">
<item name="android:background">#color/colorAccent</item>
<item name="android:elevation">4dp</item>
<item name="android:gravity">center</item>
<item name="android:padding">16dp</item>
<item name="android:textColor">#android:color/white</item>
</style>
</resources>
And the output is:
As you see, we have the same effect (top view has a small shadow, bottom view have a big shadow). So my questions are:
What I did wrong?
How can I achieve the same shadow for all views (not different by their positions)?
Also, I haven't found any explanations in docs, so where I can read about that phenomenon?
Does it happen on all devices or only on specific?
P.S.: I have Nexus 5X, Android 7.1.2.
UPD:
An important mention that from Android Studio Preview Window everything is fine. Every view has the same shadow as other. But on a real device, you can see the difference.
Shadows generated by Elevation API are positioned in 3D space, which means that the look of each shadow is affected not only by its elevation value, but also by shadow caster's x and y position on screen. It's pretty much like in the real world - objects beneath a light source cast shorter shadows than objects further away.
Take a closer look at the first image you posted. Shadows are longer on left edges of the left cards and on right edges of the right cards than on the edges at the horizontal center.
Ad. 1. Nothing. It just works that way.
Ad. 2. It's not possible using Elevation API. You can draw shadows by yourself.
Ad. 3. Don't know, sorry.
Ad. 4. All devices.
Ad. UPD. Shadows in the editor are static, so there's no effect you're observing.
I'm trying to use <include> to include ImageButtons inside a android.support.v7.widget.GridLayout. The problem is, if I don't specify all the attributes explicitly on my <include> elements, they don't display properly. In other words, the include is pointless since I have to redeclare all the attributes on every <include> element.
dialpad_button.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageButton
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:layout_width="0dp"
android:layout_height="0dp"
grid:layout_columnWeight="1"
grid:layout_rowWeight="1"
grid:layout_gravity="fill"
android:layout_margin="5dp"
android:scaleType="centerInside"/>
dialpad_view.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:id="#+id/dialpad_grid_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
grid:alignmentMode="alignBounds"
grid:columnCount="2"
grid:rowCount="1">
<include
android:id="#+id/dialpad_view_btn1"
android:src="#drawable/dialpad_1"
layout="#layout/dialpad_button" />
<include
android:id="#+id/dialpad_view_btn2"
android:src="#drawable/dialpad_2"
layout="#layout/dialpad_button" />
</android.support.v7.widget.GridLayout>
If I declare all the attributes directly on the <include>s, here's what it looks like in XML:
<include
layout="#layout/dialpad_button"
android:id="#+id/dialpad_view_btn1"
android:src="#drawable/dialpad_1"
android:layout_width="0dp"
android:layout_height="0dp"
grid:layout_columnWeight="1"
grid:layout_rowWeight="1"
grid:layout_gravity="fill"
android:layout_margin="5dp"
android:scaleType="centerInside" />
As you can see in the comparison image below, the buttons now scale properly but the images are nowhere to be seen.
And if I change the <include>s to ImageButton, things work as expected.
<ImageButton
android:id="#+id/dialpad_view_btn1"
android:src="#drawable/dialpad_1"
android:layout_width="0dp"
android:layout_height="0dp"
grid:layout_columnWeight="1"
grid:layout_rowWeight="1"
grid:layout_gravity="fill"
android:layout_margin="5dp"
android:scaleType="centerInside" />
Is there a workaround to this?
Since I'm going to have 12 near-identical buttons in my dialpad, I'd really like to clean the XML up by including a "template" and only modifying the necessary attributes for each button (i.e. src and id).
EDIT
Trying to use styles, as suggested in one answer, did not work. None of the views that I applied the styles to get displayed. What's even more strange, even if I just apply the style to one of the views in the GridLayout, only the last view gets displayed (I've shortened down the sample code here to only two views for readability, in reality I have twelve).
Here's the style I tried using:
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto" >
<style name="dialPadButtonStyle">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">0dp</item>
<item name="grid:layout_columnWeight">1</item>
<item name="grid:layout_rowWeight">1</item>
<item name="grid:layout_gravity">fill</item>
<item name="android:layout_margin">5dp</item>
<item name="android:scaleType">centerInside</item>
<item name="android:background">#android:color/transparent</item>
</style>
</resources>
Maybe you can use a style to declare the common attributes and then set it for every button.
<style name="dialPadButtonStyle">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">0dp</item>
<item name="android:layout_columnWeight">1</item>
<item name="android:layout_rowWeight">1</item>
<item name="android:layout_margin">5dp</item>
<item name="android:src">#android:drawable/ic_menu_camera</item>
</style>
I also added: columnCount to 3 and rowCount to 4 for GridLayout and added 12 ImageButtons with that style. The final result is this:
I'm making this simple UI. It fits nicely on the Nexus 5X (emulator)(1920x1080).
But when I'm running the app on the Galaxy Nexus (emulator)(1280x720), the UI doesnt seem to resize which causes it not fitting on the screen. As you can see, I'm using for the sizes only DP's. What am I doing wrong?
Nexus 5X:
Galaxy Nexus:
I have the following code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
style="#style/EditValues"
android:hint="num1"/>
<EditText
style="#style/EditValues"
android:hint="num2"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test123333333"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingBottom="70dp">
<android.support.v7.widget.AppCompatButton
style="#style/OperatorButton"
android:text="+"/>
<android.support.v7.widget.AppCompatButton
style="#style/OperatorButton"
android:text="-"/>
<android.support.v7.widget.AppCompatButton
style="#style/OperatorButton"
android:text="*"/>
<android.support.v7.widget.AppCompatButton
style="#style/OperatorButton"
android:text="%"/>
</LinearLayout>
</LinearLayout>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="EditValues">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center_horizontal</item>
<item name="android:textSize">50dp</item>
</style>
<style name="OperatorButton">
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">100dp</item>
<item name="backgroundTint">#color/colorAccent</item>
<item name="android:textColor">#fff</item>
<item name="android:textSize">50dp</item>
</style>
</resources>
You misunderstand what dp is. 1 Dp is 1/160th of an inch. It allows you to make sure that an item is the same physical size across all devices- for example an item is always 1 inch wide or always has a quarter inch of padding. But if a screen is bigger it obviously has more dp than a smaller screen. You need to then use different sizes or even entirely different layouts for smaller devices if things don't fit.
Use a different dimensions for a different screens sizes.
<style name="OperatorButton">
<item name="android:layout_width">#dimen/operator_btn_width</item>
<item name="android:layout_height">#dimen/operator_btn_height</item>
....
Then create additional values directories values-ldpi, values-hdpi, values-xhdpi ...
and add dimens.xml files with different values for operator_btn_width etc.
<resources>
<dimen name="activity_horizontal_margin">100dp</dimen>
<dimen name="activity_vertical_margin">100dp</dimen>
...
Dimensions: http://developer.android.com/samples/BasicSyncAdapter/res/values/dimen.html
100dp is obviously going to take up more room on a smaller screen with a smaller resolution.
This is where you need different values in different folders ie styles-hdpi, styles-xhdpi,styles-xxhdpi
I'm having trouble with the layout of my Android app.
The graphical preview editor shows me an image like (and this is how I want it to look like):
I am using a table layout that looks like this:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:shrinkColumns="*"
android:stretchColumns="*" >
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffff"
android:padding="5dp" >
<TextView
style="#style/leftColumn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Branche" />
<TextView
android:id="#+id/textViewBranche"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/rightColumn"
android:text="Branche"
/>
</TableRow>
</TableLayout>
styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ... -->
<style name="leftColumn">
<item name="android:background">#2B60DE</item>
<item name="android:textColor">#ffffff</item>
</style>
<style name="rightColumn">
<item name="android:background">#C0C0C0</item>
<item name="android:textColor">#ffffff</item>
</style>
</resources>
If I run my app it looks like this:
As you can see only one text view is displayed. I would like the table layout to have 2 columns (just like in the preview). The first one (blue) indicating what I am displaying and the second (grey) the information provided by my adapter. However I only see the provided information of my adapter (in this case "sonstige (others)". So basically I only see the right column.
I have no idea why I can't see the content of the first text view (respectively the first row).
I played around with some properties like layout_width and layout_height but it doesn't change.
I'm running this app on my S3.
Any help would greatly be appreciated.
Cheers
Suppose I have a background in my Activity's root layout. I wish to place some buttons on the screen which always stay in the same place relative to the screen. How can I accomplish that?
I tried using dp and sp but if I test the layout in another screen it all falls apart. (So if it is OK in WVGA it is not working in QVGA. Am I doing something wrong?
This is my layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/menu_activity_bg" >
<Button
android:id="#+id/continueButton"
android:layout_width="110sp"
android:layout_height="30sp"
android:layout_marginLeft="100sp"
android:layout_marginTop="180sp"
android:background="#drawable/menu_activity_continue" />
<Button
android:id="#+id/newGameButton"
android:layout_width="130sp"
android:layout_height="35dp"
android:layout_marginLeft="90sp"
android:layout_marginTop="220sp"
android:background="#drawable/menu_activity_new_game" />
<!-- ... -->
</RelativeLayout>
My solution to this is to have a number of style types, which I place in the values-large, values-small, values-normal, and values-xlarge folders. A typical entry will look like this:
<resources>
<style name="bigText">
<item name="android:textSize">60dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_marginTop">5dp</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="android:textColor">#000000</item>
</style>
</resources>
Then my layout XMLs would look like:
<TextView
android:id="#+id/somTextValue"
style="#style/bigText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/someText" />
Having a number of these styles, I apply them to my objects that need to scale. Trial and error will allow me to find something that works well for all screen sizes.
I have one another 2 approaches:
Use layout weight to your view so that it will take space accordingly
Use of DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int wwidth = metrics.widthPixels; This will give you width & height of screen then while creating give measurement in percentage e.g. 20% of width. It is helpful when you are dynamically creating UI.