Is it possible to save layout_weight in an xml? - android

I need to change the layout_weight of 3 views in a layout, according to the physical size of the screen. The views have the weight of 0-1-0, but this has to change to 0.2-0.6-0.2 when the layout is used in an xlarge screen.
I tried saving the layout_weight inside different copies of the dimensions.xml (one in values/dimensions and an other one in values-xlarge/dimensions), but it looks like I cannot give a dimension without setting dp/px or w/e (cannot save a "raw" number like 1, or 0.2).
Is it possible to do via xml somehow, or do I have to work programmatically in order to achieve that?

Try an integer resource file. It is very similar to dimensions.
http://developer.android.com/guide/topics/resources/more-resources.html

Create a file in your corresponding values folders i.e. values, values-large, values-xlarge, .... Add a resources file with content similar to this example:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item type="integer" name="layout_weight_xy">7</item>
</resources>
and then call
android:layout_weight="#integer/layout_weight_xy"
in your layout file.

You can create special layout in layout-xlarge folder and provide different weights there

First, define your resource e.g integer.xml and make sure you set the correct type and format. If you want to use it for layout_weight you can set type="integer" format="float".
<item name="my_weight_value" type="integer" format="float">1.2</item>
Then we can use it in layout
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="#integer/my_weight_value"
android:orientation="vertical">
</LinearLayout>

Related

How to specify fixed layout_marginLeft for smartphones and wrap_content for tablet for NavigationDrawer

