오늘도 더 나은 코드를 작성하였습니까?

Android Styling: prefer theme attributes (번역 및 학습) 본문

Android Material Design

Android Styling: prefer theme attributes (번역 및 학습)

hik14 2022. 10. 27. 15:49

우리는 테마와 스타일의 차이점을 살펴보았습니다.

테마와 공통으로 사용할  속성을 고려하여  자주 변경될 수 있는것 을 제외하는 것이 좋은 이유를 살펴보았습니다.

 

더 적은 수의 레이아웃이나 스타일을 생성하여 테마 내에서 변경 사항을 격리할 수 있습니다.

 

실제로는 테마별로 색상을 다양하게 만들고 싶기 때문에 항상* 테마 속성을 통해 색상을 참조해야 합니다.

 

즉, 아래와 같은 코드는 옳바르지 못합니다.

<View …
  android:background="@color/white"/>

 

대신에 테마 속성을 참조해야 합니다.

예를 들어 어두운 테마에서 다른 값을 제공하는 것과 같이 테마별로 색상을 변경할 수 있습니다

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="?attr/colorSurface"/>

현재 대체 테마를 지원하지 않더라도(어두운 테마는 없나요?), 이 접근 방식을 따르면 테마를 훨씬 쉽게 채택할 수 있습니다.

Qualified Colors?

여러 configuration을 사용할 수 있게 대체 값을 제공하여 색상을 변경할 수 있습니다(예: res/values/colors.xml에 정의된 @color/foo 및 res/values-night/colors.xml에 설정된 대체 값). 대신 테마 속성을 사용하는 것이 좋습니다.

 

Color Layer를  다양하게 하기위해서 색상에  semantic names을 부여해야 합니다.

 

색상을 @color/white로 지정하지 않아야 된다.

night configuration에서 어두운 변형을 제공할 가능성이 높으므로 이는 매우 혼란스러울 것입니다.

 

대신 @color/background와 같은 a semantic name 을 사용해야 됩니다.

 

 @color/white 문제는 색상 선언과 값 제공을 결합한다는 것입니다.

따라서 이것이 주제에 따라 다를 수 있거나 달라질 것이라는 암시는 없습니다.

 

@colors를 변경하면 더 많은 색상을 만들 수 있습니다.

여러 상황에 있어서 동일한 값(즉, 배경은 아니지만 동일한 색상이어야 함)을 사용하여 a semantic name 새로운 색상을 요구하는 경우에도 색상 파일에 새 항목을 생성해야 합니다.

 

theme 속성을 사용하여 semantic 색상 선언을 값을 제공하는 것과 분리하고, call-site 에서 색상이 테마(?attr/ 구문을 사용하기 때문에)에 따라 다르다는 것을 더 명확하게 만듭니다.

 

색상 선언할 때,  색상의 이름이 지정된 값으로 하여 앱에서 사용하는 색상 팔레트를 정의한다.

테마 수준에서 색상 파일을 다양하게 해서 색상 파일을 작고 유지 관리하기 쉽게 유지할 수 있습니다.

 

앱에서 사용하는 색상 팔레트를 정의하고 테마 수준에서 변경

 

이 접근 방식의 추가 이점은 이러한 색상을 참조하는 레이아웃/스타일이 더 재사용 가능하다는 것입니다.

테마는 중첩되는 부분도 있고 다를 수 있기 때문에 간접 지정하게 되면,  일부 색상을 변경하기 위해 대체 레이아웃이나 스타일을 만들 필요가 없습니다.

동일한 레이아웃을 다른 테마로 사용할 수 있습니다.

 

언제나?

테마별로 색상을 변경하고 싶지 않은 경우가 있을 수 있기 때문에 "항상* 테마 속성을 통해 색상 참조"에 별표를 표시했습니다.

예를 들어, 머티리얼 디자인 지침은 밝은 테마와 어두운 테마 모두에서 동일한 브랜드 색상을 사용하려는 경우입니다.

 

이러한 드문 경우에 색상 리소스를 직접 참조하는 것이 완벽하게 유효합니다.
<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<FloatingActionButton …
  app:backgroundTint="@color/owl_pink_500"/>

