본문 바로가기

Hello, Android

Hello, Android, 너를 보여줘 (2) - 코드를 이용한 화면 구성

강좌 작성환경
SDK Version : Android SDK 2.0, release 1
ADT Version : 0.9.4

추후 SDK업데이트로 인해 글의 내용과 최신 SDK 내용간 차이가 있을 수 있습니다.

지난 시간에는 레이아웃 파일(XML)을 이용하여 Hello, Android의 화면을 구성하는 것에 대해 알아보았습니다.

안드로이드 액티비티의 화면 구성 방법은 크게 두 가지가 있습니다. 하나는 앞에서 알아보았던 것처럼 레이아웃을 이용하여 화면을 구성하는 방법이고, 다른 하나는 이번 글에서 살펴볼 자바 코드를 통해 화면을 구성하는 방법입니다.일반적으로 정적인 레이아웃을 구성할 때는 레이아웃 파일을 이용하고, 동적인 레이아웃을 구성할 경우 자바 코드를 통해 레이아웃을 구성하게 되며 이 두 가지 방법을 모두 사용하여 레이아웃을 구성하는 것 또한 가능합니다. (기본 레이아웃을 구성한 후, 사용자의 동작에 따라 View들을 추가해주는 등의 레이아웃)

이번 글에서는 자바 코드만을 이용하여 저번 강좌의 Hello, Android와 동일한 화면을 구성하는 방법에 대해 알아보도록 하겠습니다. 아래는 저번 강좌에서 사용했던 레이아웃 파일입니다.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>

Hello, Android의 레이아웃은 LinearLayout을 바탕으로 하고 있으며, 그 안에 텍스트를 표시해주는 뷰인 TextView가 들어가 있습니다. TextView를 감싸고 있는 LinearLayout의 너비(layout_width) 및 높이(layout_height)는 각각 fill_parent, 즉 화면을 꽉 채우게 설정되어 있습니다. fill_parent 속성은 해당 뷰를 포함하는 부모 객체가 가진 너비 혹은 높이만큼의 크기를 가진다는 것인데, 여기에서 LinearLayout은 그 자체가 최상위 객체, 루트(root) 객체 이므로 액티비티의 화면을 꽉 채우게 됩니다.

한번, 화면에 표시되는 레이아웃이 어떤 구조를 가지고 있는지 알아보도록 하겠습니다. [SDK 설치 경로]/tools 폴더의 Hierarchy Viewer를 실행시켜 보면, 액티비티의 레이아웃이 어떤 구조를 가지고 있는지 더 잘 알 수 있습니다. HelloAndroid 어플리케이션이 실행된 상태에서 Hierarchy Viewer를 실행시킨 후, Load View Hierarchy 버튼을 누르면 아래와 같이 현재 화면의 View에 대한 정보들이 표시됩니다.

Hierarchy Viewer의 모습



아래는 Hello, Android의 뷰 구조입니다.


우리가 생각했던 구조는 LinearLayout이 TextView를 감싸고 있는 구조였는데, 생각보다 복잡해 보이는군요. 이는 화면에 표시되는 모든 View의 구조가 다 표시되었기 때문입니다. 별로 어렵지 않으니 하나하나씩 보도록 합시다. 



우선, 가장 상위에 위치한 개체, 루트 개체인 PhoneWindow$DecorView는 상태 표시줄을 제외한 실질적으로 액티비티 화면이 표시되는 모든 영역을 뜻합니다. 이는 크게 타이틀바 (액티비티 이름이 표시되는 영역)과 실제 액티비티의 내용들이 표시되는 영역으로 나뉩니다.




루트 객체의 바로 아래에는 타이틀바와 컨텐트 영역을 포함하는 LinearLayout이 있습니다. 

각 영역은 FrameLayout을 바탕으로 구성됩니다. FrameLayout은 레이아웃이 포함하는 뷰들을 왼쪽 가장 윗쪽을 기준으로 차곡차곡 쌓아주는 형식으로 배치합니다. 이러한 각 영역 안에 실질적으로 타이틀바에 표시되는 텍스트 및 액티비티 화면에 표시될 레이아웃 객체들이 들어가게 됩니다.




id가 content인 FrameLayout, 즉 컨텐트 영역의 하위에 우리가 작성했던 LinearLayout 및 TextView가 있는 것을 볼 수 있습니다. 이처럼, 간단해 보이는 화면도 사실은 이렇게 여러 구조를 가지고 있습니다.

fill_parent 속성이 부모 객체의 크기만큼의 크기를 갖는 것이니, 여기에서는 LinearLayout의 부모 객체, FrameLayout의 크기만큼의 크기를 갖고 이 FrameLayout은 화면에서 가로 세로로 타이틀바 및 상태 표시줄을 제외한 모든 화면을 차지하도록 되어있으므로 이 FrameLayout 하위의 객체들은 최대 이 레이아웃의 크기만큼을 차지할 수 있게 됩니다.

