@ Ответ Aleadam очень полезен, но imho он пропускает одно существенное различие между enum
и flag
. Первый предназначен для нас, чтобы выбрать одно и только одно значение, когда мы назначаем соответствующий атрибут для некоторого просмотра. Однако значения последнего можно объединить с помощью побитового оператора ИЛИ.
Например, в res/values/attr.xml
<!-- declare myenum attribute -->
<attr name="myenum">
<enum name="zero" value="0" />
<enum name="one" value="1" />
<enum name="two" value="2" />
<enum name="three" value="3" />
</attr>
<!-- declare myflags attribute -->
<attr name="myflags">
<flag name="one" value="1" />
<flag name="two" value="2" />
<flag name="four" value="4" />
<flag name="eight" value="8" />
</attr>
<!-- declare our custom widget to be styleable by these attributes -->
<declare-styleable name="com.example.MyWidget">
<attr name="myenum" />
<attr name="myflags" />
</declare-styleable>
В res/layout/mylayout.xml
теперь мы можем сделать
<com.example.MyWidget
myenum="two"
myflags="one|two"
... />
Таким образом, перечисление выбирает одно из возможных значений, а флаги можно комбинировать. Числовые значения должны отражать эту разницу, как правило, вы хотите, чтобы последовательность шла 0,1,2,3,...
для перечислений (скажем, для использования в качестве индексов массива), а флаги - 1,2,4,8,...
, чтобы их можно было независимо добавлять или удалять, используя побитовую ИЛИ |
для объединения флагов.
Мы могли бы явно определить «мета-флаги» со значениями, которые не являются степенью 2, и, таким образом, ввести своего рода сокращение для общих комбинаций. Например, если мы включили это в нашу myflags
декларацию
<flag name="three" value="3" />
тогда мы могли бы написать myflags="three"
вместо myflags="one|two"
, чтобы получить полностью идентичные результаты как 3 == 1|2
.
Лично мне нравится всегда включать
<flag name="none" value="0" /> <!-- or "normal, "regular", and so on -->
<flag name="all" value="15" /> <!-- 15 == 1|2|4|8 -->
, что позволит мне сбросить или установить все флаги одновременно.
Более тонко, это может быть тот случай, когда один флаг подразумевается другим. Итак, в нашем примере предположим, что установленный флаг eight
должен заставить установить флаг four
(если он еще не был). Затем мы могли бы переопределить eight
и включить как бы флаг four
,
<flag name="eight" value="12" /> <!-- 12 == 8|4 -->
Наконец, если вы объявляете атрибуты в проекте библиотеки, но хотите применить их в макетах другого проекта (зависит от lib), вам нужно будет использовать префикс пространства имен, который необходимо связать в корневом элементе XML , Например.,
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto="http://schemas.android.com/apk/res-auto"
... >
<com.example.MyWidget
auto:myenum="two"
auto:myflags="one|two"
... />
</RelativeLayout>