2009년 12월 5일 토요일

5. 안드로이드 사용자 인터페이스

5.1 사용자 인터페이스 개요

 

안드로이드 어플리케이션은 사용자 인터페이스를 만들 때 View와 ViewGroup 객체를 사용합니다. 뷰나 뷰 그룹은 여러 가지가 있으나 모두 View 클래스를 상속받은 것들입니다. 안드로이드 플랫폼에서 사용자 인터페이스를 만드는 기본 빌딩 블럭이 바로 이 View 객체입니다. View 클래스는 "위젯(widget)" 하위 클래스들의 기반이 됩니다. 실제로 위젯은 완전하게 구현된 UI 객체입니다. 예를 들면, 텍스트 필드나 버튼 같은 것들이 위젯입니다. ViewGroup 클래스는 "레이아웃(layout)" 하위 클래스의 기반이 됩니다. 레이아웃을 이용하여 화면 배치를 다양하게 만들 수 있습니다. 예를 들면, 일렬로 나열하거나 테이블로 표현하거나, 서로 상대적인 관계를 표현하거나 할 수 있습니다.

 

View 객체는 레이아웃 매개변수나 화면의 특정 사각 영역에 대한 정보를 담고 있는 자료 구조입니다. View 객체는 자신이 놓여 있는 화면 영역의 위치나 크기 정보와 배치, 화면 영역 안에 그리기, 포커스 변경 처리, 스크롤, 키 또는 제스처 상호 작용 처리 등을 담당하고 있습니다. 다시 말해서 사용자 인터페이스 객체로서 사용자와 상호작용을 위한 창구 및 이벤트 리스너(listener) 역할을 합니다.

 

(1) 뷰 계층 구조

 

안드로이드 플랫폼에서 액티비티의 UI를 정의할 때는 아래 그림과 같이 뷰나 뷰 그룹의 계층 구조로 정의합니다. 이런 계층 구조는 개발하려는 UI의 복잡도에 따라서 달라지겠지요. UI 계층 구조는 안드로이드에 미리 정의된 위젯이나 레이아웃을 이용할 수도 있고, 자신의 용도에 맞게 맞춤식 뷰를 만들 수도 있습니다.

 

 

이런 뷰 계층 구조를 화면에 표시하기 위해서는 액티비티에서 setContentView() 메소드를 부르면 됩니다. 호출 시 인자로 뷰 계층 구조 트리의 루트 노드에 대한 참조를 전달해야 합니다. 안드로이드 시스템은 이 참조를 받아서 뷰 트리에 해당하는 화면 영역이 어디인지 측정하고, 해당 화면 영역을 지우고(invalidate), 이 화면 영역에 다시 인자로 받은 뷰 트리의 루트 노드를 그립니다. 물론 뷰 계층 구조 트리의 루트 노드는 다시 자기 자식 노드들에게 뭔가를 그리라고 요청할 수 있습니다. 이렇게 차례로 계층 구조 트리를 따라 내려 가면서 각각의 노드를 그리게 됩니다. 각 뷰 그룹 노드는 자신은 그릴 필요가 없고 자식 노드들에게 뭔가를 그리라고 요청만 하면 되겠지요. 자식 노드는 부모 노드의 어느 위치에 어떤 크기로 그려야 할 지를 부모 노드에게 물어 볼 수 있습니다. 부모 객체가 자식 객체를 어디에 어떤 크기로 그릴 지를 최종 결정합니다. 안드로이드는 레이아웃 구성 요소들을 파싱할 때 계층 구조의 꼭대기에서부터 in-order로 따라 가면서 파싱합니다. in-order로 파싱한다는 의미는 뷰들을 인스턴스화 한 후에 이것들을 부모 노드에 추가하는 식으로 동작한다는 뜻입니다. 그릴 때도 in-order로 그려지기 때문에 만일 두 구성 요소의 위치가 겹치게 되면 마지막에 그려지는 구성 요소가 이전에 그려진 구성 요소 위에 그려지게 됩니다. 뷰 계층 구조가 어떻게 측정되고 그려지는지는 다음에 다시 자세히 설명하겠습니다.

 

