Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

개발 마스터 김규규

Background resource의 동적 color 변경 본문

Project/LivingTogether

Background resource의 동적 color 변경

덜 큰 개발자 2020. 6. 15. 13:54


(문제가 된 부분)

디바이스가 사용가능한지에 대한 유무를 보여주는 state circle을 구현할 때 약간 버벅였다.


circle의 형태이기 때문에 xml에서 background 속성을 이용하여 shape나 vector resource를 지정해주어야했다.


그러나 디바이스의 상태에 따라 동적으로 녹색, 회색으로 state circle의 색을 변경시켜야하는데 이 또한 background 속성을 사용하여야 했다.

<View
    android:id="@+id/view_state_circle"
    android:layout_width="10dp"
    android:layout_height="10dp"
    android:background="@drawable/circle_background"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

state circle 을 위와 같이 정의해주었다.

viewStateCircle.setBackgroundResource(
    when (data.isAvailable) {
        true -> R.color.stateGrean
        else -> R.color.gray
    }
)

그런데 이렇게 setBackgroundResource()를 사용하여 컬러를 변경시키면 당연히 기존의 @drawable/circle_background는 날아간다.


view 객체에 대한 다른 메서드가 없을까 하고 둘러보니 setBackgroundColor() 라는 메서드를 발견하였다.


Background resource랑 background color는 다르지 않을까?

public void setBackgroundColor(@ColorInt int color) {
    if (mBackground instanceof ColorDrawable) {
        ((ColorDrawable) mBackground.mutate()).setColor(color);
        computeOpaqueFlags();
        mBackgroundResource = 0;
    } else {
    setBackground(new ColorDrawable(color));
    }
}

그러나 메서드를 뜯어본 결과 ColorDrawable객체를 생성하여 똑같이 setBackground() 를 호출하고 있었다..


도대체 어떻게 background와 color를 동시에 지정해줄 수 있을까?


메서드를 또 둘러보니 xml에서 backgroundTint 라는 속성을 발견했다.





공식 문서에는 그저 View에 Tint를 적용해주는 속성이라고만 설명이 되어있다.



(그래서 Tint가 뭔데요..!)


그리고 backgroundTintMode에 대한 설명도 바로 아래에 있었다.


위 설명을 보니 Tint가 어떠한 filter 역할을 하는 것 같아보인다.


그렇다면 background resource의 컬러를 흰색으로 두고 background tint를 동적으로 변경하여 background resource의 컬러에 필터를 씌어주는 방법을 사용하면 되지 않을까?


그러나 위 사진에서 보다시피 setBackgroundTint() 메서드는 ColorStateList 타입을 파라미터로 받는다.


ColorStateList.valueOf(int color)메서드를 활용하면 될 것 같은데 Color resource에 있는 색상 값을 어떻게 ColorInt로 넘겨줄 수 있을까?


이럴 때는 ContextCompat.getColor()메서드를 사용하면 된다.

최종적으로

viewStateCircleItem.backgroundTintList = when (data.isAvailable) {
    true -> ColorStateList.valueOf(ContextCompat.getColor(this.root.context, R.color.stateGrean))
    else -> ColorStateList.valueOf(ContextCompat.getColor(this.root.context, R.color.gray))
}

이렇게 코드를 작성하였고 원하는 결과대로 state circle이 표시됨을 확인할 수 있었다.