Управление видимостью представления из ресурсов

У меня есть макет, который содержит два ImageViews. Я хочу, чтобы один из них был виден в портретном режиме, а другой — в ландшафтном. Как мне достичь этого с помощью ресурсов? (Я знаю, как установить его программно, но для этого конкретного использования мне нужно использовать ресурсы).

Я пробовал что-то вроде

в 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"   
      ...
/>

в 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>

в res/values-land/integers.xml:

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

Но я получаю ошибку времени выполнения (индекс за пределами границ) при попытке раздуть изображения. Когда я удаляю операторы android:visibility, программа запускается, но я вижу оба изображения.

Вопрос. Как использовать ресурс в качестве значения атрибута android:visibility?

(если вам интересно, почему установка его программно мне не поможет, это связано с автоматическим переключением виджетов приложений с изображением файла uri).


person user1139880    schedule 17.03.2012    source источник


Ответы (3)


это станет возможным, когда вы воспользуетесь этим трюком, добавите свою линию видимости в стиль и поместите два экземпляра этого файла в режим -land и обычный режим.

То есть в файле styles.xml в папке values поместите стиль с именем s1, а в нем поместите android:visibility=visible, а в styles.xml в папке values-land поместите стиль с именем s1 и поместите android:visibility=gone.

также в файле styles.xml в папке values поместите стиль с именем s2, а в нем поместите android:visibility=gone, а в styles.xml в папке values-land поместите стиль с именем s2 и поместите android:visibility=visible.

а затем установите s1 на первое изображение и s2 на второе.

Решение, данное уважаемым Кальвином, также верно, но когда у вас сложный макет, который может меняться со временем, было бы лучше иметь один файл макета, и вам меньше нужно будет его менять.

person Keyhan Asghari    schedule 17.03.2012
comment
Спасибо, Кейхан, я попробую и сообщу здесь. Поможет ли этот подход и в этом вопросе? stackoverflow .com/questions/9745227/ . У меня есть 5 разных размеров, умноженных на два режима (портретный и языковой). Использовать стиль также для управления размером ImageView? Таким образом, у меня будет один макет с двумя изображениями и 5 парами стилей ориентации/портрета. (обходить ограничения RemoteViews не весело ;-)). - person user1139880; 17.03.2012
comment
Работает хорошо. Это было большим подспорьем!. Спасибо Кейхан. - person user1139880; 17.03.2012
comment
Предлагаемое решение предполагает использование ресурсов стилей. - person denispyr; 17.06.2013
comment
Создание целого стиля только для установки атрибута не является хорошей практикой, особенно если вам уже нужно установить больше атрибутов в стилях (у вас не может быть двух стилей в представлении). Ответ Флавио намного чище. - person TWiStErRob; 24.04.2015

Это старый вопрос, который уже был принят, но следующее решение может помочь кому-то другому:

Если вы проверите res/values/attrs.xml в исходном коде Android, вы увидите такое определение свойства видимости:

 <!-- 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>

Этот атрибут ожидает строковое значение (видимый, невидимый, исчезнувший), которое будет преобразовано в (0, 1, 2) соответственно. Таким образом, вы можете объявить целочисленные ресурсы, содержащие эти значения, следующим образом:

значения/целые числа.xml

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

значения-земля/integers.xml

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

Однако, если вы хотите сделать его еще лучше, чтобы перестать каждый раз угадывать эти числовые константы, вы можете сделать так:

значения/целые числа.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 -->

значения-земля/integers.xml

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

Вы можете использовать этот подход или тот, который предложил Кейхан. Выберите тот, который подходит вам лучше.

person Flávio Faria    schedule 16.01.2013
comment
Это также работает, объявляя их как <integer>, а не <string> - person TalkLittle; 01.01.2014
comment
хорошей практикой было бы сохранить исходные значения Android для видимого, невидимого и исчезнувшего (не 0, 1, 2, а 0, 4, 8) - person Bartek Lipinski; 19.08.2014
comment
Ну, это не совсем то, как это работает. Если вы отметите код класса View, эти значения (0, 1 и 2) используются для доступа к позициям этого члена: private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};. Вот почему вы не можете использовать 0, 4 и 8, потому что 0, 1 и 2 обозначают индексы VISIBLE, INVISIBLE и GONE. - person Flávio Faria; 19.08.2014
comment
Псевдонимы у меня не работают (например, view_visible). Это работает только в том случае, если я назначаю 0, 1, 2 целочисленному ресурсу, который я использую напрямую. (но +1 за этот бит!!) - person charles-allen; 25.11.2017
comment
Из android.view.View#VISIBLE``android.view.View#INVISIBLE и android.view.View#GONE значений переменных должно быть <enum name="visible" value="0" /> <enum name="invisible" value="4" /> <enum name="gone" value="8" /> - person NickUnuchek; 14.05.2019

Это невозможно. (Я попытался определить fill_parent как строку и использовать ее для layout_width, но тоже не получилось.)

Почему бы вам не использовать 2 макета?

  1. рез/макет/may_layout.xml
  2. res/layout-land/may_layout.xml

Каждый из которых определяет правильное изображение для отображения.

Кроме того, наличие value-land может вызвать у вас проблемы, когда вам нужно поддерживать несколько языков. (Вам нужно будет значение xx-land для каждого языка)

person Calvin    schedule 17.03.2012
comment
Спасибо, Кальвин. Я пытался избежать дублирования макета, если я не могу автоматически генерировать их из шаблона во время сборки. Не знаю, поддерживает ли это eclipse и насколько оно будет стандартным. - person user1139880; 17.03.2012