마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

NoActionBar 설정후 Toolbar를 지정해줬을때 색상 질문.

0 추천

기존의 액션바(툴바)를 없애고 새로운 툴바를 정의하기 위해 Theme의 DarkActionBar -> NoActionBar로 설정해줬습니다. 

이후에 xml에 CoordinatorLayout, AppbarLayout, Toolbar를 차례로 정의해줬습니다.

이 툴바에는 xml에서든 소스코드에서든 어디서든 Theme은 따로 지정해주지 않았습니다.

그런데 궁금한것이 생겨 기본 Theme의 colorPrimary의 색상을 다른 색상으로 변경해보니 

xml에 새로 정의한 툴바의 색상도 변경되었습니다.

위에서도 말했지만 어디서든 Theme은 지정해주지 않았습니다. 

그런데 왜 색상이 변경되는 것인가요? 왜 전혀 관련없는 Theme 스타일의 영향을 받은건가요?

 

코드입니다

Themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.WriteWeight" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>


</resources>

 

 

activity_main.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent">
        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            app:elevation="0dp">
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:titleMarginStart="30dp" />
        </com.google.android.material.appbar.AppBarLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

 

codeslave (3,940 포인트) 님이 2020년 12월 24일 질문

1개의 답변

0 추천
그건 theme에 정의된 칼러를 theme 시스템이 사용하기 때문입니다. colorPrimary나 colorPrimaryDark, colorSecondary, colorSecondaryDark처럼 님이 사용하는 theme에 에 정의된 색상들은 theme에서 가져다 씁니다.  

개발자 문서에도 관련 정보들이 많습니다.

https://developer.android.com/guide/topics/ui/look-and-feel/themes

Material theme을 사용하신다면,

https://material.io/components?platform=android

 

안드로이드 theme 이 쉽지 않은 부분인 것 같습니다. Material design으로 넘어오면서 배워야될 게 많아졌더라구요.
spark (227,530 포인트) 님이 2020년 12월 24일 답변
theme에서 가져다 쓰신다고하셨는데 본문코드에서 Theme.WtiteWeight 말고 따로 Theme라고 있나요? colorPrimary를  컨트롤 B 해서 따라들어가니
?attr 이라는곳에 정의되어있는것같은데 이것인가요
Theme.MaterialComponents.DayNight.NoActionBar
이렇게 안드로이드 theme이 정의되어 있다면, 클래스 구조처럼
Theme.MaterialComponents 는 Theme을 상속받고 Theme.MaterialComponents.DayNight 는 Theme.MaterialComponents를 상속받는 형태로 되어 있습니다. 각각의 theme 에서 정의해서 사용하는 속성들은 님의 확인하신 것처럼 정의되어 있습니다. 따라서 해당 theme에 정의된 속성을 오버라이드하실 수 있습니다.
마찬가지로 님이 theme을 정의할 때 AppTheme을 정의한 다음 AppTheme.Fancy라고 정의한 다면 AppTheme.Fancy는 AppTheme을 상속받습니다
아..style도 상속과 오버라이드의 형태로 진행되는군요..
<style name="" parent=""> 에서 name은 제가 새로 정의할 style의 이름이고
parent는 어떤걸 상속받는지에대한 부모이름이네요?
그리고 클래스와 마찬가지로 제가 정의하는 style은 상속받는 parent의 속성도 그대로 물려받으며, 또 새로운 속성(item)을 추가로 정의할수도 있고 기존의 속성을 오버라이드해서 속성값을 새로 정할수도 있고 이런식인거네요?
그런데 name의 Theme.WriteWeight은 Theme을 상속했다는 것인가요..아니면 그냥 Theme인 WriteWeight를 정의한다는 것을 알아보기 쉽게 네이밍한건가요?
왜 이걸 묻냐면 Theme.WriteWeight 의 경우 parent로 이미 NoActionBar를 상속받기 때문에 name="Theme.WriteWeight" 이게 상속이라면 이중상속같은것인가..해서 질문드렸습니다..또한 선생님이 올려주신 링크에도 parent없이 name="Theme.WriteWeight" 이런식으로하면 parent대신 상속한다고 되어있어서요..

