안드로이드 나인 패치(9-Patch) 이미지 버튼. (Android Nine-Patch Image Button)

2017. 6. 7. 11:02


1. 이미지 버튼 사용 시 만날 수 있는 문제.

안드로이드에서 기본적으로 제공하는 Button 위젯의 단순함을 향상시키기 위한 하나의 방법으로, 이전 글 [개발자 레시피 - 안드로이드 이미지 버튼 만들기]에서 Button에 이미지를 표시하는 방법을 설명하였습니다. 이미지 버튼을 사용하면, 이미지 파일(주로 png, 또는 jpg)에 저장된 이미지를 Button 위에 표시하여, 자신만의 디자인이 적용된 버튼 UI를 제공할 수 있죠.


그리고 [개발자 레시피 - 안드로이드 이미지 버튼에 텍스트 출력하기]와 [개발자 레시피 - 안드로이드 이미지 버튼에 아이콘 이미지 출력하기]에 정리한 글을 통해 이미지 버튼에 텍스트 또는 전면 이미지를 표시하여 이미지 버튼을 확장하는 방법에 대해 살펴보았습니다.


앞선 여러 버튼 예제들을 통해 이미지 버튼을 만드는 방법에 관해서는 충분히 숙지하였을테니, 이전 글에서 설명한 방법에 따라 자신의 앱에 이미지 버튼을 추가하는 상황을 가정해보겠습니다.


아래 그림과 같이, 안드로이드 기기 화면 너비를 삼등분한 크기에 맞게 세 개의 이미지를 만든 다음, 각각의 이미지를 Button을 사용하여 표시하도록 하겠습니다. 각 버튼의 문자열 텍스트와 함께 말이죠.

ImageButton에 표시할 이미지


버튼들이 화면에 표시된 내용은 아래와 같습니다.

ImageButton 세로 모드 표시 예제


그림과 같이 세 개의 이미지 버튼이 나란히 출력되는 것을 확인할 수 있습니다. 음, 깔끔하네요.


그럼 이제 안드로이드 기기를 90도 회전시켜서, 화면 모드를 가로 모드로 바꿔보도록 하겠습니다.

ImageButton 가로 모드 표시 문제


의도(?)한 것과는 조금 다르게, 가로 방향으로 늘어난 화면 크기에 따라, 버튼의 이미지 또한 늘려진 형태로 표시되는 것을 확인할 수 있습니다.

ImageButton 세로, 가로 모드 차이 문제점


버튼에 표시된 이미지가 식별 가능한 건 분명한 사실이지만, 그림과 같이 가로로 늘려진(stretch) 형태로 표시되는 것은, 그리 썩 좋은 결과는 아닐 것입니다.

2. 나인 패치(9-Patch) 이미지.

자, 그럼 위에서 살펴본 이미지 버튼의 문제를 해결하려면 어떻게 해야 할까요? 물론, 기기 별 해상도 및 화면 모드에 따라 각각의 이미지 파일을 모두 만들어 사용한다면, 가장 만족스러운 결과를 얻을 수 있겠죠. 하지만, 그 많은 수의 이미지 파일을 만들고 관리하는게 그리 쉬운 작업은 아닐 것입니다.


대신, 아래의 그림과 같이, 이미지의 특정 영역(주로 가장자리)은 원본 이미지 그대로 표시되도록 만들고, 그 외 이미지의 내용이 표시되는 영역을 버튼의 크기에 따라 늘어나도록 만들면, 아래 그림처럼 버튼의 크기가 늘어나더라도, 깔끔한 형태의 이미지 버튼을 표시할 수 있을 것입니다.

나인 패치(9-Patch)가 적용된 ImageButton


이렇게, "이미지에서 늘어날 수 있는(stretchable) 영역과 원본 크기대로 표시되어야 할 영역을 구분하여, 이미지가 그려질 영역의 크기가 늘어나거나 줄어들더라도 원본이미지 형태를 유지하도록 만들어진 이미지"를 나인 패치(9-Patch) 이미지라고 합니다.

2.1 나인 패치(9-Patch) 이미지 파일.

