Drawble Selector를 이용한 Button 만들기

왜 기본 Button이 있는데, Selector?

우리가 일반적으로 사용하는 Button은 다양한 제약을 받으며, 이를 피하기 위해 Custom해서 사용해야 한다. 버튼 또는 이미지가 터치 됐을 때, 터치됐다는 느낌을 주고싶다면, 혹은 한 버튼의 현재 상태에 따른, 예를 들면 포커스 됐을 때, 체크 됐을 때, 선택 되었을 때 등 여러 상태에 따라 커스텀하고 싶을 때 Drawble Selector를 이용해서 만들면 편리하다.

Drawble Selector

먼저 Drawble Selector를 이용해 이미지로 버튼을 클릭했을 때, 클릭하지 않았을 때의 이미지를 다르게 만들어보겠다.

  1. res/drawable 폴더에 클릭 됐을 때, 클릭이 안됐을 때(true와 false일 때) 이미지를 넣어준다.
  2. drawable 폴더에 우클릭 후 New / Drawable Resorce File을 선택해 Root element를 Selector로 지정한 후 버튼이 클릭됐을 때 할 행동을 Seletor XML을 만들어준다.

  3. 예제에서는 클릭됐을 때, 클릭되지 않았을 때 두 가지 예시로만 만들었다.
<?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/press"/>
    <item android:state_pressed="false"
    	  android:drawable="@drawable/not_pressed"/>
</selector>
  1. 사용할 버튼의 background에 적용해준다.
<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/clicked"
        android:text="버튼 클릭" />

이런 식으로 적용해 주면 ?

안된다

왜 안될까? 특정 버전의 안드로이드 스튜디오는 프로젝트 생성시에
1. Theme.MaterialComponents.DayNights.DarkActionBar를 디폴트 테마로 설정한다.
2. 해당 테마에서 Button 생성시 MaterialButton을 생성한다.
3. MaterialButton의 background는 자체적인 background를 가지고 있어, android:background 속성의 설정 값을 무시한다!

이를 수정하기 위해서 2가지 방법이 있다.

  1. 일반 Button 대신 androidx.appcompat.widget.AppCompatButton 을 사용한다.
<androidx.appcompat.widget.AppCompatButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/clicked"
        android:text="버튼 클릭" />
  1. res/values/themes/themes.xml 에서 상단의 parent="Theme.MaterialComponents.DayNight.DarkActionBar" 부분을
    parent="Theme.AppCompat.DayNight.DarkActionBar"로 바꾸어 준다.

이렇게 둘중 하나를 적용해주면 아래와 같이 버튼을 클릭했을 때와 클릭하지 않았을 때 다른 이미지를 볼 수 있다.

ImageView 또는 TextView에서의 Selector

그렇다면 ImageView 또는 TextView에서도 똑같이 가능할까? ImageView나 TextView에서는 다르게 적용해준다. 상단에 RelaytiveLayout으로 TextView 또는 ImageView를 감싸준 뒤 clickable="true"로 설정해준다. 그리고 background 속성에 동일하게 drawable을 설정해준다.
이런식으로 설정하지 않고 TextView에 clickable 속성을 줄 경우 Text를 정확하게 클릭하지 않으면 이미지가 바뀌지 않기 때문이다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/clicked"
        android:clickable="true">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    </RelativeLayout>

    <androidx.appcompat.widget.AppCompatButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/clicked" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/clicked"
        android:clickable="true">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/clicked" />
    </RelativeLayout>

</LinearLayout>

6가지 상태

버튼이 클릭 됐을 때 이외에도 다양한 옵션을 줄 수 있다.

android:state_enable : 사용 가능 상태
android:state_selected : 선택 상태
android:state_pressed : 클릭 상태 (눌려있는 경우)
android:state_focused : 포커스 상태
android:state_checked : 체크된 상태
android:state_checkable : 체크할 수 있는지

다양한 옵션 모두 실행해보길 바란다.

Selector가 enabled, selected 등 여러 속성에 따른 이미지가 다른 경우(속성이 겹칠 경우) 맨 마지막 속성의 이미지가 표시된다.

정리

1. Drawable Selector를 이용할 땐 true와 false 모두 설정해주기(false 값이 기본 값이다.)

2. 기존의 Button은 Default값 때문에 바뀌지 않으니 Appcompat의 Button 사용하기( 또는 theme에서 설정 값 바꿔주기)

3. ImageView 또는 TextView에서 Selector를 이용할 땐 뷰 그룹안에 넣은 뒤 Clickable을 True로 해준 뒤 사용하기

출처

https://curryyou.tistory.com/398

좋은 웹페이지 즐겨찾기