(2) 레이아웃

 

XML 파일로 레이아웃을 정의하고 뷰 계층 구조를 표현하는 것이 가장 일반적인 방법입니다. XML은 HTML 처럼 사람이 읽을 수 있도록 구조를 표현합니다. XML에 있는 각 구성 요소는 뷰 객체이거나 뷰 그룹 객체 중 하나입니다. 앞의 그림에서 설명했듯이 뷰 객체들은 트리의 끝에 있는 잎이고, 뷰 그룹 객체는 트리의 가지입니다.

 

XML 구성 요소의 이름은 해당 자바 클래스의 이름을 쓰면 됩니다. <TextView> 요소는 TextView를 생성합니다. <LinearLayout> 요소는 LinearLayout 뷰 그룹을 생성합니다. 레이아웃 리소스를 로드할 때, 안드로이드 시스템이 레이아웃에 있는 각 구성 요소에 대응되는 이런 런타임 객체를 초기화해 줍니다. 아래 소스 코드는 텍스트 뷰와 버튼을 가진 간단한 수직 레이아웃의 예입니다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

 

위 코드를 보면 LinearLayout 요소 안에 TextView와 Button이 있습니다. 위 뷰 계층 구조를 더 확장하여 더 복잡한 레이아웃을 만들려면 여기에다 다른 LinearLayout을 중첩시키면 됩니다. UI 레이아웃을 만드는 방법은 추후 더 자세히 설명드리겠습니다.

 

뷰를 배치하는 방법은 여러 가지가 있습니다. 더 다양한 종류의 뷰 그룹을 사용하면 무한히 많은 방법으로 자식 뷰와 뷰 그룹을 구조화할 수 있겠죠. 안드로이드가 제공하는 미리 정의된 뷰 그룹(레이아웃)에는 LinearLayout, RelativeLayout, TableLayout, GridLayout 등이 있습니다. 각각은 각기 다른 파라미터로 자식 뷰의 위치나 레이아웃 구조를 정의하고 있습니다.

 

 

(3) 위젯

 

위젯은 사용자와 상호 작용하기 위한 인터페이스로 뷰 객체의 일종입니다. 안드로이드는 버튼, 체크 박스, 텍스트 입력 필드 등과 같이 완전히 구현된 위젯들을 제공해 줍니다. 이 위젯들을 이용하여 UI를 신속하게 만들 수 있습니다. 안드로이드는 날짜 지정, 줌 컨트롤과 같은 더 복잡한 위젯도 제공합니다. 그렇다고 안드로이드 플랫폼에서 제공 가능한 위젯의 종류가 제한되어 있는 것은 아닙니다. 만약 맞춤식 위젯을 원한다면 기존 위젯을 확장하거나 조립하여 새로운 뷰 객체를 정의할 수 있습니다.

 

(4) UI 이벤트

 

