declare-styleable
컴포넌트에 대한 사용자 정의 스타일을 선언 할 수 있는 태그에 대한 귀중한 문서가 거의 없습니다 . 태그 의 속성에 대해 유효한 값 목록 을 찾았습니다 . 그것이 진행되는 한 좋지만 이러한 값 중 일부를 사용하는 방법을 설명하지 않습니다. attr.xml (표준 속성에 대한 Android 소스)을 찾아 보면서 다음과 같은 작업을 수행 할 수 있음을 발견했습니다.format
attr
<!-- The most prominent text color. -->
<attr name="textColorPrimary" format="reference|color" />
format
속성 분명히 값의 조합으로 설정할 수있다. 아마도 format
속성은 파서가 실제 스타일 값을 해석하는 데 도움이 될 것입니다. 그런 다음 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>
이 두 가지 모두 표시된 스타일에 허용되는 값 집합을 선언하는 것 같습니다.
그래서 두 가지 질문이 있습니다.
enum
값 세트 중 하나를 취할 수있는 스타일 속성과 값 세트를 취할 수있는 스타일 속성의 차이점은 무엇입니까flag
?- 누구든지
declare-styleable
작동 방식 에 대한 더 나은 문서를 알고 있습니까 (Android 소스 코드를 리버스 엔지니어링하는 것 제외)?
답변
여기에이 질문이 있습니다. 약간의 정보로 사용자 지정 속성 을 정의 하지만 많지는 않습니다.
그리고이 포스트 . 플래그 및 열거 형에 대한 좋은 정보가 있습니다.
사용자 지정 XML 속성 플래그
플래그는 아주 작은 값의 하위 집합, 즉 속성 태그 아래에 정의 된 값만 허용된다는 점에서 특수 속성 유형입니다. 플래그는 “이름”속성과 “값”속성으로 지정됩니다. 이름은 해당 속성 유형 내에서 고유해야하지만 값은 그럴 필요가 없습니다. 이것이 Android 플랫폼이 진화하는 동안 “fill_parent”와 “match_parent”가 모두 동일한 동작에 매핑되는 이유입니다. 그들의 가치는 동일했습니다.
name 속성은 레이아웃 XML 내의 값 위치에 사용되는 이름에 매핑되며 네임 스페이스 접두사가 필요하지 않습니다. 따라서 위의 “tilingMode”에 대해 속성 값으로 “center”를 선택했습니다. 나는 “늘어난”또는 “반복”을 쉽게 선택할 수 있지만 다른 것은 없습니다. 실제 값으로 대체하는 것도 허용되지 않았습니다.
값 속성은 정수 여야합니다. 16 진수 또는 표준 숫자 표현의 선택은 귀하에게 달려 있습니다. 둘 다 사용되는 Android 코드 내 몇 군데가 있으며 Android 컴파일러는 둘 중 하나를 기꺼이 받아들입니다.
사용자 지정 XML 속성 열거 형
열거 형은 하나의 프로 비전이있는 플래그와 거의 동일한 방식으로 사용되며 정수와 교환하여 사용할 수 있습니다. 내부적으로 Enum과 Integer는 동일한 데이터 유형, 즉 Integer에 매핑됩니다. 정수와 함께 속성 정의에 나타날 때 Enum은 항상 나쁜 “매직 넘버”를 방지하는 역할을합니다. 이것이 차원, 정수 또는 명명 된 문자열 ‘fill_parent’가있는 ‘android : layout_width’를 가질 수있는 이유입니다.
이를 컨텍스트에 적용하기 위해 정수 또는 “scroll_to_top”문자열을 허용하는 “layout_scroll_height”라는 사용자 지정 속성을 생성한다고 가정 해 보겠습니다. 이렇게하려면 “integer”형식 속성을 추가하고 enum을 따릅니다.
<attr name="layout_scroll_height" format="integer"> <enum name="scroll_to_top" value="-1"/> </attr>
이러한 방식으로 Enum을 사용할 때 한 가지 규정은 사용자 정의보기를 사용하는 개발자가 의도적으로 “-1″값을 레이아웃 매개 변수에 배치 할 수 있다는 것입니다. 이렇게하면 “scroll_to_top”이라는 특수한 경우 논리가 트리거됩니다. 이러한 예상치 못한 (또는 예상되는) 동작은 Enum 값을 잘못 선택하면 라이브러리를 “레거시 코드”더미로 빠르게 이동할 수 있습니다.
내가보기에 속성에 실제로 추가 할 수있는 실제 값은 속성에서 얻을 수있는 것에 의해 제한됩니다. 더 많은 힌트는 여기 에서 AttributeSet
클래스 참조를 확인하십시오 .
다음을 얻을 수 있습니다.
- 부울 (
getAttributeBooleanValue
), - 수레 (
getAttributeFloatValue
), - 정수 (
getAttributeIntValue
), - int (
getAttributeUnsignedIntValue
), - 및 문자열 (
getAttributeValue
)
답변
@Aleadam의 답변은 매우 도움이되지만 imho는 enum
과 사이의 주요 차이점을 생략 flag
합니다. 전자는 하나를 선택하도록 의도되었으며 일부 뷰에 해당 속성을 할당 할 때 하나의 값만 선택합니다. 그러나 후자의 값은 비트 OR 연산자를 사용하여 결합 할 수 있습니다.
예, 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,...
하여 비트 OR |
을 사용하여 플래그를 결합 하여 독립적으로 추가하거나 제거 할 수 있도록해야 합니다.
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>