이제 자바 실제 코드를 통해 레이아웃을 구성해보도록 하겠습니다. 우선, 아래의 코드에서부터 시작합니다.

public class HelloAndroid extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
    }
}
우리가 구성할 화면은 LinearLayout 내부에 TextView가 들어가 있는 구조이므로, 우선 LinearLayout 객체를 생성해 주도록 합시다.

LinearLayout root = new LinearLayout(this);

그 다음은 LinearLayout이 어떻게 화면에 표시될 것인지를 지정해 주어야 합니다. 이러한 속성을 지정해 주기 위해 LinearLayout 클래스 내의 내부 클래스인 LayoutParams 객체를 사용하여 LinearLayout의 어떻게 화면에 표시될지 그 속성을 담고 있는 객체를 생성합니다.


LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
        		ViewGroup.LayoutParams.FILL_PARENT, 
        		ViewGroup.LayoutParams.FILL_PARENT, 
        		0.0F);


[API]
public LinearLayout.LayoutParams (int width, int height, float weight)

주어진 너비, 높이 및 weight를 갖는 새 레이아웃 속성을 생성합니다.


LinearLayout이 컨텐트 영역에 꽉 차게 나오도록 width 및 height에 모두 fill_parent 속성을 지정해줍니다. weight는 화면에 여러 뷰들이 표시될 때 해당 View가 화면에서 차지하는 비율로, 여기에서는 사용하지 않으므로 0을 넣어줍니다.

root.setLayoutParams(params);
root.setOrientation(LinearLayout.VERTICAL);

다음으로, LinearLayout의 레이아웃 속성으로 우리가 만든 앞서 만들어준 속성을 사용하기 위해 setLayoutParams() 메소드의 인자로 우리가 만들어준 레이아웃 속성(객체)을 넣어줍니다. 그리고, LinearLayout에서 View를 표시할 방향을 지정하기 위해 setOrientation() 메소드를 사용합니다. 여기에서는 Vertical, 레이아웃 내의 View들을 수직으로(위->아래) 표시하도록 하였습니다.

이제는 TextView를 LinearLayout에 추가할 차례입니다. TextView 객체를 생성한 후, setText()를 통해 TextView에 표시될 문자열을 지정합니다. 여기에서는 리소스에 저장되어있는 문자열을 불러왔습니다. 그 다음, LinearLayout과 마찬가지로 TextView의 레이아웃 속성을 지정합니다. 

TextView tv = new TextView(this);
tv.setText(R.string.hello);
LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(
        		ViewGroup.LayoutParams.WRAP_CONTENT, 
        		ViewGroup.LayoutParams.WRAP_CONTENT, 
        		0.0F);
tv.setLayoutParams(tvParams);

TextView 객체의 설정이 완료되었으므로, 이 TextView를 LinearLayout에 추가시켜줍니다. 그 후, LinearLayout을 액티비티의 화면으로 표시하도록 설정합니다.

root.addView(tv);
setContentView(root);

완성된 코드는 아래와 같습니다.

package com.androidhuman.HelloAndroid;

import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

public class HelloAndroid extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout root = new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
        		ViewGroup.LayoutParams.FILL_PARENT, 
        		ViewGroup.LayoutParams.FILL_PARENT, 
        		0.0F);
        
        root.setLayoutParams(params);
        root.setOrientation(LinearLayout.VERTICAL);
        
        TextView tv = new TextView(this);
        tv.setText(R.string.hello);
        LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(
        		ViewGroup.LayoutParams.WRAP_CONTENT, 
        		ViewGroup.LayoutParams.WRAP_CONTENT, 
        		0.0F);
        tv.setLayoutParams(tvParams);
        
        root.addView(tv);
        
        setContentView(root);
    }
}
이 코드를 실행시키면 우리가 저번에 레이아웃 파일을 통해 구성했던 화면과 동일한 화면이 표시되게 됩니다.

여기까지 자바 코드를 통해 액티비티의 화면을 구성하는 것에 대해 알아보았습니다. 사실, 레이아웃을 구성할 때 자바 코드를 통해 구성하는 것보다는 레이아웃 파일을 이용하여 구성하는 것이 일반적으로 더 효율적입니다. 하지만, 동적으로 화면을 구성하는 경우 (사용자의 입력에 반응하여 View에 요소들이 추가되어야 한다는 둥...) 자바 코드를 이용하여 레이아웃을 구성해야 합니다. 

이러한 특성 때문에 보통 기본 바탕이 되는 레이아웃은 레이아웃 파일을 통해, 그 이후는 자바 코드를 통해 레이아웃을 구성하게 됩니다. 따라서 레이아웃 파일을 이용하는 방법과 자바 코드를 이용하여 레이아웃을 구성하는 방법 모두 꼭 알고 있어야 합니다.