[안드로이드] 이미지 버튼의 이미지 크기 조절

안녕하세요. 개발자 드리머즈입니다.


안드로이드에서 이미지버튼(ImageButton)을 사용 중 정리가 필요해 글 남깁니다.

처음에는 고정된 이미지 버튼의 크기에 맞게 이미지의 크기가 조절될 거라고 생각했는데 아닌 것 같습니다. 이미지 버튼의 크기가 layout xml파일에서 android:layout_width="50dp"와 같은 방식으로 크기가 고정된 상태에서 이미지 버튼의 크기보다 이미지가 작으면 버튼 내부에 여백이 생기며 이미지 버튼의 크기보다 이미지가 크면 이미지가 짤립니다.


제가 겪은 상황은 이미지버튼의 이미지가 크기가 버튼보다 크다는 것을 발견했고 이 문제를 xml코드에서 간단하게 android:padding으로 해결할 수 있을 거라고 생각했습니다. 그런데 padding으로 조절되지 않아 정리글 남깁니다. 


스택오버플로우에 도움이 되는 글이 있습니다.(https://stackoverflow.com/questions/15116393/fit-image-in-imagebutton-in-android/15117536#15117536)


android:adjustViewBounds="true"
android:scaleType="fitCenter"
cs


위의 두 attribute에 대한 이야기가 나옵니다. 위의 두 속성은 ImageView에 정의된 것인데 ImageButton가 ImageView를 상속받기에 ImageButton에서도 사용가능한 것 같습니다. 따라서 디벨로퍼 사이트에서 ImageView에 정의된 adjustViewBounds와 scaleType attribute에 대해 찾아보겠습니다.



android:scaleType


Controls how the image should be resized or moved to match the size of this ImageView. See ImageView.ScaleType

ImageView의 사이즈에 맞추기 위해 이미지가 어떻게 resize되어야 하는지 혹은 이동되어야 하는지 조절한다는 말입니다. android:scaleType="fitCenter"와 같이 attribute의 값에 따라 조절하는 방식이 달라집니다. 

여러 방식 중에 fitCenter에 대해서만 간단히 보겠습니다.


CENTER

added in API level 1 

Matrix.ScaleToFit CENTER

Compute a scale that will maintain the original src aspect ratio, but will also ensure that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. The result is centered inside dst. 

원본 대상의 가로 세로 비율을 유지하면서 비율을 조절합니다. 원본이 대상의 안에 완전이 들어가는 것 또한 보장합니다. 적어도 하나의 축(X나 Y)에 대해서 확실히 들어맞습니다. 결과물은 대상의 중앙에 배치됩니다.

위의 나열된 속성들이 바로 우리가 ImageView(ImageButton)에 바라는 것입니다.


android:adjustViewBounds는 사용하지 않고(사용해도 차이가 없음) android:scaleType="fitCenter"만 사용했을 때 변화를 보겠습니다.

위의 오른쪽 버튼이  android:scaleType="fitCenter"가 적용된 사진입니다. 왼쪽 버튼에는 적용되지 않았습니다. 위의 사진만 보면 왼쪽 버튼의 이미지가 버튼에 딱 맞게 되어있다고 생각할 수도 있습니다. 하지만 그렇지 않습니다.


꺽쇠 모양의 이미지는 사실 상하에 여백이 좀 있습니다. 그래서 왼쪽 이미지 버튼의 이미지는 버튼의 경계에 딱 맞는 것이 아닙니다. 오히려 오른쪽 이미지 버튼의 이미지가 버튼의 경계에 맞세 설정됐습니다. 가로 세로 비율을 유지하면서 버튼의 경계에 맞도록 조절되어야 하므로 버튼의 상하 부분만 이미지와 접해있습니다.

그리고 android:scaleType="fitCenter" 값이 추가된 오른쪽 버튼의 경우 padding으로 여백 조절이 가능해졌습니다.


설명이 조금 길었지만 ImageButton 사용시 대부분의 경우에 android:scaleType="fitCenter'는 필수인 것 같습니다.


android:adjustViewBounds


Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.

May be a boolean value, such as "true" or "false".

이미지의 가로세로 비율을 유지하기 위해 이미지 이미지뷰의 경계를 조절한다는 말입니다. 그런데 제가 xml코드에서 테스트해봤을 때 위의 attribute를 true하나 false로 하나 동작의 차이를 느낄 수 없었습니다. ImageView의 bound를 adjust한다는 게 정확하게 무슨 말인지 잘 모르겠습니다.

구글 디벨로퍼 사이트의 설명도 상당히 불친절하게 되어있기에 직접 관련된 소스를 보겠습니다.


https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/widget/ImageView.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    /**
     * Set this to true if you want the ImageView to adjust its bounds
     * to preserve the aspect ratio of its drawable.
     *
     * <p><strong>Note:</strong> If the application targets API level 17 or lower,
     * adjustViewBounds will allow the drawable to shrink the view bounds, but not grow
     * to fill available measured space in all cases. This is for compatibility with
     * legacy {@link android.view.View.MeasureSpec MeasureSpec} and
     * {@link android.widget.RelativeLayout RelativeLayout} behavior.</p>
     *
     * @param adjustViewBounds Whether to adjust the bounds of this view
     * to preserve the original aspect ratio of the drawable.
     *
     * @see #getAdjustViewBounds()
     *
     * @attr ref android.R.styleable#ImageView_adjustViewBounds
     */
    @android.view.RemotableViewMethod
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        mAdjustViewBounds = adjustViewBounds;
        if (adjustViewBounds) {
            setScaleType(ScaleType.FIT_CENTER);
        }
    }
cs


adjustViewBounds의 기본값은 false이며 true로 설정되면 결국 scaleType을 fitCenter로 설정합니다. 그러면 android:scaleType="fitCenter"와 동일하게 동작을 해야하는데 왜 아무런 효과도 없는 것인지 모르겠습니다.


버그일까요?


몇 가지 테스트 도중에 android:adjustViewBounds="true"를 사용함으로써 차이가 있는 케이스를 발견했습니다.


1
2
3
4
5
6
7
8
9
<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:maxHeight="35dp"
    android:maxWidth="35dp"
    android:src="@drawable/left_arrow75d"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
/>
cs


바로 위의 코드처럼 layout_width와 layout_height는 wrap_content로 설정하고 maxWidth와 maxHeight를 모두 설정한 상태에서는 android:adjustViewBounds="true" 코드와 android:scaleType="fitCenter"를 함께 사용해야 효과가 발휘합니다.


아무것도 적용하지 않은 ①번의 경우에선 maxWidth와 maxHeight가 무시됐습니다.

②번의 경우에는 maxWidth와 maxHeight가 적용된 것 같습니다. 그런데 이미지가 조금 짤렸습니다.

③번의 경우는 maxWidth와 maxHeight가 무시됐습니다. ①번과 차이를 느낄 수 없습니다

④번의 경우 maxWidth와 maxHeight가 적용됐으며 이미지도 짤리지 않았습니다.


위의 테스트로 보아 android:adjustViewBounds="true"와 android:scaleType="fitCenter"는 다른 효과를 가지는 것 같습니다. 확실하게 파악하려면 안드로이드 소스를 많이 봐야할 것 습니다. 그러나 시간이 너무 많이 걸릴 것 같고 궁금증 해결 말고는 그럴 필요도 느끼지 못해 이 포스트는 잠정적으로 여기서 마무리합니다.






작성자

Posted by 드리머즈

관련 글

댓글 영역