안드로이드에서 사용되는 나인 패치(9-Patch) 이미지가 일반적인 이미지 파일과는 다르게 취급된다고 하더라도, 나인 패치(9-Patch)만의 특별한 파일 포맷으로 저장되는 것은 아닙니다. 일반적으로 사용되는 png 이미지 파일 형식과 확장자가 그대로 사용됩니다. 단, 파일의 확장자를 포함한 이름의 마지막이 ".9.png"로 끝나면, 안드로이드에서는 이를 나인 패치(9-Patch) 이미지 파일로 인식하여 처리합니다. 그리고 늘어날(stretchable) 영역과 고정(fixed) 영역 등에 대한 정보는 원본 이미지에 추가된 상하좌우 1 pixel 영역에 저장되기 때문에, 추가적으로 요구되는 파일도 없습니다.


나인 패치(9-Patch) 이미지 파일이 ".9.png" 로 저장된다고 하더라도, 소스에서 참조될 때는 ".9"를 제외한 파일 이름만 리소스 이름으로 사용됩니다. 즉, "/res/drawable/image.9.png"로 저장된 파일을 XML 에서 사용할 때는, "@drawable/image.9" 가 아닌, "@drawable/image"로 참조한다는 것입니다.

2.2 나인 패치(9-Patch) 이미지의 영역 구분

나인 패치(9-Patch) 이미지는 크게 두 개의 영역으로 나뉩니다. 하나는 뷰의 크기에 따라 늘어나야 할 이미지 영역이고, 다른 하나는 뷰의 크기와 관계없이 원본 이미지 그대로 표시되는 영역입니다.


나인 패치(9-Patch)에서는 이 두 가지 영역을 구분하기 위해, 기본적으로 이미지를 9개의 세부 영역으로 나눕니다. 그런 다음, 4개의 모서리 영역은 원본 이미지를 그대로 그리고, 나머지 5개 영역은 뷰의 크기에 따라 늘려서 그립니다. (이제 왜 이름이 나인 패치(9-Patch)인지 아시겠죠?)

나인 패치(9-Patch)에서 Patch의 사전적 의미


글로 설명된 내용 만으로는 쉽게 이해되지 않을 수 있으니, 아래 그림을 통해 각 영역의 구분과 구분된 영역에 따라 이미지가 표시되는 방법을 확인해보겠습니다.

나인 패치(9-Patch) 이미지 영역


나인 패치(9-Patch)의 세부 영역이 반드시 9개로 나뉘어야 하는 것은 아닙니다. 일부 모서리가 뷰의 크기에 따라 늘어나야 한다거나, 원본 크기대로 그려져야 하는 영역과 늘어나야 하는 영역이 섞여 있는 경우, 세부 영역을 다양한 갯수로 구분하여 사용할 수 있습니다. 즉, 크기가 늘어나는 영역의 갯수를 원하는 만큼 설정할 수 있다는 것이죠.

나인 패치(9-Patch) 이미지 영역의 예


2.3 나인 패치(9-Patch) 이미지의 영역 정보

앞서 나인 패치(9-Patch)의 영역에 대해 살펴봤는데요, 그렇다면, 나인 패치(9-Patch) 이미지에서 늘어나야 할 영역의 정보는 어디에 저장되는 것일까요? 원본 이미지의 위(over)에 영역 정보를 표시하면, 원본 이미지를 훼손하게 되어 이미지를 올바르게 표시할 수 없을텐데 말이죠.


나인 패치(9-Patch)에서는 이미지가 늘어나야 할 영역에 대한 정보를 저장하기 위해 원본이미지(image.png) 크기에서 상/하/좌/우 각각 1픽셀(pixel) 씩 늘린 이미지(image.9.png)를 새로 만듭니다. 그리고 위(Top) 1픽셀(pixel) 라인에는 가로로 늘어날 영역을 기록하고, 왼쪽(Left) 1픽셀(pixel) 라인에는 세로로 늘어날 영역을 기록합니다.


