开发者

How can I use layout_width using resource file?

There are a activity what I want to fill the screen in a phone and pop up(dialog) for a tablet.

I thought I make a layout file like this,开发者_开发知识库

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="@dimen/main_layout_width"
  android:layout_height="match_parent">

and externalize the value of width as

in values/dimens.xml

<dimen name="tutorial_width">match_parent</dimen>

in values-xlarge/dimens.xml

<dimen name="tutorial_width">320dp</dimen>

But I can't representation 'match_parent' as dimen element. Any help? Thanks!


The best way I found: - instead of "match_parent" and "fill_parent" write "-1dp" - instead of "wrap_content" write "-2dp"


dp depends on the device display metrics and won't work on all devices without a set of density-specific overlays, however, px can be used instead.

Unfortunately, the simple rounding technique used by TypedValue#complexToDimensionPixelSize() only considers non-negative values:

final int res = (int)(f+0.5f);
if (res != 0) return res;
if (value == 0) return 0;
if (value > 0) return 1;
return -1;

When f (the px value) is negative, the result is usually rounded incorrectly because it always uses addition. The following pixel sizes are observed for negative px dimensions:

0px = 0.0
-1px = -1.0
-2px = -1.0
-3px = -2.0
-4px = -3.0
-5px = -4.0
...

I opened an AOSP issue for this method:

TypedValue#complexToDimensionPixelSize() rounds negative dimensions incorrectly

Considering this behavior, the following values will work on all devices:

<dimen name="match_parent">-2px</dimen>
<dimen name="wrap_content">-3px</dimen>

You can use -1px or -2px for match_parent, but wrap_content must be -3px. Either combination works on devices and emulators.

In practice, I've found that IntelliJ's Preview feature fails to render layouts when -1px is used for match_parent, and incorrectly renders -2px as if it were "wrap_content" when referenced by another dimension e.g. <dimen name="my_width">@dimen/match_parent</dimen>. I have opened an issue for IntelliJ IDEA:

Android Preview cannot render layout_width="-1px"


I used a style to fix this problem. Having separate xml style elements with android:layout_width items for different screen sizes solved the problem without using the undocumented -1dp


I am not able to comment yet so i'm writing new answer. I used answer provided by @pjanecze in my project. All was fine till few days ago when suddenly some devices started to report strange widget positioning. Devices with very high density, instead of getting match_parent as -1 from my dimenstions (which was equivalent to android constant match_parent = -1 in layout parameters), it was getting -2, which means that width was set to wrap_content (-2 in layout_parameters). Obviously because -1dp is converted to pixels in runtime, and -1dp was in some cases -2px.

So ... instead of using constant -1dp and -2dp, you should use -1px and -2px for match_parent and wrap_content.


Whats works for me and probably features academic correctness is something like this:

<!-- In values/dimens.xml -->
<item name="width_match_unless_huge" type="dimen" format="integer">-1</item>

<!-- In values-sw600dp/dimens.xml -->
<item name="width_match_unless_huge" type="dimen" format="dimension">600dp</item>

This allows you to mix sizing behavior constants like MATCH_PARENT and concrete sizes in dp depending on the current configuration.

You would use it as a regular <dimen/>:

<LinearLayout
    android:layout_width="@dimen/width_match_unless_huge"
    .../>


According this great contribution: http://blog.danlew.net/2015/01/06/handling-android-resources-with-non-standard-formats/

  1. Let's try defining both match_parent and wrap_content without a format:

    <item name="match_parent" type="dimen">-1</item>
    <item name="wrap_content" type="dimen">-2</item>
    
  2. We can reference those in any other dimension value:

    <!-- Inside /res/values/dimens.xml -->
    <dimen name="responsive_width">@dimen/match_parent</dimen>
    
    <!-- Inside /res/values-sw800dp/dimens.xml -->
    <dimen name="responsive_width">800dp</dimen> 
    

For more info visit the web page I mentioned earlier!


You can create two layouts - default with android:layout_height="match_parent" in "layout" dir, and for tablet android:layout_height="320dp" in "layout-xlarge" dir


As mentioned earlier in https://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html#MATCH_PARENT MATCH_PARENT = -1 and WRAP_CONTENT = -2. Instead of declaring the values as Dimension resources I have successfully declared and used them as Integer resources. So for the example to work you can use two Integer resource files:

values/integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="tutorial_width">-1</integer>
</resources>

values-sw600dp/integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="tutorial_width">-2</integer>
</resources>

And the layout file will be:

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="@integer/tutorial_width"
  android:layout_height="match_parent">


Value -1 was not working for me on android api 30 emulator of Pixel 4.

Clean solution is to define sw600dp/styles.xml and create base style for your component in styles f.e. DialogControllerTypeGridBase then create other that ha its as parent DialogControllerTypeGrid and also other in sw600dp.

Example:

styles.xml

<style name="DialogControllerTypeGridBase" parent="CSGridMatch">
    <item name="android:layout_height">wrap_content</item>
    <item name="android:background">@drawable/background_bordered_section</item>
    <item name="android:horizontalSpacing">8dp</item>
    <item name="android:padding">4dp</item>
    <item name="android:verticalSpacing">8dp</item>
</style>

<style name="DialogControllerTypeGrid" parent="DialogControllerTypeGridBase">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:numColumns">6</item>
</style>

sw600dp/styles.xml

 <style name="DialogControllerTypeGrid" parent="DialogControllerTypeGridBase">
        <item name="android:layout_width">450dp</item>
        <item name="android:numColumns">3</item>
 </style>

This way nothing gets duplicated and you dont use meaningles values like -1, -2 that dont work reliably across device based not just by me but also comments from others.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