일단 UI에 뷰나 위젯을 추가했다면, 이것들과 상호작용하는 방법을 알아야 원하는 동작을 수행할 수 있습니다. UI 이벤트를 받으려면 다음 2 가지 중 하나를 해야 합니다.

 

  • 이벤트 리스너(listener)를 하나 정의하고 뷰에 등록
    이벤트를 받지 않을 경우보다는 받을 일이 더 많겠죠. 이럴 때는 특정 이벤트를 수신하는 리스너를 정의하고 뷰에 등록해야 합니다. View 클래스에는 On<이벤트 이름>Listener 형식의 인터페이스가 여러 개 정의되어 있습니다. 이런 각각의 리스너에는 On<이벤트 이름>() 형식의 콜백 함수가 대응됩니다. 예를 들면, 뷰의 클릭 이벤트를 수신하기 위한 View.OnClickListener가 있고, 뷰의 터치 스크린 이벤트를 수신하기 위한 View.OnTouchListener가 있고, 뷰의 키 입력 이벤트를 수신하기 위한 View.OnKeyListener가 있습니다. 버튼이 선택되었을 때 즉, 클릭이 되었을 때 뷰가 이런 이벤트를 수신하려면 OnClickListener를 정의하고 setOnClickListener() 메소드로 뷰에 등록을 해야 합니다. 그리고 이런 이벤트를 받았을 때 뭔가를 수행하려면 onClick() 콜백 메소드를 구현해야 합니다.
  • 뷰에 있는 기존 콜백 메소드의 재정의
    View
    클래스를 하나 구현하고 나서 특정 이벤트의 동작을 재정의하고자 할 때 사용합니다. 이런 이벤트로는 스크린이 터치되었을 때 onTouchEvent(), 트랙볼이 움직였을 때 onTrackballEvent(), 장치에 있는 키가 눌렸을 때 onKeyDown() 등이 있습니다. 자신의 맞춤형 뷰에서 각 이벤트의 기본 동작을 재정의하거나 자식 뷰에게 이런 이벤트를 전달하고 할 때 사용합니다. 이런 함수들은 뷰 클래스의 콜백 함수들입니다. 따라서 이런 콜백 함수를 재정의하는 경우는 맞춤형 컴포넌트를 만들었을 때만 하면 됩니다.

 

(5) 메뉴

 

어플리케이션 메뉴는 UI의 중요한 부분 중 하나죠. 이런 메뉴는 어플리케이션의 기능이나 설정을 드러낼 때 주로 사용됩니다. 장치의 MENU 키를 눌렀을 때 나오는 메뉴가 가장 대표적인 것입니다. 이 외에도 여러 가지 메뉴가 있습니다. 예를 들면 문맥(context) 메뉴를 추가하여 사용자가 어떤 항목을 누르고 있으면 튀어 나오게 할 수 있습니다.

 

메뉴도 뷰 계층 구조를 사용하여 구조화됩니다. 그러나 사용자가 이런 구조를 일일이 정의할 필요는 없습니다. 대신에 액티비티에 onCreateOptionsMenu()나 onCreateContextMenu() 콜백 함수만 정의하면 됩니다. 그리고 메뉴에 포함되길 원하는 항목을 액티비티에 선언하세요. 그러면 적당한 시점에 안드로이드가 자동으로 메뉴를 구성하여 뷰 계층 구조를 만들고 각 메뉴 항목을 화면에 그려 줍니다.

 

메뉴 관련 이벤트를 처리할 필요가 있을 때도 각 메뉴 항목에 대한 이벤트 리스너를 등록할 필요가 없습니다. 메뉴에 있는 항목이 하나 선택되면 onOptionsItemSelected()나 onContextItemSelected() 메소드가 프레임웍에 의해서 호출됩니다. 레이아웃처럼 메뉴도 XML 파일에 각 항목이 선언되어 있습니다.
 

(6) 어뎁터

 

외부 데이터를 가지고 뷰를 구성하거나 하드 코딩되지 않은 정보를 가진 뷰 그룹을 만들고 싶을 때가 있겠죠. 이렇게 하려면 뷰 그룹으로 AdapterView를 사용하고, 각 자식 뷰를 어뎁터에서 초기화하고 데이터를 집어 넣어 주면 됩니다.

 

AdapterView 객체는 주어진 Adapter 객체에 기반하여 자신의 자식 뷰들을 결정하도록 ViewGroup을 구현한 것입니다. Adapter는 데이터 원천(아마도 외부 문자열 배열이 되겠죠)과 이 데이터를 디스플레이하는 AdapterView 사이에서 전달자처럼 동작합니다. Adapter 클래스를 구현한 예는 많이 있습니다. Cursor로부터 오는 데이터베이스 데이터를 읽는 CursorAdapter도 있고, 임의의 배열로부터 데이터를 읽는 ArrayAdapter도 있습니다.

 