+ 그런데 본문 xml소스를 보시면 Toolbar에는 따로 theme를 적용하지 않았는데,
Theme.xml의 Theme.WriteWeight 스타일의 colorPrimary의 색상을 변경하면 툴바의 색상도 변경되는데 이건 왜이런건가요? 답변을 해주신것같은데 이해가 잘가질 않습니다.. 제가 툴바에 직접 정의한 theme이나 정의 되어있는Theme.WriteWeight을 적용해줬다면 모르겠는데.. 적용하지도 않았는데
Theme.WriteWeight의 색상을 변경하면 같이 변경되니 왜그런지 잘모르겠습니다... 매니페스트에 적영되어있는 어플리케이션 테마가 Theme.WriteWeight 이것이긴한데.. 이거의 영향인가요..? xml에서 툴바를 추가하면 Theme.WriteWeight의 영향을 받도록 뭐 어떻게 설정되어있는건가요..
스타일은 두가지 방식으로 상속이 가능한데요.
<style name ="MyTheme" parent = "Theme.Material">
<style name ="MyAwesomeTheme" parent ="MyTheme">
parent tag를 사용해서 할 수도 있구요. MyAwesomeTheme은 MyTheme을 상속 받습니다.


<style name= "MyTheme.Awesome">
name tag를 통해서도 할 수 있습니다. MyTheme.Awesome도  MyAwesomeTheme과 같이 MyTheme을 상속받습니다.

<style name= "MyTheme.Awesome" parent="DifferentTheme">
이렇게 하면 어떻게 되냐면, name에 있는 상속규칙에 우선 순위가 있어서 MyTheme만 적용되고 DifferentTheme은 적용되지 않습니다. 따라서 상속시에는 name tag만 사용하던가 parent tag만 사용하던가 하는 게 좋습니다.
님의 앱 기본 theme이 Theme.WriteWeight 이잖아요. 별도로 스타일을 지정하기 전까지는 이 앱 전체에 이 theme이 기본적으로 적용됩니다. 이  theme은 기본 색상으로 Theme.WriteWeight 밑에 정의된  속성들을 사용합니다. 툴바같은 경우는 colorPrimary를 사용하구요. 따라서 activity_main.xml 에 있는 툴바에 별도의 스타일을 지정해주지 않는한, app theme인 Theme.WriteWeight에 정의된 색상을 가져다 쓰는 겁니다. Theme.MaterialComponents를 찾아보시면 툴바같은 앱에서 사용되는 컴포넌트들의 스타일을 지정해 주고 있고, 이 theme을 상속받을 경우 님이 따로 정의하지 않아도 기본적으로 여기에 정의된 기본 스타일을 사용하는 겁니다. 그리고 Theme.MaterialComponents에 정의된 개별 컴포넌트의 스타일에서 colorPrimary나 colorSecondary 같은 theme에 정의된 색상을 재사용하는 겁니다. 마치 글로벌 변수를 지정하고 이걸 여러 클래스에서 공유하는 것 같이 말이죠.

Material app bar의 상세 styling에 대해서는 material design 사이트를 참조하세요.
https://material.io/components/app-bars-top/android#using-top-app-bars

그리고 youtube에 올라온 MAD skills를 꼭 체크해 보세요.
https://www.youtube.com/results?search_query=mad+skills+material+design

제 설명보다는 훨씬 더 나을 것 같네요.
감사합니다 이해가 어느 정도됐네요.
그런데
본문 코드에서
<style name="Theme.WriteWeight" parent="Theme.MaterialComponents.DayNight.NoActionBar">은 요즘 액티비티를 생성하면 theme이 기본적으로 이렇게 정의되던데, 왜 name과 parent를 같이 쓰나요?
그리고 name이 우선순위이고 둘다 같이쓰는경우 name만 적용된다면
뒤의 NoActionBar는 왜 적용되는것인가요?
닝의 theme에는 Theme이라고 정의된 게 없기 때문에 Theme.WriteWeight는 parent에 정의된 theme을 상속받겠죠. theme의 이름을 저렇게 한 이유는 naming convention(명명규칙)과 관련이 있는 것으로 보여요. 사실 Theme.WriteWeight 은 이름으로만 보면 애매한 이름이긴 합니다. 왜냐하면 Theme은 안드로이드 시스템에 있는 theme인데,
Theme은 정의되어 있지 않고, parent에도 안드로이드 theme이 있으니, Theme 먼저 정의하고 이것을 상속받으려고 한 것인데 이 부분을 실수로 빼먹은 것인지, 그냥 안드로이 Material Theme을 상속받으려고 한 것인데, 이름을 명확하지 주지 않은 것인지 해당 개발자한테 물어보기 전에는 알 수가 없습니다.

그냥 AppTheme이나 WriteWeightTheme이란 이름을 사용하는 것이 더 명확해 보여요.
또는 AppTheme을 하나 만들고 나서 상속을 받는게 명확해 보이네요.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar" >...</style>
<style name="AppTheme. WriteWeight"> ...</style>
결론적으로, name의 상속규칙과 parent tag를 같이 쓰는 것은 권장되지 않는 방법입니다.
...