안드로이드 이미지 버튼 만들기. (Android ImageButton)

2016. 5. 17. 10:08


1. 이미지 버튼

안드로이드에서 제공하는 기본 Button 위젯은 그 자체만으로 깔끔한 디자인을 제공하지만, 그 형태의 단순함으로 인해 사용자들의 다양한 취향을 만족시키기엔 다소 부족한 것이 사실입니다.


이런 경우 개발자가 선택할 수 있는 방법은 Button 위에 png 또는 jpg 등으로 만들어진 이미지를 출력하여 Button을 좀 더 화려하게(?) 꾸미는 것입니다. 이런 경우를 위해 안드로이드에서는 ImageButton이라는 클래스를 제공하고 있습니다.

안드로이드 이미지 버튼

사용자 클릭 이벤트 처리 기능을 생각하면 ImageButton이 Button으로부터 상속받을 것 같지만, ImageButton의 부모는 ImageView입니다. 기본적으로 텍스트를 출력하는 Button 위젯이 TextView에서 상속받은 것처럼, 이미지를 출력하는 ImageButton은 ImageView로부터 상속받는다는 것을 기억하시기 바랍니다.


지금부터 ImageButton 위젯을 사용하여 이미지로 구성된 Button을 만드는 방법에 대해 알아보겠습니다.

2. ImageButton에 이미지 출력하기

ImageButton을 사용하여 이미지를 출력하는 Button을 만드는 방법은 아주 간단합니다. ImageButton을 Activity의 Layout 리소스 XML에 추가한 다음, ImageButton의 "src" 속성에 이미지(png 등) 리소스를 지정하기만 하면 됩니다.

2.1 이미지 리소스 추가.

ImageButton에 이미지를 출력하기 위해 가장 먼저 해야 할 일은 이미지 파일을 프로젝트에 추가하는 것입니다. png 또는 jpg로 만들어진 이미지 파일을 "/res/drawable" 디렉토리에 복사하기만 하면 됩니다.

[STEP-1] "/res/drawable" - 이미지 파일을 "/res/drawable"에 리소스로 추가.

안드로이드 drawable 추가

2.2 Layout 리소스 XML에 ImageButton 추가.

Layout 리소스 XML에 ImageButton을 정의하는 코드는 다음과 같이 작성합니다.
이 때 ImageButton의 "src" 속성에 위에서 추가한 이미지 리소스를 적어줍니다.

[STEP-2] "activity_main.xml" - Activity Layout 리소스 XML에 ImageButton 추가.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.recipes4dev.examples.imagebuttonexample1.MainActivity"
    tools:showIn="@layout/activity_main">

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton1"
        android:padding="0dp"
        android:src="@drawable/imgbtn"/>

</RelativeLayout>

위의 소스의 내용과 같이 ImageButton의 "src" 속성에, "imgbtn.png" 파일 이름의 확장자("png")를 제외한 이름인 "imgbtn"을 지정하였습니다.


또한 XML 소스 내용 중 "android:padding" 값을 "0dp"로 설정한 것에 주의하세요. ImageButton에 이미지를 출력하면, 기본 Button 배경(회색) 위에 이미지가 출력됩니다. 이는 ImageButton이 가지고 있는 기본적인 padding 값이 적용되기 때문입니다.
위 소스에서는 이미지가 ImageButton의 전체 영역에 표시되도록 만들기 위해 padding 값을 0으로 설정하였습니다.

2.3 실행 결과

위에서 작성한 내용을 실행하면 다음과 같이 화면이 출력됩니다.

안드로이드 이미지 버튼 예제 실행 화면

실행 결과가 잘 동작하는 것 처럼 보이지만 한가지 큰 문제점을 가지고 있습니다. 안드로이드 기본 Button의 동작을 보면 일반적인 상태에서 화면에 보이는 색상(default)과 눌려졌을 때 보이는 색상(pressed)이 다름을 알 수 있습니다.

그런데 예제에서 사용된 ImageButton은 기본(default) 상태와 눌려진(pressed) 상태 모두 동일한 이미지를 출력하기 때문에 눌려진 상태를 식별할 수 없죠.


즉, ImageButton에서 눌려진 상태의 식별을 위해서는 추가적인 작업이 필요합니다.

3. ImageButton 상태(눌려짐)에 따라 다른 이미지 출력하기.

ImageButton의 상태(normal, pressed, focused)에 따라 다른 이미지를 출력하려면, 각 상태를 나타내는 이미지 파일들을 리소스에 추가한 다음, 상태에 따라 표시될 이미지를 각각 지정해주면 됩니다. 이 때 상태 별 출력 이미지 지정은 Drawable 리소스 밑에 "selector"를 사용한 리소스 파일을 만들어서 사용합니다.

3.1 상태에 따른 이미지 파일 준비.