(7) 스타일과 테마

 

표준 위젯의 모양이 마음에 안 드는 분도 있겠죠. 이런 모양을 고치고 싶다면 자기 자신만의 스타일이나 테마를 만들 수도 있습니다.

 

  • 스타일은 하나 이상의 포맷팅 속성들의 집합입니다. 스타일 속성들은 레이아웃의 각각의 구성 요소에 스타일 단위로 적용될 수 있습니다. 예를 들면, 어떤 텍스트의 크기나 색깔을 규정하는 스타일을 하나 정의하고, 이 스타일을 특정 뷰 구성 요소에 적용할 수 있습니다.
  • 테마도 하나 이상의 포맷팅 속성들의 집합입니다. 테마 속성들은 어떤 어플리케이션의 모든 액티비티에 테마 단위로 적용될 수도 있고, 하나의 액티비티에만 적용될 수도 있습니다. 예를 들면, 윈도 프레임의 색깔이나 패널의 배경색을 특정 색으로 바꾼다든지, 메뉴의 텍스트 크기나 색깔을 바꿀 수 있습니다. 이렇게 테마는 특정 액티비티나 전체 어플리케이션에 적용될 수 있습니다.

 

스타일이나 테마는 리소스입니다. 안드로이드는 기본 스타일이나 테마 리소스를 몇 개 제공합니다. 이것들을 그대로 사용하거나 새로운 맞춤형 스타일이나 테마 리소스를 새로 선언할 수 있습니다.

 

5.2 레이아웃 선언하기

 

레이아웃은 액티비티 안의 사용자 인터페이스를 정의하기 위한 아키텍처입니다. 레이아웃은 사용자에게 보여지는 모든 구성 요소들을 가지고 있으며, 이것들의 배치 구조를 정의합니다. 다음과 같이 2 가지 방법으로 레이아웃을 선언합니다.

 

  • XML로 UI 구성 요소 선언
    안드로이드는 뷰 클래스와 그 하위 클래스에 각각 직접 대응되는 XML 어휘(예를 들면, 위젯이나 레이아웃 등)를 제공합니다.
  • 실행 시 레이아웃 구성 요소의 인스턴스화
    프로그램으로 뷰나 뷰 그룹 객체를 생성할 수 있습니다. 물론 속성 값들도 프로그램으로 지정하면 됩니다.

 

안드로이드 프레임웍은 어플리케이션의 UI를 선언하고 관리하는 방법으로 위 2 가지 중 하나 또는 2 가지 방법 모두를 사용할 수 있도록 유연성을 제공합니다. 예를 들면, 어플리케이션의 기본 레이아웃(화면에 표시될 스크린 구성 요소와 그 속성들)은 XML로 선언하고, 실행시 XML로 선언된 화면 객체들의 상태를 변화시킬 수 있는 것들은 어플리케이션의 코드에 추가할 수 있습니다.

 