State of the art

레이아웃/스타일에서 테마 속성을 직접 참조할 수 없는 또 다른 상황은 ColorStateLists를 사용할 때입니다.

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="@color/primary_20"/>

 

primary_20이 색상 값에 대한 테마 속성을 참조하는 ColorStateList인 경우 유효할 수 있습니다.

 

일반적으로 다양한 상태(눌림, 비활성화 등)에서 다양한 색상을 제공하는 데 사용됩니다

ColorStateList에는 테마 지정에 유용할 수 있는 또 다른 기능이 있습니다.

 

색상에 적용할 알파 값을 지정할 수 있습니다.

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<selector …
  <item android:alpha="0.20" android:color="?attr/colorPrimary" />
</selector>

단일 색상 ColorStateList(즉, 상태당 다른 색상이 아닌 단일 기본 색상만 제공)는 유지해야 하는 색상 리소스의 수를 줄이는 데 도움이 됩니다

 

colorPrimary에 알파 값을 수동으로 설정하는 새로운 색상 리소스를 생성하는 대신(configuration 마다) 현재 테마에 있는 colorPrimary를 변경합니다.  colorPrimary이 변경되면 조정된 모든 인스턴스를 찾아서 변경하지 않고 한 곳에서만 업데이트하면 됩니다.

 

유용하지만, 알아야 할 몇 가지 주의 사항이 있습니다.

 

1. 지정된 색상에도 알파 값이 있으면 알파가 결합됩니다.

 

즉, Alpha 50%가 이미 적용된 색상이에 50% Alpha를 적용하면 25% Alpha가 적용됩니다.

테마 색상을 완전히 불투명하게 지정하고 ColorStateLists를 사용하여 알파를 수정하는 것이 좋습니다

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<selector …
  <item android:alpha="0.50" android:color="#80ffffff" />
</selector>

2. Alpha 구성 요소는 API 23에만 추가 되었습니다.

 

최소 SDK가 이보다 낮으면 이 동작을 백포트하는 AppCompatResources.getColorStateList를 사용해야 합니다(그리고 항상 android:alpha 네임스페이스를 사용하고 app:alpha 네임스페이스는 사용하지 않음)

 

3. 종종 shorthand를 사용하여 Color -> Drawable로 설정합니다.

 

View의 background는 드로어블이며, 이 shorthand는 주어진 색상을 ColorDrawable로 강제 변환 해준다.

 

ColorStateList를 Drawable로 변환할 방법이 없습니다(ColorStateListDrawable이 도입된 API 29 이전)

그러나 아래와 같은 방법으로 위 문제를 해결할 수 있습니다.

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="@drawable/a_solid_white_rectangle_shape_drawable"
  app:backgroundTint="@color/some_color_state_list"/>

Background Tint가 View에 필요한 상태를 지원하는지 확인하십시오. 비활성화되었을 때 변경해야 하는 경우.

 

Enforcement

 테마 속성과 ColorStateList를 사용해야 한다고 확신하지만 이를 코드베이스나 팀 전체에 적용하려면 어떻게 해야 할까요?

코드 리뷰 중에 항상 확인하고 시도할 수 있지만 이는 잘 되지 않습니다.

 

더 나은 접근 방식은 이를 포착하기 위해 도구에 의존하는 것입니다.

아래 링크를 따라 리터럴 색상 사용을 찾기 위해 Lint 검사를 추가하는 방법을 설명하고 모든 조언을 포함하도록 확장될 수 있습니다.

https://proandroiddev.com/making-android-lint-theme-aware-6285737b13bc

 

Making Android Lint Theme Aware

Use Android Lint API to identify screens and drawable not ready for dark theme. Also, use it to maintain dark theme apps.

proandroiddev.com

Be Indirect

테마 속성과 ColorStateList를 사용하여 테마에 색상을 적용하면 레이아웃과 스타일이 더 유연해져서 재사용을 촉진하고 코드베이스를 간결하고 유지 관리하기 쉽게 유지할 수 있습니다.