이 때, 늘어나야 할 영역은 BLACK(0xFF000000)으로 채우고, 그렇지 않은 영역은 WHITE(0xFFFFFFFF) 또는 TRANSPARENT(0x00XXXXXX)로 채웁니다.


아래 그림을 보며 나인 패치의 설명을 다시 읽어보면, 좀 더 이해가 쉬울 것입니다.

나인 패치(9-Patch) 이미지 동작 방식


앞서 나인 패치(9-Patch) 이미지의 세부 영역 구분에 대해 언급할 때 다양한 형태의 나인 패치 영역에 대해 설명했었는데요, 여기서도 몇 가지 예를 더 들어보겠습니다.

나인 패치(9-Patch) 이미지의 몇 가지 예제


2.4 나인 패치(9-Patch)의 컨텐츠(contents) 영역 지정

자, 이제 나인 패치(9-Patch) 이미지가 그려지는 과정에 대해 알게 되었으니, 버튼의 배경에 나인 패치(9-Patch) 이미지를 지정하고 버튼 텍스트를 표시해볼까요? 버튼에 텍스트를 표시할 때는 가운데(center)를 기준으로 표시하는 게 일반적이지만, 지금은 특별히 왼쪽/위를 기준으로 표시되도록 만들겠습니다.

나인 패치(9-Patch) 컨텐츠 padding 필요성 1


음, 텍스트가 버튼의 왼쪽/위에 표시되지만, 이미지의 경계 영역을 침범해버리는 문제가 발생하는군요. 이미지의 형태에 따라 어느 정도 추가 공간(Padding)이 주어진다면 버튼의 텍스트가 이미지의 경계를 침범하는 문제가 발생하지 않을텐데요. 아래 그림처럼 말이죠.

나인 패치(9-Patch) 컨텐츠 padding 필요성 2


이렇게, 나인 패치(9-Patch) 이미지가 뷰(View)의 배경으로 사용될 때, 컨텐츠(contents)가 표시될 영역을 지정해야 하는 경우가 있는데, 이 때 나인 패치(9-Patch) 이미지의 오른쪽(Right)/아래(Bottom) 1픽셀(pixel) 테두리를 사용하여 지정할 수 있습니다. 참고로 컨텐츠 영역 지정은 선택 사항(optional) 입니다.

나인 패치(9-Patch) 컨텐츠 영역 지정


컨텐츠(contents) 영역 지정은 이미지 영역 지정과 마찬가지로 BLACK(0xFF000000)으로 채웁니다. 그 외 영역은 WHITE(0xFFFFFFFF) 또는 TRANSPARENT(0x00XXXXXX)로 채우면 됩니다.

아래 그림은 컨텐츠(contents) 영역 지정에 따른 텍스트 표시 예를 나타낸 것입니다.

나인 패치(9-Patch) 컨텐츠 영역 예제


4. 참고

.END.


ANDROID 프로그래밍/BUTTON , , , , , , , , , ,

  1. Blog Icon

    나인패치에 대해 한방에 이해되네요.
    도움 많이 되었습니다.

  2. 도움이 되셨다니 다행입니다.

    감사합니다.

  3. 저도 마찬가지로 윗분에 동감합니다. 이해하기 쉽고 도움 많이 되었습니다.

    좋은글 감사합니다 잘 읽었습니다

  4. 도움이 되셨다니, 다행입니다.
    방문해 주셔서 감사합니다.

  5. Blog Icon
    oz

    좋은 글 감사합니다. 나인패치 이해에 좋은 게시글이네요.
    한가지 문의점이 있는데요.

    1. 버튼에 글씨가 들어가지 않는 경우는 컨텐츠 영역지정을 어떻게 해야하나요? 빈틈 없이 전부다 채워야하나요?

    시간되실때 답변 부탁드립니다. 감사합니다.

  6. 먼저, 답변을 늦게 드리게 되어 죄송합니다.
    버튼에 글씨가 들어가지 않는 경우는 컨텐츠 영역 지정이 의미를 가지지 않기 때문에, 어떻게 지정하던지 상관없습니다. 컨텐츠가 표시되어야 하는 경우에만 의미를 가지니까요.

    감사합니다.