XML로 UI를 선언하는 장점은 어플리케이션의 동작을 제어하는 코드로부터 겉모습(presentation)을 더 잘 분리할 수 있다는 점입니다. UI 서술 내역이 어플리케이션 코드의 외부에 있기 때문에 소스 코드를 수정하여 재컴파일 하지 않고도 UI를 수정하여 적용할 수 있습니다. 예를 들면, 여러 가지 다른 화면 방향(orientation)이나 여러 가지 다른 장치 화면 크기, 다양한 언어에 따른 XML 레이아웃을 만들어 놓을 수 있습니다. 또한 XML에 레이아웃을 선언하면 UI 구조를 더 쉽게 가시화시킬 수 있어서 디버깅도 쉬워집니다. 따라서 이 장에서는 XML에 레이아웃을 선언하는 방법에 대한 설명에만 집중합니다.

 

  • 이클립스 ADT 플러그인은 XML 레이아웃의 미리보기 기능을 제공합니다. XML 파일을 연 후에 Layout 탭을 선택하면 레이아웃을 볼 수 있습니다.
  • 레이아웃 디버깅을 하려면 계층 구조 뷰어 도구를 꼭 사용하세요. 이 도구를 이용하면 레이아웃 속성 값을 볼 수 있고, 패딩(padding)/마진(margin) 인디케이터를 가지고 윤곽을 그려 볼 수 있고, 에뮬레이터나 장치에서 디버깅할 때 모두 그려진 뷰들을 볼 수 있습니다.
  • layoutopt 도구를 사용하면 비효율적이거나 다른 문제가 있는 레이아웃이나 계층 구조를 신속히 분석할 수 있습니다.

 

일반적으로 XML 어휘는 XML 요소의 경우 클래스나 메소드의 구조나 명명법을 그대로 따릅니다. 요소의 이름은 클래스 이름에 대응되고, 속성의 이름은 메소드에 대응됩니다. 사실 이런 대응 관계가 너무 직관적이라서 어떤 XML 속성이 어떤 클래스 메소드에 대응되는지, 어떤 클래스가 어떤 XML 요소에 대응되는지 추측할 수 있죠. 그러나 모든 어휘가 이런 것은 아닙니다. 어떤 경우는 미세하게 명명법이 달라집니다. 예를 들면, EditText 요소는 EditText.setText()에 대응되는 setText 속성이 아닌 text 속성을 가지고 있습니다.

 

(1) XML 작성

 

안드로이드의 XML 어휘를 사용하여 UI 레이아웃과 이 레이아웃 안에 포함되는 스크린 구성 요소들을 신속히 설계할 수 있습니다. HTML로 일련의 중첩 요소를 가진 웹 페이지를 만드는 것처럼 말이죠. 각 레이아웃 파일에는 뷰 또는 뷰 그룹 객체인 루트 요소를 하나만 포함해야 합니다. 일단 루트 요소를 정의하면 추가적인 레이아웃 객체나 위젯들을 자식 요소로 추가하여 점진적으로 레이아웃을 구성하는 뷰 계층 구조를 만듭니다. 예를 들면, 앞에서 본 것과 같은 다음 XML 레이아웃은  TextView와 Button을 가지는 수직 LinearLayout입니다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

 

펼쳐두기..

 

XML로 레이아웃을 선언한 후에는 이 파일을 .xml 확장자로 안드로이드 프로젝트의 res/layout/ 디렉토리에 저장하여야 올바로 컴파일됩니다.

 

(2) XML 리소스 로드

 

어플리케이션을 컴파일할 때, 각 XML 레이아웃 파일도 뷰 리소스로 컴파일됩니다. 어플리케이션의 Activity.onCreate() 콜백 함수에서 이 레이아웃 리소스를 로드하는 코드를 구현해야 합니다.  R.layout.layout_file_name 형식의 레이아웃 리소스에 대한 참조를 인자로 전달하여 setContentView()를 호출하면 됩니다. 예를 들어 XML 레이아웃 파일이 main_layout.xml로 저장되어 있다면 다음 코드와 같이 액티비티에서 레이아웃 리소스를 로드할 수 있습니다.

 

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView.(R.layout.main_layout);
}

 

위 액티비티가 론치될 때 안드로이드 프레임웍에 의해서 onCreate() 콜백 메소드가 호출됩니다. 이에 대해서는 이미 4 장의 안드로이드 어플리케이션 기초의 액티비티 수명 부분에서 설명하였습니다.

 

(3) 속성

 