I have the below navigation drawer and I want to give layout_marginLeft as -64dp for smartphones and wrap_content for tablets.
Please let me know how to do that?I don't want to create separate laytout.xml files for smartphone and tablets i.e I have only one layout.xml file. As of now I am specifying different dimension in dimes.xml files which are created for smartphones and tabs.
<!-- The navigation drawer -->
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layout_marginLeft="-64dp"
Assuming that you know how to create different dimes.xml files for multiple screens (If you don't know that have a look in How to define dimens.xml for every different screen size in android?) your problem should be how to set android:layout_marginLeft in the specific xml file using dimen value.
You can try this way
for wrap_content>
<dimen name="your_value">-2dp</dimen>
for match_parent>
<dimen name="your_value">-1dp</dimen>
and set android:layout_marginLeft="#dimen/your_value"
You Just have to create 5 layouts file for all screen sizes with same name(of layout file) and store it into different folder In (hdpi,mdpi,xhdpi,xxhdpi,xxxhdpi).

Change several layouts for different densities at the same time

If I have three different layouts for a same view (lets say, one for phone, one for tablet and one for tablet in landscape) and I want to add/change a property that the three of them share (lets say, the android:background), is there a way of adding/changing it in one place and have it automatically in the other two layouts? Is there an alternative to copy-and-paste it?
Unfortunately not really. You could have separate layouts for each set of elements and use include to include them in each subsequent layout, then just updating the single layout would update all of them. But this would mean having a lot of stand alone layouts. A good example of this is using a seperate Toolbar layout like so:
Toolbar layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
style="#style/Toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
Then have this line in all layouts which you want to use Toolbar.
<include layout="#layout/toolbar" />
This technique could be applied to anything you like, and would allow you to in future only edit each separate layout once and have it applied everywhere you use it. You can also edit dimensions inside these Layouts under the include, or in code.
The only other way to achieve what you want would be to handle it all explicitly in code but I wouldn't recommend this.
You can apply style for the widget(TextView or LinearLayout for example) that uses background property and determine background property in that style.
Changing background property in style will affect all the widgets this style was previously applied to.
http://developer.android.com/guide/topics/ui/themes.html

Set visibility via bindings - dimens.xml

Is it possible to set the visibility via bindings? (dimens.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="#whatever/visibility_of_this_view"
android:orientation="horizontal">...
so that I can put something inside of the dimens.xml like:
<whatever name="visibility_of_this_view">visible</whatever>
I don't want to do it via code or different layouts, just with different dimens.xml.
How ever your different dimens are selected (layout, api, what ever) you should use the same mechanism to select another layout or even a different style which sets the visibility. Every other way seems to be a abusive way :)

Referencing another layout.xml file without duplicating it

I need to provide the same layout.xml file for an Activity for several different qualifiers. I know that there's a way to just reference one existing layout.xml instead of really copying it and having a duplicate one.
But how? Can't find it in the Android docs right now... :-/
Anybody faster than me?
EDIT: although I found this "solution" I am still not there.
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="#layout/main_ltr"/>
</merge>
I need to point to a different qualifiers's layout file, not to another layout file in the same qualifier.
Reason behind it: I specified the new Android 3.2 qualifier by proving screen width qualifiers. But on Android 3.0/3.1 this does not work, I need xlarge there, but I want it to be exactly the SAME file, not a copy!
If I understood correctly asker has one layout file for xlarge and sw-600dp and another one for all the rest. Anyway that was my situation when I stumbled on this question.
One can solve this by creating folders layout-xlarge and layout-s600dp and put one layout file in each but with the same contents. But one would like not to have two exact same files in two folders for obvious reasons.
This is my solution for the problem. Dont make layout-xlarge and layout-sw600dp files at all. Let's say you're creating a cool activity with layout file /res/layout/cool_activity.xml. Create your tablet layout file in the same folder but with a different name, i.e. /res/layout/cool_activity_for_tablet.xml and then create folders values-xlarge and values-sw600dp with layout.xml files in it with the following content
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="cool_activity" type="layout">#layout/cool_activity_for_tablet</item>
</resources>
Yes you will still have 2 of these with the same content but this is dumb content not the layout itself which can be hundreds of lines of xml.
<include> see Layout tricks #2
<merge> see Layout tricks #3
Create a wrapper layout my_activity.xml and your layouts for small and xlarge devices.
<merge>
<include layout="#layout/my_activity_small.xml"/>
</merge>
Your resources should look like:
layout
-> my_activity.xml
-> my_activity_small.xml
-> my_activity_xlarge.xml
Now override my_activity.xml in layout-xlarge and layout-sw600dp:
<merge>
<include layout="#layout/my_activity_xlarge.xml"/>
</merge>
Your ressources should look like:
layout
-> my_activity.xml <-- includes my_activity_small.xml
-> my_activity_small.xml
-> my_activity_xlarge.xml
layout-xlarge
-> my_activity.xml <-- includes my_activity_xlarge.xml
layout-sw600dp
-> my_activity.xml <-- includes my_activity_xlarge.xml
Use my_activity.xml in your code for loading the layout.
P.S.: You can not point to a layout in another qualifier's directory, as you mentioned in one of the comments.

Android: How to use an xml string value to determine layout orientation

I have a simple linear layout that I would like to change based on the screen size of the device. What I am trying to do is something like
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="#string/cover_orientation"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
I have created different dimen.xml files under values and values-xlarge so that the cover_orientation variable will take on a different value (either 'vertical' or 'horizontal') based on the screen size.
string name="cover_orientation">"vertical"
But this doesn't work. I have found a temporary work around that involves checking the screen size and changing the orientation manually:
if(getResources().getString(R.string.screen_size) == "xlarge"){
((LinearLayout)convertView).setOrientation(1);
}
but it seems like you should be able to do it the first way (much more elegant/less code).
I considered just having a different layout for each screen size, but the layout is actually quite big and this is the only change I need for the different screen sizes. So it didn't make much sense to me to duplicate the entire layout.
Thanks!
A nice way to do this is to add
android:orientation="#integer/cover_orientation"
on your LinearLayout and defining it like below.
in values/consts.xml:
<resources>
<integer name="orientation_horizontal">0</integer>
<integer name="orientation_vertical">1</integer>
</resources>
in values/something.xml:
<resources>
<integer name="cover_orientation">#integer/orientation_vertical</integer>
</resources>
in values-land/something.xml:
<resources>
<integer name="cover_orientation">#integer/orientation_horizontal</integer>
</resources>
This way you avoid hardcoding zeros and ones in your orientation variable definitions across the app.
I eventually found a solution to the problem by looking around the android docs. What I originally had was a LinearLayout, that contained an image an text inside of it (there was actually a lot more content inside of it but I'll keep it simple for this example), that looked something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView android:id="#+id/cover"
android:layout_width="#dimen/cover_width"
android:layout_height="#dimen/cover_height"/>
<TextView android:id="#+id/title"
android:gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="#dimen/title_font_size"
android:scrollHorizontally="true"
android:maxLines="1"
android:ellipsize="end" />
</LinearLayout>
What I wanted was to be able to dynamically change whether the text was beside the image or below the image, based on the device screen size. In other words i wanted to dynamically change the android:orientation dynamically. My first thought, which I posted in my question, was to have a string variable declared in the res/values/dimen.xml as
<string name="orientation">horizontal</string>
and another string variable declared in res/values-large/dimen.xml as
<string name="orientation">vertical</string>
Then when I was setting the orientation in the LinearLayout I thought I could use
android:orientation="#string/orientation"
But this didn't work. What I ended up doing was splitting the layout up. I originally had reservations about having two separate layouts because I thought I would have a lot of duplicated code for one simple change. That was before I learned about include and merge. First I created a common layout file that was the image and text in res/layout/content.xml that looked like:
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<ImageView android:id="#+id/cover"
android:layout_width="#dimen/cover_width"
android:layout_height="#dimen/cover_height"/>
<TextView android:id="#+id/title"
android:gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="#dimen/title_font_size"
android:scrollHorizontally="true"
android:maxLines="1"
android:ellipsize="end" />
</merge>
(Sidenote: I was originally confused at what the merge tag did. It is not merging what is inside the merge tag (in this example the image and the text) it is basically saying whatever parent file includes this file, merge the contents in between the tags into the parent file)
Then I created two separate files for just the LinearLayout that included the image and description xml file. One in res/layout/container.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/library_item_container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<include layout="#layout/content"/>
</LinearLayout>
and one in res/layout-large/container.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/library_item_container"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<include layout="#layout/library_item_contents"/>
</LinearLayout>
Notice the only difference between the two container.xml files is that the orientation has changed from vertical to horizontal. Now there is minimal code that is repeated and problem is solved!
#odiggity, thank you for posting this question. I was trying the same. Application crashed upon starting.
I would assume that it's a runtime typing issue. In other words, there are only two legal values for the orientation attribute, which is not reflected by the string "type". What the framework would probably have to do is introduce another specialized resource type, similar to dimen or boolean.
I feel there is an answer to your question which addresses more cases than your own answer above. One can use style inheritance to define all attributes except orientation in an orientation-independent parent style and then add only the orientation in a small orientation-dependent style definition with that as a parent.
This way, one can avoid duplication even in complex cases.
I suggest you do some reading: http://developer.android.com/guide/practices/screens_support.html

Categories

Resources