Istnieje niewielka dokumentacja dotycząca declare-styleable
tagu, za pomocą której możemy zadeklarować niestandardowe style komponentów. Znalazłem listę prawidłowych wartości format
atrybutu attr
tagu. Chociaż jest to miłe, jeśli chodzi o to, nie wyjaśnia, jak używać niektórych z tych wartości. Przeglądając attr.xml (źródło Androida dla standardowych atrybutów), odkryłem, że możesz robić takie rzeczy, jak:
<!-- The most prominent text color. -->
<attr name="textColorPrimary" format="reference|color" />
format
Atrybut można oczywiście ustawić do kombinacji wartości. Przypuszczalnie format
atrybut pomaga parserowi zinterpretować rzeczywistą wartość stylu. Potem odkryłem to w attr.xml:
<!-- Default text typeface. -->
<attr name="typeface">
<enum name="normal" value="0" />
<enum name="sans" value="1" />
<enum name="serif" value="2" />
<enum name="monospace" value="3" />
</attr>
<!-- Default text typeface style. -->
<attr name="textStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
Oba wydają się deklarować zestaw dozwolonych wartości dla wskazanego stylu.
Mam więc dwa pytania:
- Jaka jest różnica między atrybutem stylu, który może przyjąć jeden z zestawu
enum
wartości, a takim, który może przyjąć zestawflag
wartości? - Czy ktoś zna lepszą dokumentację dotyczącą tego, jak
declare-styleable
działa (poza inżynierią wsteczną kodu źródłowego Androida)?
źródło
enum
aflag
.Odpowiedź @Aleadam jest bardzo pomocna, ale imho pomija jedną zasadniczą różnicę między
enum
iflag
. Pierwsza z nich ma na celu wybranie jednej i tylko jednej wartości, gdy przypisujemy odpowiedni atrybut do jakiegoś widoku. Te ostatnie wartości można jednak łączyć za pomocą bitowego operatora OR.Przykład w
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>
W
res/layout/mylayout.xml
możemy teraz zrobić<com.example.MyWidget myenum="two" myflags="one|two" ... />
Zatem wyliczenie wybiera jedną z możliwych wartości, podczas gdy flagi można łączyć. Wartości liczbowe powinny odzwierciedlać tę różnicę, zazwyczaj będziesz chciał, aby sekwencja przeszła
0,1,2,3,...
dla wyliczeń (na przykład do użycia jako indeksy tablic) i flagi, aby1,2,4,8,...
mogły być niezależnie dodawane lub usuwane, używając bitowego LUB|
do łączenia flag.Moglibyśmy wyraźnie zdefiniować „meta flagi” z wartościami, które nie są potęgą 2, i w ten sposób wprowadzić rodzaj skrótu dla typowych kombinacji. Na przykład, gdybyśmy zawarli to w naszej
myflags
deklaracji<flag name="three" value="3" />
wtedy moglibyśmy
myflags="three"
zamiast tego napisaćmyflags="one|two"
, dla zupełnie identycznych wyników jak3 == 1|2
.Osobiście lubię zawsze dołączać
<flag name="none" value="0" /> <!-- or "normal, "regular", and so on --> <flag name="all" value="15" /> <!-- 15 == 1|2|4|8 -->
co pozwoli mi usunąć lub ustawić wszystkie flagi jednocześnie.
Bardziej subtelnie może się zdarzyć, że jedna flaga jest implikowana przez inną. Zatem w naszym przykładzie załóżmy,
eight
że ustawiana flaga powinna wymuszać ustawieniefour
flagi (jeśli jeszcze nie było). Moglibyśmy wtedy ponownie zdefiniować,eight
aby wstępnie uwzględnićfour
flagę,<flag name="eight" value="12" /> <!-- 12 == 8|4 -->
Wreszcie, jeśli deklarujesz atrybuty w projekcie biblioteki, ale chcesz zastosować je w układach innego projektu (zależnego od biblioteki), musisz użyć przedrostka przestrzeni nazw, który musisz powiązać w głównym elemencie XML. Na przykład,
<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>
źródło