모든 뷰와 뷰 그룹 객체는 자신들의 다양한 XML 속성들을 지원합니다. 어떤 속성들은 특정 뷰 객체에만 해당됩니다. 예를 들면, TextView는 textSize 속성을 지원합니다. 그러나 이런 속성들은 이 클래스를 확장하는 다른 뷰 객체들에게도 상속됩니다. 어떤 속성들은 모든 뷰 객체들에 공통됩니다. id 속성과 같은 것들은 루트 뷰 클래스로부터 상속되기 때문입니다. 그리고 다른 속성들은 "레이아웃 파라미터"로 간주됩니다. 레이아웃 파라미터는 뷰 객체의 레이아웃 방향을 기술하는 속성입니다. 이런 속성은 해당 객체의 부모인 뷰 그룹 객체에 의해 정의됩니다.

 

ID

 

뷰 객체는 정수 ID를 가집니다. 이 ID는 트리 내에서 뷰를 식별하는 유일한 값입니다. 어플리케이션이 컴파일될 때 이 ID는 정수 값으로 참조가 됩니다 그러나 레이아웃 XML 파일에는 id 속성의 문자열 값으로 기술되어 있습니다. 이 ID는 View 클래스에 의해 정의되며 모든 뷰 객체에 공통된 속성입니다. 이 값을 사용할 일이 자주 있을 것입니다. XML 태그 내에서 ID를 사용할 때의 구문은 다음과 같습니다.

 

android:id="@+id/my_button"

 

문자열의 첫 번째 문자인 엣 심볼(@)은 XML 파서가 이 ID 문자열의 나머지 부분을 파싱한 후에 ID 리소스로 식별하도록 지시하는 것입니다. 플러스 심볼(+)은 R.java 리소스 파일에 새로운 이름을 생성하여 추가하라는 의미입니다. 안드로이드 프레임웍에서 사용되는 많은 ID 리소스들이 있습니다. 안드로이드 리소스 ID를 참조할 때는 플러스 심볼은 필요하지 않습니다. 다음과 같이 android 패키지 네임스페이스를 플러스 대신 추가해야 합니다.

 

android:id="@android:id/empty"

 

android 패키지 네임스페이스를 가지고 있으면 이제는 로컬 리소스 클래스가 아닌 android.R 리소스 클래스에서 ID를 참조합니다. 어플리케이션에서 뷰를 생성하고 참조하는 일반적인 패턴은 다음과 같습니다.

 

  1. 레이아웃 파일에 뷰/위젯을 정의하고 유일한 ID를 할당합니다.
    <Button android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/my_button_text"/>
    
  2. 그리고 뷰 객체의 인스턴스를 생성하고, (보통은 onCreate() 메소스에서) 다음과 같이 레이아웃에서 이것을 가져 옵니다.
    Button myButton = (Button) findViewById(R.id.my_button);
    

 

RelativeLayout을 생성할 때는 뷰 객체에 ID를 정의하는 것이 중요합니다. 상대 레이아웃에서는 형제 뷰의 배치가 다른 형제 뷰와의 상대적인 관계로 정의됩니다. 이럴 때 유일한 ID로 다른 형제 뷰를 참조합니다. 전체 트리를 통틀어서 ID가 유일할 필요는 없지만 검색 중인 부분에서는 유일해야 합니다. (물론 전체 트리에서 검색할 수도 있으므로 가능한 한 전체 트리에서 완벽히 유일하게 ID를 만드는 것이 제일 좋습니다.)

 

레이아웃 파라미터

 

layout_something으로 이름이 지어진 XML 레이아웃 속성은 뷰에 대한 레이아웃 파라미터를 정의합니다. 이 레이아웃 파라미터는 뷰가 어떤 뷰 그룹에 속하면 적합한 지를 나타냅니다. 모든 뷰 그룹 클래스는 ViewGroup.LayoutParams를 확장하여 중첩 클래스로 구현해야 합니다. 이런 하위 클래스는 뷰 그룹에 적합하도록 자식 뷰의 크기와 위치를 정의하는 속성을 가지고 있습니다. 아래 그림에서 부모 뷰 그룹은 자식 뷰(자식 뷰 그룹도 포함)의 레이아웃 파라미터를 정의하고 있습니다.

 

 

