layered

9. 드로어블(Drawable) 본문

안드로이드/안드로이드 앱 프로그래밍

9. 드로어블(Drawable)

스윗푸들 2023. 4. 13. 18:05

메모는 개인적으로 느낀 부분을 아무렇게나 적은 것이어서 오류가 있을 수 있다!

개념


보통 뷰에 이미지를 넣을 때에는 background라는 속성을 사용하게 된다.

하지만 만약 좋아요를 눌렀을 때 하트가 칠해지는 것처럼, 어떤 이벤트가 발생할 때 이미지에 변화를 주고 싶다면 어떻게 해야 할까?

이때 드로어블을 사용하게 된다.

 

드로어블은 뷰에 설정할 수 있는 객체로, 그 위에 그래픽을 그릴 수 있다.

상태에 따라 그래픽이나 이미지가 선택적으로 보이게 할 수도 있다.

따라서 이미지 같은 것을 그냥 바로 /res/drawble에 넣는 게 아니라 xml로 만들어서 넣게 된다.

 

A Drawable is a general abstraction for "something that can be drawn."

 

안드로이드 드로어블 문서의 첫줄인데, 추상적이지만 확실한 정의인 것 같다.

그릴 수 있는 것에 대한 일반적인 추상화.

 

 

상속 관계

 

뷰를 상속하는 것은 아니기 때문에 뷰처럼 이벤트를 처리하거나 사용자와 상호작용 할 수는 없다.

 

 

메모

낯선 개념이라 조금 추상적이지만 이미지를 객체화해서 사용하자는 것 같다. 단순히 이미지 리소스로 사용하는 것과 객체로 다루는 것은 다르기 때문이다.

음... 자바에서 객체란 상태와 동작을 가지고 있으니까, 정지된 리소스가 아니라 동적인 객체로 더 다채롭게 사용하자는 느낌.

 

이건 개인적이지만 뷰에서 이미지를 지정하는 background는 그냥 속성 중 하나일 뿐이어서 이미지보다는 그 뷰 자체에 집중하게 되는데, 객체로 만들면 그 이미지만의 고유한 객체가 되는 것이니까 드로어블이라는 게 있는 것 같다.

 

스폰지밥 이미지가 들어간 "버튼"

스폰지밥 이미지 객체

 

이런 느낌(?)

 

상태 드로어블(StateListDrawable)


뷰의 상태에 따라 보여줄 그래픽을 다르게 지정할 수 있다.

drawable 폴더에서 우클릭을 하면 드로어블 리소스 파일을 생성할 수 있다!

 

 

이렇게 xml 파일을 만들게 되면 <selector> 태그로 둘러싸인 코드 부분을 볼 수 있다.

 

 

넣고자 하는 이미지를 <item> 태그로 감싸서 지정하면 된다.

상태는 state_ 속성으로 설정하는데, 지금은 버튼에 넣을 드로어블을 만들 것이므로 state_pressed를 선택한다.

 

코드를 다 작성하고 나면 버튼의 background 속성에 드로어블 파일을 넣어 주면 된다.

 

버튼이 눌리게 되면 하트가 채워진다!

 

태그는 <item> 하나뿐인데 그 안에 상태에 관련된 속성들이 많다. state_pressed라든가 state_checked 같은 것들! 

속성들의 이름이 대부분 직관적이어서 딱히 정리하지 않아도 될 것 같다.

 

 

메모

처음에는 드로어블의 상태와 버튼이 별개인 줄 알았는데, 버튼을 텍스트뷰로 바꿔 보니 하트가 안 채워졌다.

우리가 버튼을 누르면 내부적으로는 pressed 상태가 되고 드로어블에서는 그 상태를 참조하는 형태로 작동하는 것 같다!

 

background를 설정할 때 @drawable 키워드를 이용하는 걸 보면 객체화된 이미지도 결국 하나의 리소스로 취급이 되는 것 같다.

 

드로어블 파일 내의 여러 요소들은 더 알아봐야겠다!

 

쉐이프 드로어블(ShapeDrawable)


xml로 도형을 그릴 수 있는 드로어블이다.

상태 드로어블에서의 <selector> 태그를 <shape>으로 바꾸면 된다!

 

 

태그들이 많아서 가볍게 정리했다!

 

태그 설명 속성
<shape> 도형 태그
android:shape
<size> 도형 크기 지정
android:width
android:height
<stroke> 테두리 선 속성 지정
android:width
android:color
android:dashGap="점선 간격"
android:dashWidth="점선 길이"
<solid> 도형 채우기
android:color
<padding> 테두리 안쪽 공간 설정
android:top
android:bottom
android:left
android:right
<gradient> 그라데이션  
<corners> 테두리 둥글게
android:radius

 

<layer_list> 태그를 사용하면 여러 개의 그래픽을 사용할 수 있어서, 더 다채롭게 만들 수 있다.

 

 

이렇게 된다! 실제로 버튼 커스텀도 이런 식으로 하는지는 모르겠다.

 

 

메모

쉐이프 드로어블에서 크기를 지정하지 않으면 뷰의 크기에 따라서 유동적으로 조절이 되는 것 같다. 크기를 지정했을 때에는 뷰에 따라 테두리 같은 게 잘리거나 조금 이상하게 나왔기 때문이다.

 

아까 드로어블도 결국 리소스로 취급이 된다고 했었는데, 그러면 상태 드로어블 파일에서 쉐이프 드로어블을 가져다 쓸 수 있지 않을까? 하는 생각으로 해봤는데 된다!

 

저 그라데이션 버튼은 밑의 상태 드로어블을 이용해 누르면 색이 나타나는 형태로 구현했다(사진은 누른 상태이다).

 

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_pressed="true"
        android:drawable="@drawable/gradient_button"/>
</selector>

 

https://developer.android.com/reference/android/graphics/drawable/Drawable

 

Drawable  |  Android Developers

 

developer.android.com