안드로이드의 GUI 는 View 와 ViewGroup 의 계층으로 구성된다. View 는 Button 이나 Text Field 와 같은 UI Widget 들이다. (Windows 의 UI Component 들과 같은 개념이다). View Group 은 보이지 않는 컨테이너로, Child View 들이 어떻게 배치(Lay Out) 되는지 (Grid 나 Vertical List 같이)를 정의한다.

안드로이드는 View 와 ViewGroup 의 Subclass 들을 XML 의 Vocabulary 로 제공한다. 이 XML 로 UI 요소들의 계층을 쉽게 정의할 수 있다.

Layout 은 ViewGroup 의 Subclass 들이다. 대표적으로 LinearLayout 과 같은 Subclass 가 있다.

위 그림은 View 와 View Group 의 계층적인 관계도를 도식화 한 것이다.


Linear Layout  생성

res/layout 디렉토리에서 content_hello.xml 을 연다. 기본적으로 RelativeLayout과 TextView Child View 를 사용하도록 되어있다. 현재 코드를 수정해서 Linear Layout 과 EditText View 를 사용하도록 하겠다.

현재 안드로이드가 지원하는 Layout 에 대해서는 ViewGroup 클래스의 Child Class 들을 보면 알 수 있다.

  1. XML 에서 <TextView> 요소를 삭제한다
  2. <RelativeLayout> 요소를 <LinearLayout> 요소로 변경한다
  3. Layout 요소의 android:orientation 속성을 추가하고 "horizontal" 로 값을 준다
  4. Layout 요소의 android:padding 과 tools:context 속성들을 모두 삭제한다

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_hello">

위와 같은 코드로 Layout 정의가 변경되어야 한다.

LinearLayout 은 View Group 이며 (ViewGroup의 Subclass), View 들을 android:orientation 속성값에 따라 Vertical 이나 Horizontal 하게 레이아웃 할 수 있다. Linear Layout 의 Child 요소들은 XML 에 정의된 순서대로 표시된다.

android:layout_width, android:layout_height 는 ViewGroup 의 Nest 클래스인 LayoutParams 클래스의 XML 속성으로, 모든 View 들은 이 속성을 사용하여 Size 를 지정하여야 한다.

LinearLayout 이 Layout 의 Root View 이므로, 앱 이 가능한 전체 스크린 사이즈로 크기를 지정한다 ("match_parent" 를 쓰면, 부모 뷰의 크기와 동일한 크기의 width 와 hegith 를 지정하게 된다).


Text Field 추가

모든 View 가 그렇듯, EditText 객체에도 특정 XML 속성을 추가해주어야 한다.

  1. content_hello.xml 에서 <LinearLayout> 요소의 하위 요소로 <EditText>요소를 추가한다.
  2. <EditText> 요소의 속성에 id 를 추가하고, 값을 @+id/edit_message 로 입력한다
  3. layout_width 와 layout_height 는 wrap_content 로 정의한다.
  4. hint 속성으로 edit_message 라는 String 객체를 값으로 넣어준다 (@string/edit_message)

<EditText android:id="@+id/edit_message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/edit_message" />

그러면 위와 같은 코드가 될것이다.

각 속성에 대한 설명을 하면, 

  • android:id
    View 에 대한 유일한 식별자를 부여하는 것이다. 이 ID 를 통해 View 객체로부터 값을 읽거나 객체를 조작할 수 있다.
    @ 는 XML 에서 모든 리소스 객체를 참조할 때 사용하는 식별자이다.
    android:id="@<리소스타입>/<리소스이름>" 의 형태로 사용한다.
    + 는 리소스 ID 를 처음으로 정의할 때에만 사용한다. 앱을 컴파일할 때 SDK 툴은 프로젝트의 gen/R.java 파일에 EditText 를 참조하는 새로운 리소스 ID 를 만들 때 이 식별자를 사용한다.
    그러나, 리소스 ID 가 생성된 이후 부터는 + 기호를 붙이지 않는다. 또한 String 이나 layout 같은 실체가 있는 리소스에는 사용하지 않는다.

  • android:layout_width, android:layout_height
    특정 사이즈를 입력하는 대신에 "wrap_content"를 사용하면 View 의 Content 크기에 맞게 View 크기가 결정된다. 만약 "match_parent"를 썼다면 View 는 전체 스크린 사이즈로 생성될 것이다. 왜냐하면, EditText의 부모 View 가 LinearLayout 이고 이 Size 는 앱의 전체 화면크기가 되기 때문이다.

  • android:hint
    Text Field 에 값이 없을 때 기본으로 표시되는 값이다. 값을 하드코딩 하는 대신에 "@string/edit_message"와 같이 해주면, 값은 String 리소스가 정의된 분리된 파일을 참조한다.

    hint 의 리소스 객체 이름이 위의 ID 요소와 같다(edit_message). 그러나 리소스 타입이 다르므로 충돌이 발생하지 않는다.