모든 LayoutParams 하위 클래스는 값을 설정하는 자신 만의 구문이 있습니다. 자식은 부모에 적합하도록 LayoutParams이 정의되어야 합니다. 물론 손자도 그 부모에 적합하도록 LayoutParams이 정의되어야 합니다.

 

모든 뷰 그룹은 폭과 높이(layout_width와 layout_height)를 가집니다. 각 뷰도 폭과 높이를 정의해야 합니다. LayoutParams는 마진과 테두리를 옵션으로 포함합니다. 폭과 높이를 정확히 측정하여 명시할 수도 있습니다. 비록 이렇게 자주 하고 싶지는 않겠죠. 종종 뷰에게 자신의 내용을 표시하기 위해서 필요한 폭과 높이를 알아서 지정하도록 할 수도 있고, 부모 뷰의 크기와 똑같게 맞출 수도 있습니다. 이럴 경우 각각 wrap_content와 fill_parent 값을 사용하면 됩니다. 허용되는 치수 타입은 이용가능한 리소스 문서에 정의되어 있습니다.

 

(4) 레이아웃 위치

 

뷰의 모양은 사각형입니다. 뷰의 위치는 left와 top 좌표로, 차원은 폭과 높이로 표현됩니다. 위치와 차원의 단위는 픽셀입니다.

 

getLeft()와 getTop() 메소드를 호출하여 뷰의 위치를 알 수 있습니다. 앞의 메소드는 뷰를 나타내는 사각형의 왼쪽 x 좌표를 반환하고, 뒤의 메소드는 위쪽 y 좌표를 반환합니다. 반환 값은 뷰의 부모의 위치에 상대적입니다. 즉, getLeft()가 20을 반환하면 현 뷰가 부모 뷰의 왼쪽 모서리에서 오른쪽으로 20 픽셀 떨어져서 위치하고 있다는 뜻입니다.

 

불필요한 계산을 피하도록 여러 가지 편리한 메소드들이 많이 제공됩니다. 예를 들면 뷰의 사작형 오른쪽 끝이나 아래쪽 끝의 좌표를 알아내는 getRight()나 getBottom() 등도 있습니다. getRight()는 getLeft() + getWidth()를 계산한 것과 같습니다.

 

(5) 크기, 패딩, 마진

 

뷰의 크기는 폭과 높이로 표현됩니다. 뷰는 실제로 폭과 높이를 두 쌍을 가지고 있습니다. 첫 번째 쌍은 measured width와 measured height입니다.  이 값은 뷰가 부모 안에서 얼마나 크게 표시되기를 원하는지 정의합니다. 이 차원 값은 getMeasuredWidth()와 getMeasuredHeight()를 호출하여 얻을 수 있습니다.

 

두번째 쌍은 width와 height입니다. 이 값은 때로는 각각 drawing width와 drawing height로 불립니다. 이 차원 값은 화면에 표시된 뷰의 실제 크기를 정의합니다. 이 값들은 measured width, measured height와 다를 수도 있습니다. (그렇다고 꼭 달라야 하는 것은 아닙니다.) 이 값들은 getWidth()와 getHeight()를 호출하여 얻을 수 있습니다. getPaddingLeft(), getPaddingTop(), getPaddingRight()와 getPaddingBottom() 메소드를 불러서 각각의 값을 얻을 수 있습니다.

비록 뷰가 패딩을 정의할 수 있지만 마진을 지원하지 않습니다. 뷰 그룹이 마진을 지원합니다. 더 자세한 사항은 ViewGroup과 ViewGroup.MarginLayoutParams을 참조하세요.

 

끝.

댓글 없음:

댓글 쓰기