먼저 ImageButton의 상태에 따라 출력될 이미지 파일을 준비합니다. ImageButton의 상태는 일반(normal), 눌려짐(pressed), 포커스(focused)로 구분하므로 각 상태에 맞는 이미지 파일을 "/res/drawable"에 저장합니다.

[STEP-1] "/res/drawable" - 각 상태 이미지 파일을 "/res/drawable"에 추가.

안드로이드 이미지 버튼 상태


3.2 "selector"를 지정한 리소스 XML 추가.

상태에 따른 이미지 지정은 "selector" 태그를 사용하여 XML 파일에 저장합니다. XML 파일의 이름은 개발자가 결정하면 되고, 저장된 파일 이름은 다음 단계에서 ImageButton의 "src" 속성에 사용됩니다.


예제에서는 "imgbtn_states.xml"이라는 파일 이름으로 저장합니다. 위치는 이미지와 마찬가지로 "/res/drawable"에 추가합니다.

[STEP-2] "res/drawable/imgbtn_states.xml" - "selector"를 지정한 리소스 XML 추가.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/imgbtn_pressed"
          android:state_pressed="true" />
    <item android:drawable="@drawable/imgbtn_focused"
          android:state_focused="true" />
    <item android:drawable="@drawable/imgbtn_default" />
</selector>

"selector"를 사용할 때 주의해야 할 점은, item의 순서가 결과에 영향을 미친다는 것입니다. 첫 번째 item부터 비교를 시작하여 현재 Button의 상태와 일치하는 아이템이 있다면 그 뒤에 있는 item은 더 이상 비교하지 않습니다. 또한 가장 마지막에 있는, 상태 값이 사용되지 않은 item은 "default" 상태로 사용됩니다. 즉, "pressed"도 아니고 "focused"도 아닌 경우에 출력하는 기본 item이라는 거죠.


대부분의 경우에 Button에 대한 "selector"는 위의 예제 형식을 그대로 사용하되, "android:drawable"에 사용될 리소스 이름만 변경하시면 됩니다.


3.3 ImageButton의 "src" 속성에 drawable XML 지정.

마지막으로 위에서 작성한 drawable XML 파일(imgbutton_state.xml)을 ImageButton의 "src" 속성에 지정합니다. 이 때, "state_focused" 상태를 확인하기 위해 두 개의 ImageButton을 사용합니다.

[STEP-3] "activity_main.xml" - "src" 속성에 drawable XML 지정.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.recipes4dev.examples.imagebuttonexample1.MainActivity"
    tools:showIn="@layout/activity_main">

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton1"
        android:padding="0dp"
        android:layout_marginRight="20dp"
        android:focusableInTouchMode="true"
        android:src="@drawable/imgbtn_states"/>

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton2"
        android:padding="0dp"
        android:layout_toRightOf="@id/imageButton1"
        android:focusableInTouchMode="true"
        android:src="@drawable/imgbtn_states"/>
</RelativeLayout>

두 개의 ImageButton에 "focusableInTouchMode" 속성을 사용한 것을 확인하세요. 터치를 사용하는 안드로이드는 기본적으로 Button에 대한 focus 상태를 지원하지 않습니다. 만약 focus 상태를 지원하고자 한다면 위의 XML 내용처럼 "focusableInTouchMode" 속성을 "true"로 설정해줘야 합니다.

3.4 실행 결과

"selector"를 사용한 예제를 실행하면 ImageButton의 상태에 따라 다른 이미지가 출력됨을 확인할 수 있습니다.

안드로이드 이미지 버튼 상태 예제 실행 화면


각 버튼의 상태에 따라 출력되는 이미지는 다음과 같이 출력됩니다.


4. Button 위젯을 사용하여 이미지 출력하기.

위에서 기술한 ImageButton 사용법 설명이 무색하게도, ImageButton이 아닌 Button 위젯에 동일하게 이미지를 출력할 수 있습니다. 바로 Button의 "background" 속성을 사용하는 것입니다. 아래 예제는 ImageButton에서 사용한 리소스(이미지, xml)를 그대로 사용하여 Button의 background 속성에 적용한 것입니다.

Button의 background에 drawable XML 지정.
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button1"
        android:layout_marginRight="20dp"
        android:focusableInTouchMode="true"
        android:minWidth="0dp"
        android:minHeight="0dp"
        android:background="@drawable/imgbtn_states"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:layout_toRightOf="@id/button1"
        android:focusableInTouchMode="true"
        android:minWidth="0dp"
        android:minHeight="0dp"
        android:background="@drawable/imgbtn_states"/>

출력 결과는 ImageButton을 사용한 것과 똑같습니다. (이미지 출력 시 Button에 stretch되어 나타나는 것을 방지하기 위해 "minWidth" 속성과 "minHeight" 속성 값을 0으로 설정하였습니다.)

5. 참고

.END.


ANDROID 프로그래밍/BUTTON