리소스 객체

리소스 객체(Resource Object)는 앱 리소스와 연관된 비트맵, Layout 파일, String 등의 유일한 Integer 이름이다.
모든 리소스는 gens/R.java 내에 상응하는 리소스 객체가 정의된다. R 클래스 내의 객체 이름을 사용하여 android:hint 와 같은 리소스를 참조할 수 있다.
또한 View 와 연계되는 임의의 리소스 ID 를 android:id 를 통해 생성할 수 있다. 
SDK Tool 은 매 컴파일 마다 R.java 파일을 생성한다. 이 파일을 수동으로 편집하지 말아야 한다. 


String Resource 추가

기본적으로 프로젝트에는 res/values/strings.xml 파일이 추가되어있다. 여기에 "edit_message" 라는 리소스 이름의 새로운 String 객체를 만들고, 값을 "메시지 입력" 이라고 설정할 것이다.

<resources>
    <string name="app_name">Hello Android</string>
    <string name="edit_message">메시지 입력</string>
    <string name="button_send">보내기</string>
    <string name="action_settings">설정</string>
</resources>

위와 같이 res/values/strings.xml 파일을 편집한다. 이후에 할 작업들이 더 있는데, 여기에서 사용할 추가적인 String 리소스 객체들도 넣어주었다.

Button 추가

메시지 Send 버튼을 하나 추가해본다. 아래와 같이 context XML 에 Edit Text 다음에 Button 요소를 하나 추가한다.
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button_send" />

버튼 Size 는 wrap_content 로 버튼 내부의 컨텐츠 사이즈에 자동으로 버튼 크기를 맞추도록 했다.

Preview 에서 보이는 화면의 일부이다. 


그런데 영 모양이 좋지가 않다. 메시지 입력하는 부분이 wrap_content 사이즈를 갖기때문인데, 다음 과정에서 좀더 보기좋게 모양을 변경해 보도록 한다.

화면 넓이 만큼 Input Box 채우기

Android 의 View 들은 layout_weight 라는 개념이 있다.
특정 수치에 의한 고정값을 사이즈로 주는것이 아니라 한줄에 들어갈 View 간에 사이즈 비율을 주는 것이다. 예를 들어 EditText 의 Weight 가 2 이고 Button 이 1 이면 2:1 의 화면 비율로 채우란 이야기이다.
기본값은 0 으로, weight 의 비율이 설정되지 않는다.

만약 여기에, EditText 를 weight 1 로 주고, Button 의 width 가 wrap_content 라면, Button 의 wrap_content 에 의해 계산된 사이즈를 뺀 나머지 크기를 EditText 가 모두 채우게 된다.
<EditText android:id="@+id/edit_message"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:hint="@string/edit_message"
    android:layout_weight="1"/>

위와 같이 코드를 작성하되, EditText 의 layout_width 가 기존의 wrap_content 에서 0dp 로 변경된것을 유의해서 보아야 한다. EditText 의 weight 를 주었으므로 궂이 layout_width 를 wrap_content 로 하여 컨텐츠 영역의 넓이를 계싼하게 할 필요가 없다. 이는 성능상의 이유로 0dp 를 주어 계산을 건너뛰게 한것이다.


Preview 에서 위와 같이 보이게 되고,


실제 디바이스에서는 위와 같이 표시된다. (갤럭시 노트 4 / 안드로이드 5.1.1 Lollipop MR1 / API Level 22)


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,