Controlling view visibility from a resources

14,243

Solution 1

it will be possible when you use this trick, add your visibility line to a style and put two instances of that file in -land and normal mode.

I mean in file styles.xml in folder values put a style with name s1, and put android:visibility=visible in that, and in styles.xml in folder values-land put a style with name s1, and put android:visibility=gone.

also, in file styles.xml in folder values put a style with name s2, and put android:visibility=gone in that, and in styles.xml in folder values-land put a style with name s2, and put android:visibility=visible.

and then, set s1 to first imageview and s2 to second.

solution given by dear Calvin is also correct, but when you have a complex layout that may change during time, having one layout file would be better, and will have less need to change.

Solution 2

This is an old question that has already been accepted, but the following solution may help someone else:

If you check res/values/attrs.xml in Android source code, you'll see the definition of visibility property like this:

 <!-- Controls the initial visibility of the view.  -->
    <attr name="visibility">
        <!-- Visible on screen; the default value. -->
        <enum name="visible" value="0" />
        <!-- Not displayed, but taken into account during layout (space is left for it). -->
        <enum name="invisible" value="1" />
        <!-- Completely hidden, as if the view had not been added. -->
        <enum name="gone" value="2" />
    </attr>

This attribute expects a string value (visible, invisible, gone) that will be converted to (0, 1, 2) respectively. So, you can declare integer resources containing these values like this:

values/integers.xml

<integer name="visible_in_portrait">2</integer> <!-- This is GONE -->

values-land/integers.xml

<integer name="visible_in_landscape">0</integer> <!-- This is VISIBLE -->

However, if you want to make it even better in order to stop guessing these numeric constants every time, you could do like this:

values/integers.xml

<!-- These are alias for the constants we'll reference below -->
<integer name="view_visible">0</integer> <!-- This is VISIBLE -->
<integer name="view_invisible">1</integer> <!-- This is INVISIBLE -->
<integer name="view_gone">2</integer> <!-- This is GONE -->

<integer name="visible_in_portrait">@integer/view_gone</integer> <!-- We're referencing the visibility alias we declared above -->

values-land/integers.xml

<integer name="visible_in_landscape">@integer/view_visible</integer>

You can use this approach or the one suggested by Keyhan. Choose the one that fits you better.

Share:
14,243
user1139880
Author by

user1139880

Updated on June 09, 2022

Comments

  • user1139880
    user1139880 almost 2 years

    I have a layout that contains two ImageViews. I want one of them to be visible in portrait and the other in landscape. How do I achieve it using resources? (I know how to set it programmatically for but this specific use I need to achieve it using resources).

    I tried something like

    in res/layout/may_layout.xml:

    ...
    <ImageView
          android:id="@+id/image1"
          android:visibility="@integer/visible_in_portrait"   <<-- is this allowed?
          ...
    />
    <ImageView
          android:id="@+id/image2"
          android:visibility="@integer/visible_in_landscape"   
          ...
    />
    

    in res/values/integers.xml:

    ...
    <!-- NOTE: 0 and 8 are VISIBLE and GONE respectively -->
    <integer name="visibile_in_portrait">0</integer>
    <integer name="visibile_in_landscape">8</integer>
    

    in res/values-land/integers.xml:

    ...
    <integer name="visibile_in_portrait">8</integer>
    <integer name="visibile_in_landscape">0</integer>
    

    But I get a runtime error (index out of bound) when trying to inflate the images. When I remove the android:visibility statements, the program runs but I see both images.

    Q: What is the way to use a resource as a value for the android:visibility attribute?

    (if you wonder why setting it programmatically will not help me, it has to do with automatic landspace/portrait switch of app widgets with file uri bitmaps).

  • user1139880
    user1139880 about 12 years
    Thanks Calvin. I was trying to avoid duplicating the layout, unless I can generate them automatically from a template at build time. Don't know if eclipse supports it and how standard it will be.
  • user1139880
    user1139880 about 12 years
    Thanks Keyhan, I will give it a try and report here. Will this approach also help with this question? stackoverflow.com/questions/9745227/… . I have 5 different sizes times two modes (portrait and langscape). Use the style also to control the ImageView size? This way I will have a single layout with two images and 5 pairs of orientation/portrait styles. (working around the limitations of RemoteViews is not fun ;-)).
  • user1139880
    user1139880 about 12 years
    Works well. This was a great help!. Thanks Keyhan.
  • denispyr
    denispyr almost 11 years
    The suggested solution involves the usage of Style Resources
  • TalkLittle
    TalkLittle over 10 years
    It also works declaring them as <integer> rather than <string>
  • Bartek Lipinski
    Bartek Lipinski over 9 years
    the good practice would be to keep the original android values for visible, invisible and gone (not 0, 1, 2, but 0, 4, 8)
  • Flávio Faria
    Flávio Faria over 9 years
    Well, that's not exaclty how it works. If you check the View class code, these values (0, 1 and 2) are used to access the positions of this member: private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};. That's why you can't use 0, 4 and 8, because 0, 1 and 2 stand for VISIBLE, INVISIBLE and GONE indices.
  • TWiStErRob
    TWiStErRob about 9 years
    Creating a whole style just to set an attribute is not a good practice, especially if you need to set more attributes in styles already (you can't have two styles on a view). Flávio's answer is much cleaner.
  • charles-allen
    charles-allen over 6 years
    Aliases doesn't work for me (i.e. view_visible). It only works if I assign 0, 1, 2 to an integer resource that I use directly. (but +1 for that bit!!)
  • NickUnuchek
    NickUnuchek almost 5 years
    From android.view.View#VISIBLE``android.view.View#INVISIBLE and android.view.View#GONE values of variables should be <enum name="visible" value="0" /> <enum name="invisible" value="4" /> <enum name="gone" value="8" />