2010년 11월 21일 일요일

코드요소 - User Interface의 기본 개념

안드로이드 애플리케이션에서 사용자 인터페이스는 View와 ViewGroup 객체를 사용해서 만든다. 많은 뷰와 뷰 그룹이 있지만 이들은 모두 View 클래스의 서브클래스이다.
View객체는 사용자 인터페이스에 나타나는 기본 단위이다. View 클래스는 텍스트필드, 버튼 등 "widget"이라고 불리는 클래스들의 베이스 클래스이다. ViewGroup 클래스는 linear, tabular, relative 등 레이아웃 클래스들의 베이스 클래스이다.
View 객체는 레이아웃 파라메터나 화면의 사각영역 등의 속성을 저장하는 데이터 구조이다. 그리고 측정치, 레이아웃, 그리기, 포커스 변경, 스크롤, 제스쳐 등을 관리하고 처리한다. 또한 뷰는 사용자와의 상호작용 이벤트의 수신 지점이다.

뷰 계층도

안드로이드 플랫폼에서 개발자는 다음 다이어그램에서 보이는 것과 같은 ViewGroup과 View 노드의 계층도를 사용하여 액티비티의 UI를 정의한다. 이 뷰 계층도 내에 자원요소에서 설명한 레이아웃, 위젯들이 배치되게 된다.

이 계층도는 간단할 수도 있고 필요한 만큼 복잡하게 정의할 수도 있으며, 안드로이드의 미리 정의된 위젯들을 사용하여 만들 수도 있고, 자신이 제작한 뷰들을 이용하여 만들 수도 있다.
이 뷰 계층도를 화면에 나타나도록 하려면, 액티비티가 setContentView() 메쏘드를 이용하여 루트 노드 객체에 대한 레퍼런스를 전달해야 한다. 안드로이드 시스템은 이 레퍼런스를 받아서 뷰 트리를 갱신,측정,생성한다. 계층도상의 루트 노드가 차일드 노드 자신을 그리도록 요청한다.--바꾸어 말하면, 각 뷰그룹 노드는 각 차일드 노드들에게 자신을 그리도록 요청하는 책임을 맡고 있다. 차일드는 부모 내에서 크기나 위치를 요청할 수 있지만, 각 차일드가 어디에 얼마나 크게 그려질지는 부모 노드가 최종적으로 결정한다. 안드로이드는 레이아웃의 엘리먼트들을 순차적으로 파싱(계층 트리의 꼭대기에서부터)하여 뷰를 인스턴스화하고 부모 뷰에 추가한다. 이 그리기가 순차적으로 이루어지기 때문에, 위치가 겹치는 엘리먼트가 있을 경우, 마지막에 그려진 뷰가 이전에 그려진 뷰의 위에 그려지게 된다.

UI 이벤트

UI에 뷰/위젯을 배치했으면, 사용자와의 상호작용에 의해 액션을 취할 필요가 있다. UI 이벤트를 인식하려면 다음 둘 중 한 가지를 해야 한다:
• 이벤트 리스터를 정의하고 그것을 뷰에 등록한다. 대부분, 이 방식으로 이벤트를 취한다. View 클래스에는 On<something>Listener라는 이름의 네스티드 인터페이스 콜렉션이 있고, 각 인터페이스에는 On<somethind>()라는 콜백 메쏘드가 들어 있다. 예를 들면, View.OnClickListerer(View의 클릭을 처리), View.OnTouchListener, View.OnKeyListener 등이 있다. 따라서 뷰가 클릭되었을 때 알려주기를 원한다면, OnClickListener를 구현하고 그 리스너의 onClick() 콜백 메쏘드(여기서 클릭에 대한 반응 코드를 입력)를 정의하고, 그것을 View에 setOnClickListener()로 등록해야 한다.
• 그 View의 기존 콜백 메쏘드를 오버라이드한다. 자신만의 View 클래스를 구현하고 그 안에서 발생하는 특정 이벤트를 취하려면 이 방식으로 구현한다. 처리할 수 있는 이벤트의 예로는 onTouchEvent(),onTrackballEvent(),onKeyDown() 등이 있다.

메뉴

메뉴는 어플리케이션의 UI에서 중요한 요소 중 하나이다. 메뉴를 통해 어플리케이션의 기능과 설정을 표시하는 안정적인 인터페이스를 만들 수 있다. 가장 일반적은 어플리케이션 메뉴는 기기에 있는 MENU 키를 누름으로써 나타나는 메뉴이다. 하지만, 사용자가 항목을 꾹 눌렀을 때 나타나는 컨텍스트 메뉴를 설정할 수도 있다.
메뉴 또한 뷰 계층도를 사용하여 구조화되어 있지만, 이 구조를 개발자가 정의하지는 않는다. 대신에, 개발자는 액티비티의 onCreateOptionsMenu() 나 onCreateContextMenu() 콜백 메쏘드를 통해 정의하고 메뉴에 포함시킬 항목들을 선언한다. 그러면 안드로이드 시스템이 필요한 때에 필요한 뷰 계층도를 자동으로 그리고 각 메뉴 항목을 표시한다.
메뉴는 자신의 이벤트를 처리하기 때문에 메뉴의 항목에 대해 이벤트 리스터를 등록할 필요가 없다. 메뉴의 항목이 선택되면, 프레임웍이 자동으로 onOptionsItemSelected() 나 onContextItemSelected() 메쏘드를 호출한다.
그리고 어플리케이션 레이아웃과 똑같이, 메뉴 항목을 XML 파일에 선언할 수도 있다.

어댑터

하드코딩된 정보를 표시하는 것이 아니라, 외부 데이터 소스에서 동적인 정보를 뷰 그룹에 표시하고 싶을 때가 있다. 이런 작업을 하려면 뷰 그룹으로 AdapterView를 사용하고 각 차일드 View는 그 Adapter로부터 데이터를 초기화하고 나타내도록 한다.
AdapterView 객체는 특정 Adapter 객체에 기반하여 그 차일드 뷰를 결정하는 ViewGroup을 구현한 것이다. Adapter는 데이터소스와 AdapterView(데이터를 화면에 표시) 사이의 통로 역할을 한다. Adapter 클래스를 구현한 것은 유형별로 여러 가지가 있는데, 예를 들면 Cursor로부터 데이터베이스 데이터를 읽어오는 CursorAdapter, 임의의 배열로부터 데이터를 읽어오는 ArrayAdapter 등이 있다.

스타일 및 테마

표준 위젯의 모양이 만족스럽지 않을 경우가 있다. 이것을 개선하기 위해, 자신의 스타일과 테마를 만들어 적용할 수 있다.
• 스타일은 레이아웃 상의 개별적인 엘리먼트에 개별적으로 적용시킬 수 있는 하나 이상의 구성 가능한 속성들이다. 예를 들어, 문자 크기와 색상을 지정하는 스타일을 정의하고, 그것을 특정 뷰 엘리먼트에 적용할 수 있다.
• 테마는 어플리케이션의 모든 액티비티나 특정 액티비티에 적용시킬 수 있는 하나 이상의 구성 가능한 속성들이다. 예를 들어, 윈도우 프레임과 패널 배경에 대한 색상 및 문자 크기와 색상을 지정한 테마를 정의할 수 있다. 그리고 이 테마를 특정 액티비티나 전체 어플리케이션에 적용되도록 할 수 있다.

스타일과 테마는 자원 중 하나이다. 안드로이드는 개발자가 적용시킬 수 있는 여러 스타일과 테마를 제공하며, 개발자만의 임의 스타일 및 테마 자원을 정의해서 사용할 수도 있다.

2010년 11월 15일 월요일

코드요소

지난호까지 안드로이드의 자원요소를 알아봤고, 지금부터는 코드요소에 대해 연재하려고 합니다.

자원요소를 뼈대라고 한다면 코드요소는 살과 기능들이라고 할 수 있고, 자원요소를 정적인 부분이라고 하면, 코드요소는 동적인 부분이라고 할 수 있습니다. 그만큼 자원요소는 좀 재미 없고 지루한 느낌이 들고, 코드요소는 재미가 좀 나죠.. 하지만 코드요소를 또 열심히 하다 보면, 나중엔 또다시 자원요소를 들여다봐야 하는 일이 있는 만큼 자원요소는 골격의 개념으로서 중요한 부분을 차지합니다.

간단한 어플인 경우 자원요소 없이 코드요소만으로 안드로이드 프로그램을 작성하는 일이 가능하며 그만큼 안드로이드는 유연한 개발환경을 제공합니다. 하지만 화면이 좀 늘어나면 코드요소만으로 화면을 제어하기가 매우 어려우며 따라서 자원요소와 코드요소를 적절히 배합하여 어플을 만드는 것이 바람직합니다.

코드요소는 Java 코드로 작성하며, 안드로이드 자체가 Java 위의 어플리케이션 프레임워크로 작성되어 있기 때문에 기본적인 Java 개념에 대한 이해를 갖고 시작하는 것이 좋습니다. Java를 모르는 상태로 안드로이드를 배우려 한다면 사상누각이라는 것이 어떤 것인가를 실감할 수 있을 것이라 생각됩니다. ^^

코드요소에 관해 연재하는 순서는
- User Interface의 기본개념
- 메뉴 설정
- 화면 구성
- 자원에 접근
- 컨텐츠 제공자
- 알림 기능
- 어댑터
- 서비스
의 순서로 다룰 예정입니다.

2010년 11월 7일 일요일

자원요소 - Android Manifest.xml

모든 어플리케이션은 루트 디렉토리에 AndroidManifest.xml 파일을 갖고 있어야 한다. 이 파일은 어플리케이션에 대한 기본적인 정보를 안드로이드 시스템에 제공함으로써, 시스템이 어플리케이션 코드를 실행하기 전에 필요한 정보를 갖고 있도록 한다. 이 파일이 수행하는 주요한 일은 다음과 같다:

• 어플리케이션의 자바 패키지 이름을 지정한다. 이 패키지 이름은 어플리케이션의 고유한 식별자로써 작용한다.
• 어플리케이션의 컴포넌트들에 대한 사항을 지정한다-어플리케이션을 구성하는 액티비티, 서비스, 브로드캐스트 리시버, 컨텐트 프로바이더 등을 지정한다. 그리고 각 컴포넌트를 실행시키고 외부에 알리는(예를 들어, 어떤 인텐트 메시지를 처리할 수 있는지) 클래스의 이름을 지정한다. 이렇게 지정함으로써 안드로이드 시스템이 어떤 컴포넌트를 어떤 조건 하에서 실행시킬지 알 수 있도록 한다.
• 어떤 프로세스가 어플리케이션들의 작동을 주관하는지 결정한다.
• 어플리케이션이 다른 API의 보호된 부분에 액세스하고 다른 어플리케이션들과 상호작용하기 위해 가지고 있어야 하는 퍼미션을 선언한다.
• 위와 반대로 다른 어플리케이션이 이 어플리케이션과 상호작용하기 위해 필요한 퍼미션을 정의한다.
• 어플리케이션이 실행될 때 프로필 및 기타 정보를 제공하는 도구 클래스를 선언한다. 이 선언은 어플리케이션이 개발 및 테스트될 때만 존재하며, 어플리케이션이 발매되면 제거된다.
• 어플리케이션에 요구되는 최소 API 레벨을 지정한다.
• 어플리케이션과 연결되어야 하는 라이브러리를 지정한다.

* AndroidManifest 파일의 구조 틀

<?xml version="1.0" encoding="utf-8"?> 

<manifest> 

    <uses-permission /> 
    <permission /> 
    <permission-tree /> 
    <permission-group /> 
    <instrumentation /> 
    <uses-sdk /> 
    <uses-configuration />   
    <uses-feature />   
    <supports-screens />   

    <application> 

        <activity> 
            <intent-filter> 
                <action /> 
                <category /> 
                <data /> 
            </intent-filter> 
            <meta-data /> 
        </activity> 

        <activity-alias> 
            <intent-filter> . . . </intent-filter> 
            <meta-data /> 
        </activity-alias> 

        <service> 
            <intent-filter> . . . </intent-filter> 
            <meta-data/> 
        </service> 

        <receiver> 
            <intent-filter> . . . </intent-filter> 
            <meta-data /> 
        </receiver> 

        <provider> 
            <grant-uri-permission /> 
            <path-permission /> 
            <meta-data /> 
        </provider> 

        <uses-library /> 

    </application> 

</manifest>


ex) NotePad 예의 AndroidManifest.xml 파일

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          package="com.example.android.notepad"> 
    <application android:icon="@drawable/app_notes" 
                 android:label="@string/app_name" > 

        <provider android:name="NotePadProvider" 
                  android:authorities="com.google.provider.NotePad" /> 

        <activity android:name="NotesList" android:label="@string/title_notes_list"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
            <intent-filter> 
                <action android:name="android.intent.action.VIEW" /> 
                <action android:name="android.intent.action.EDIT" /> 
                <action android:name="android.intent.action.PICK" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> 
            </intent-filter> 
            <intent-filter> 
                <action android:name="android.intent.action.GET_CONTENT" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> 
            </intent-filter> 
        </activity> 
         
        <activity android:name="NoteEditor" 
                  android:theme="@android:style/Theme.Light" 
                  android:label="@string/title_note" > 
            <intent-filter android:label="@string/resolve_edit"> 
                <action android:name="android.intent.action.VIEW" /> 
                <action android:name="android.intent.action.EDIT" /> 
                <action android:name="com.android.notepad.action.EDIT_NOTE" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> 
            </intent-filter> 
            <intent-filter> 
                <action android:name="android.intent.action.INSERT" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> 
            </intent-filter> 
        </activity> 
         
        <activity android:name="TitleEditor"  
                  android:label="@string/title_edit_title" 
                  android:theme="@android:style/Theme.Dialog"> 
            <intent-filter android:label="@string/resolve_title"> 
                <action android:name="com.android.notepad.action.EDIT_TITLE" /> 
                <category android:name="android.intent.category.DEFAULT" /> 
                <category android:name="android.intent.category.ALTERNATIVE" /> 
                <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> 
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> 
            </intent-filter> 
        </activity> 
         
    </application> 
</manifest>


Intent의 개념

안드로이드 애플이케이션의 세 개 핵심 컴포넌트-액티비티,서비스,브로드캐스트 리시버-는 인텐트라는 메시지를 통해 실행된다. 인텐트 메시징은 같거나 다른 애플리케이션에 있는 컴포넌트들간의 런타임 바인딩을 제공하는 장치이다.
Intent 클래스의 객체인 intent 자체는 수행할 오퍼레이션의 추상적인 설명을 담고 있는 수동적인 데이터 구조이다.

HTTP의 동사(GET,POST 등)와 자원(URL)의 구조처럼, 안드로이드의 인텐트도 Action + Context 의 형태를 갖는다. 안드로이드가 훨씬 더 많은 action과 context component를 갖고 있지만 그 개념을 똑같다.
웹 브라우저가 동사+URL 구조를 어떻게 처리해야 하는지 아는 것처럼, 안드로이드도 어떻게 주어진 인텐트를 처리할 액티비티를 찾거나  다른 프로그램의 로직을 찾는지 알고 있다.

각 컴포넌트에 대해 인텐트를 전달하는 메카니즘은 다음과 같다:
•액티비티를 새로 시작하거나 기존 액티비티가 새로운 일을 하도록 할 경우, Context.startActivity() 나 Activity.startActivityForResult() 에 인텐트 객체를 전달한다.
•서비스를 시작하거나 실행중인 서비스에 새로운 명령을 전달할 때, Context.startService()에 인텐트 객체를 전달한다. 유사한 형태로, 호출하는 컴포넌트와 대상 서비스간에 연결을 만들 경우, Context.bindService()에 인텐트 객체를 전달한다. 만약 서비스가 실행 중이 아닐 경우 그 서비스를 시작시킬 수도 있다.
•브로드캐스트 메쏘드(Context.sendBroadcast(), Context.sendOrderedBroadcast(), Context.sendStickyBroadcast() 등과 같은)에 전달된 인텐트 객체는 모든 관심 있는 브로드캐스트 리시버에게 전달된다. 대부분의 브로드캐스트는 시스템 코드에서 시작된다.

대상컴포넌트가 지정되어 있는 Explicit intent와 지정된 대상 컴포넌트가 없는 Implicit intent로 구분할 수 있다.

Intent Filter

대상 컴포넌트를 지정하지 않은 인텐트의 경우, 대상 컴포넌트가 될 가능성이 있는 컴포넌트(잠재 컴포넌트)에 대해 실행 대상이 되는지 테스트해야 한다.

이 테스트의 기준으로 정해 놓은 것이 intent filter이다. 필터에는 그 컴포넌트가 수행하는 일이나 처리할 수 있는 인텐트 등이 명시된다. 대상 컴포넌트가 되는지를 테스트할 때는 인텐트 필터의 다음 세 가지 항목을 점검한다:
action, data (both URI and data type), category

extras 나 flags는 아무 역할도 하지 않는다.

인텐트 필터는 IntentFilter 클래스의 인스턴스이다. 하지만, 그 컴포넌트를 실행하기 전에 안드로이드 시스템이 그 능력에 대해 알고 있어야 하기 때문에, 인텐트 필터는 보통 Java 코드에 설정되지 않고 애플리케이션의 매니페이스 파일(AndroidManifest.xml)에 <intent-filter> 요소로 정의된다. (한 가지 예외는 브로드캐스트 리시버인데 이것은 Context.registerReceiver()를 호출함으로써 동적으로 등록되며, 그러면 바로 IntentFilter 객체로 생성된다.)
필터는 인텐트 객체의 action, data, category 필드에 해당하는 필드를 갖고 있다. implicit intent는 이 세 영역에 대해 테스트된다. 필터를 정의한 컴포넌트가 인텐트를 갖고 있는 컴포넌트에게 전달되려면 이 세 가지 테스트를 통과해야 한다.

2010년 11월 1일 월요일

자원요소-위젯

화면에 배치하는 사용자 인터페이스 요소로서 Java의 프레임, 컨트롤 등과 유사하다.
레이아웃 내에 위젯들이 배치되는 형태로 대부분의 안드로이드 프로그램이 구성되며, 이들 요소가 단말기 화면에 나타난다.

TextView

화면에 텍스트를 그린다.

속성은 다음과 같다.
id 텍스트뷰의 이름으로서, 코드요소에서 텍스트뷰를 지칭할 때 이 태그에 지정된 이름을 사용한다.
text 텍스트뷰에 표시될 글자
layout_width
layout_height
lines 높이를 줄 수로 지정
ems 글꼴의 크기와 무관하게 텍스트뷰에 표시될 글자의 수를 지정
autoLink 링크형태로 표시. web,email,phone,map 사용 가능.

EditText

TextView에서 파생된 클래스이다.
사용자로부터 텍스트를 입력받을 수 있다.
TextView의 모든 속성을 상속한다.

유용한 속성들은 다음과 같다.
• hint 사용자가 입력을 시작하기 전에 표시되고 입력을 시작하면 사라진다.
• completionHint: 자동완성기능
• completionThreshold: 자동완성기능. 몇 개 글자가 표시되었을 때 목록을 표시할 것인지 지정.

Button
화면에 버튼 형태로 표시되는 컨트롤로, 클릭 후 액션을 수행하도록 하는데 기본적으로 사용된다.

CheckBox
체크 컨트롤을 보여줌. Java의 체크박스와 유사.

ex) 기본 XML 파일 및 Java 파일

<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This checkbox is: unchecked" />


public class CheckBoxDemo extends Activity
implements CompoundButton.OnCheckedChangeListener {
CheckBox cb;
@Override
public void onCreate(Bundle icicle) {
  super.onCreate(icicle);
  setContentView(R.layout.main);
  cb=(CheckBox)findViewById(R.id.check);
  cb.setOnCheckedChangeListener(this);
}
public void onCheckedChanged(CompoundButton buttonView,
  boolean isChecked) {
  if (isChecked) {
  cb.setText("This checkbox is: checked");
  }
  else {
  cb.setText("This checkbox is: unchecked");
  }
}
}

RadioButton
체크 컨트롤을 보여줌. Java의 체크박스와 유사.

ex) 라디오 그룹 정의 XML 코드

<?xml version="1.0" encoding="utf-8"?>
<RadioGroup
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RadioButton android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rock" />
<RadioButton android:id="@+id/radio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scissors" />
<RadioButton android:id="@+id/radio3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Paper" />
</RadioGroup>

Spinner
지정된 여러 항목 중에서 하나를 선택하도록 한다.

ex) ArrayAdapter를 이용하여 Spinner에 데이터 표시하기

//spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
 
    <TextView
android:id="@+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Spinner android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
/>

</LinearLayout>

//SpinnerDemo.java
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView;

public class SpinnerDemo extends Activity implements AdapterView.OnItemSelectedListener {
TextView selection;
String[] items={"lorem", "ipsum", "dolor", "sit", "amet",
"consectetuer", "adipiscing", "elit", "morbi", "vel",
"ligula", "vitae", "arcu", "aliquet", "mollis",
"etiam", "vel", "erat", "placerat", "ante",
"porttitor", "sodales", "pellentesque", "augue", "purus"};

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.spinner);

selection=(TextView)findViewById(R.id.selection);
Spinner spin = (Spinner) findViewById(R.id.spinner);

spin.setOnItemSelectedListener(this);
ArrayAdapter<String> aa=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,items);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(aa);
}
public void onItemSelected(AdapterView parent, View v,
int position, long id) {
selection.setText(items[position]);
}
public void onNothingSelected(AdapterView parent) {
selection.setText("");
}
}



ToggleButton
On/Off 스위치

DatePicker/TimePicker
날자/시간 선택

ProgressBar
진행상태 표시

SeekBar
사용자지정 진행상태 표시

RatingBar
별을 이용한 등급표시

Chronometer
시간흐름 표시

AnalogClock
아날로그 시계 표시

DigitalClock
디지털 시계 표시

ImageView/ImageButton

TextView, Button의 이미지용 컨트롤이라고 보면 된다.
xml에서 참조할 때는 android:src 속성을 사용한다.

ex) ImageView를 적용한 XML 파일

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/icon"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:src="@drawable/molecule"
/>

2010년 10월 28일 목요일

자원요소-레이아웃

뷰에 배치된 위젯이 화면에 나타나는 방식을 지정한다.

엄밀히 말하면 레이이웃은 사용자 UI를 Activity 클래스에 나타내는 아키텍처이다. 배치 구조를 정의하고 사용자에게 나타내는 모든 엘리먼트를 담고 있다. 레이아웃은 두 가지 방법으로 정의할 수 있다:
• XML 파일에서 UI 요소를 정의한다. 위젯이나 레이아웃 등과 같은 View 클래스 또는 그 서브클래스를 이용하여 정의하는 방법이다.
• 실행시에 레이아웃 엘리먼트를 인스턴스화한다. 애플리케이션에서는 프로그램으로 View 나 ViewGroup 객체를 생성(및 그 속성을 정의)할 수 있다.

안드로이드 프레임웍은 UI를 구성하는데 이 중 한 가지나 두 가지를 합한 방식 모두를 지원한다. 예를 들어, 애플리케이션의 스크린 엘리먼트 등의 디폴트 레이아웃은 XML에 정의하고, 그 객체의 상태를 변경시키거나 객체를 추가하는 일은 코드 부분에 넣는 것어서 실행시에 나타나게 하는 것이 가능하다.

주요 뷰 그룹(뷰그룹과 레이아웃 클래스는 유사 개념)

주요 뷰 그룹 요약-다음에 열거하는 뷰 그룹 객체는 모두 자식UI엘리먼트를 갖고 있다. 어떤 것은 화면에 나타나는 UI에 대한 형태를 지정하고, 어떤 것은 자식 뷰들의 배치를 관리하는 구조만을 결정한다.

FrameLayout: 한 개 객체만을 보여주는 뷰 프레임을 설정.
Gallery: 한정된 리스트 내의 이미지를 좌우로 스크롤해서 보여주는 프레임.
GridView: m개 칼럼, n개 로우를 스크롤 가능한 그리드로 보여줌.
LinearLayout: 자식 뷰들을 하나의 수평 또는 수직 화면으로 구성하는 레이아웃. 이 레이아웃은 화면 크기보다 윈도우의 크기가 크면 스크롤바를 생성한다.
ListView: 상하 스크롤 가능한 목록을 만들어준다.
RelativeLayout: 자식 객체의 상호 관계(B객체의 좌측에 A객체 배치)  또는 자식과 부보의 관계(부모의 위에 배치)형태로 뷰의 위치를 지정하도록 한다.
ScrollView: 목록이 아닌 객체에 대해서 상하 스크롤바가 생기도록 한다.
Spinner: 지정된 목록의 한 개 항목을 하나의 텍스트박스 형태로 표시한다. 수평 혹은 수직으로 스크롤할 수 있는 리스트박스와 유사하다.
SurfaceView: 그리기 화면에 대한 직접 액세스를 제공한다. 화면의 위에 자식 뷰를 얹을 수는 있지만, 위젯보다는 그림 픽셀을 그릴 필요가 있을 때 사용하도록 하는 목적으로 제공되는 기능이다.
TabHost: 탭 선택 형태를 제공하는 뷰그룹으로 탭을 클릭하면 애플리케이션이 다른 화면으로 변경되도록 하는 기능을 제공한다.
TableLayout: 지정된 행과 열을 구성하도록 하는 테이블 형태 레이아웃으로, 각 셀은 각각의 위젯을 가질 수 있다. 행의 크기를 가장 큰 셀의 크기에 맞춰진다. 셀 경계선은 나타나지 않는다.
ViewFlipper: 한 개 텍스트박스 안에 한 번에 하나의 항목을 보여주는 목록을 가진 객체. 슬라이드 쇼처럼 지정된 시간 간격마다 스와핑이 되도록 설정할 수 있다.
ViewSwitcher: ViewFlipper와 동일.

FrameLayout
가장 단순한 형태의 레이아웃 객체이다. 기본적으로 스크린상의 빈 공간이며 나중에 하나의 객체로 화면을 채울 수 있다. 이 프레임 레아이웃의 모든 차일드 엘리먼트는 화면의 좌상단에 고정된다; 다른 위치를 지정할 수는 없다. 차일드 뷰들은 이전 뷰 위에 차례로 그려진다.

LinearLayout

LinearLayout은 모든 자식뷰들을 한 방향으로 배치한다. 하지만 기본 방향이나 여백을 다음 다섯 가지 프로퍼티를 통해 지정할 수 있다.
- orientation: android:orientation 프로퍼티를 horizontal이나 vertical 로 지정할 수 있다. 또는 코드에서 setOrientation() 메쏘드에서 HORIZONTAL/VERTICAL로 지정할 수 있다.
- fill model: pixel 수, wrap_content, fill_parent 등으로 설정.
- weight: widget의 중요도를 1,2 등으로 줄 수 있다.
- gravity:android:layout_gravity 프로퍼티를 left, center_horizontal, right로 줄 수 있다.
- padding:android:padding으로 전체 패딩을 지정한다. 하지만 각 영역별로 지정하려면 android:paddingLeft, android:paddingRight, android:paddingTop, android:paddingBottom을 사용한다.

ex) 텍스트뷰, 버튼을 배치한 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>

TableLayout
TableLayout은 그 자식들을 행과 열로 배치한다. 하지만 행,열, 또는 셀에 대한 경계선은 보여주지 않는다. 테이블은 빈 셀을 가질 수 있지만, HTML에서처럼 칼럼 영역을 넘어설 수는 없다.

ex) 2x2 테이블 레이아웃
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:stretchColumns="1">
    <TableRow>
        <TextView
            android:text="@string/table_layout_4_open"
            android:padding="3dip" />
        <TextView
            android:text="@string/table_layout_4_open_shortcut"
            android:gravity="right"
            android:padding="3dip" />
    </TableRow>

    <TableRow>
        <TextView
            android:text="@string/table_layout_4_save"
            android:padding="3dip" />
        <TextView
            android:text="@string/table_layout_4_save_shortcut"
            android:gravity="right"
            android:padding="3dip" />
    </TableRow>
</TableLayout>

RelativeLayout
RelativeLayout 은 자식뷰가 자신의 위치를 부모 또는 다른 뷰에 대한 상대적 위치로 지정한다. 그래서 두 엘리먼트를 오른쪽으로 또는 하나가 다른 뷰의 아래에 있도록, 화면의 중앙, 중앙 왼쪽 등으로 지정할 수 있다. 엘리먼트는 주어진 순서에 따라 그려지므로, 첫 번째 엘리먼트가 화면의 중앙에 그려진다면, 다른 엘리먼트는 중앙 엘리먼트에 대해 배치되므로 화면 중앙에 대한 상대적 위치로 그려진다. 또한, 이런 순서 때문에, 이 레이아웃을 정하는데 XML을 사용한다면, 참조할 엘리먼트는 (다른 뷰 객체를 배치하기 위해) 참조ID로 다른 뷰를 참조하기 전에 미리 XML 파일에 나타나 있어야 한다.
정의된 RelativeLayout의 파라메터는: width, height, below, alignTop, toLeft, padding[Bottom|Left|Right|Top], margin[Bottom|Left|Right|Top] 등이 있다.



ex) 텍스트뷰, 버튼을 배치한 RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/blue"
                android:padding="10px" >

    <TextView android:id="@+id/label"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Type here:" />

    <EditText android:id="@+id/entry"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:background="@android:drawable/editbox_background"
              android:layout_below="@id/label" />

    <Button android:id="@+id/ok"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/entry"
            android:layout_alignParentRight="true"
            android:layout_marginLeft="10px"
            android:text="OK" />

    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/ok"
            android:layout_alignTop="@id/ok"
            android:text="Cancel" />
</RelativeLayout>



AbsoluteLayout
절대좌표 형태로 뷰의 위치를 지정하는 방식이다. 아주 쉽게 화면에 뷰를 배치할 수 있지만, 안드로이드 단말기의 해상도가 워낙 다양하므로 가급적 사용하지 않는 것이 좋다.
며칠 전 Google에서 AbsoluteLayout 엘리먼트를 deprecate 하겠다고 밝혔다. 즉, 이후 SDK 버전에서는 이 레이아웃을 사용할 수 없다는 의미이다. 역시, 사용하지 않는 것이 좋겠다.

TabHost
탭메뉴 형태의 화면을 만들 때 TabHost 를 이용한다.

ex) 탭별 화면을 정적으로 구성할 경우의 TabHost
<?xml version="1.0" encoding="utf-8"?>
<TabHost
   xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
            <TextView
                android:id="@+id/textview1"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="this is a tab" />
            <TextView
                android:id="@+id/textview2"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="this is another tab" />
            <TextView
                android:id="@+id/textview3"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="this is a third tab" />
        </FrameLayout>
    </LinearLayout>
</TabHost>


ex) 탭별 화면을 동적으로 구성할 경우의 TabHost
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp" />
    </LinearLayout>
</TabHost>

* FrameLayout 내에 TextView 가 없으므로 화면을 나타내려면 코드 요소에서 intent를 사용하여 나타나도록 해야 한다.

ScrollView
ex) 스크롤뷰 설정 기본 예
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="0">
<TableRow>
<View
android:layout_height="80px"
android:background="#000000"/>
<TextView android:text="#000000"
android:paddingLeft="4px"
android:layout_gravity="center_vertical" />
</TableRow>
<TableRow>
<View
android:layout_height="80px"
android:background="#440000" />
<TextView android:text="#440000"
android:paddingLeft="4px"
android:layout_gravity="center_vertical" />
</TableRow>
<TableRow>
<View
android:layout_height="80px"
android:background="#884400" />
<TextView android:text="#884400"
android:paddingLeft="4px"
android:layout_gravity="center_vertical" />
</TableRow>
<TableRow>
<View
android:layout_height="80px"
android:background="#aa8844" />
<TextView android:text="#aa8844"
android:paddingLeft="4px"
android:layout_gravity="center_vertical" />
</TableRow>
<TableRow>
<View
android:layout_height="80px"
android:background="#ffaa88" />
<TextView android:text="#ffaa88"
android:layout_gravity="center_vertical" />
</TableRow>
<TableRow>
<View
android:layout_height="80px"
android:background="#ffffff" />
<TextView android:text="#ffffff"
android:paddingLeft="4px"
android:layout_gravity="center_vertical" />
</TableRow>
</TableLayout>
</ScrollView>

GridView
ex) 그리드뷰 기본 설정 예
<?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:id="@+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<GridView
android:id="@+id/grid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:verticalSpacing="35px"
android:horizontalSpacing="5px"
android:numColumns="auto_fit"
android:columnWidth="100px"
android:stretchMode="columnWidth"
android:gravity="center"
/>
</LinearLayout>


import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.AdapterView;

public class GridDemo extends Activity
implements AdapterView.OnItemSelectedListener {
TextView selection;
String[] items={"lorem", "ipsum", "dolor", "sit", "amet",
"consectetuer", "adipiscing", "elit", "morbi", "vel",
"ligula", "vitae", "arcu", "aliquet", "mollis",
"etiam", "vel", "erat", "placerat", "ante",
"porttitor", "sodales", "pellentesque", "augue", "purus"};

public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.grid);
selection=(TextView)findViewById(R.id.selection);
GridView g=(GridView) findViewById(R.id.grid);
g.setAdapter(new FunnyLookingAdapter(this,
android.R.layout.simple_list_item_1,items));
g.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView parent, View v, int position, long id) {
selection.setText(items[position]);
}
public void onNothingSelected(AdapterView parent) {
selection.setText("");
}
private class FunnyLookingAdapter extends ArrayAdapter {
Context ctxt;
FunnyLookingAdapter(Context ctxt, int resource, String[] items) {
super(ctxt, resource, items);
this.ctxt=ctxt;
}
public View getView(int position, View convertView, ViewGroup parent) {
TextView label=(TextView)convertView;
if (convertView==null) {
convertView=new TextView(ctxt);
label=(TextView)convertView;
}
label.setText(items[position]);
return(convertView);
}
}
}


뷰그룹 객체의 속성 지정
Attribute

모든 View와 ViewGroup 객체는 자신의 다양한 XML 속성을 지원한다. 어떤 속성은 특정 View 객체에 한정되지만(예를 들어 TextView 는 textSize 속성을 지원), 이들 속성은 View 객체에서 상속된 것이고, 따라서 모든 View 객체의 공통속성들이 있다. 그리고, "layout parameter" 로 간주되는 속성이 있으며, 이것은 ViewGroup 객체에 의해 정의된 View 객체의 레이아웃 상의 특정 위치를 지정하는 속성이다.

ID: 모든 뷰 객체는 xml 트리상에서 자신을 고유하게 식별하는 정수값 ID를 가질수 있다. XML 태그 안의 ID의 신택스는 다음과 같다:
android:id="@+id/my_button"
문자열 시작 위치에 있는 @ 기호는 XML 해석기가 나머지 DI 문자열을 해석하고 그것을 ID 자원으로 가져가야 한다는 의미이다. + 기호는 이것이 새로운 자원이며 따라서 애플리케이션의 리소스(R.java 파일)에 생성하고 추가해야 한다는 의미이다. 그 외에도 안드로이드 프레임웍이 제공하는 많은 ID 자원들이 있다. 안드로이드 자원 ID를 참조할 때는 더하기 기호를 사용할 필요가 없고, 대신에 다음과 같이 안드로이드 패키지 네임스페이스를 추가해야 한다:
android:id="@android:id/empty"
안드로이드 패키지 네임스페이스를 사용함으로써, 로컬 리소스 클래스가 아닌 android.R 리소스 클래스를 참조하게 된다.
뷰를 생성하고 애플리케이션에서 그것을 참조하려면 통상적인 패턴은:
1. 레이아웃 파일에 뷰/위젯을 정의하고 거기에 고유한 ID를 할당한다:
2. <Button android:id="@+id/my_button"
3.        android:layout_width="wrap_content"
4.        android:layout_height="wrap_content"
        android:text="@string/my_button_text"/>
5. 다음에 뷰 객체의 인스턴스를 생성하고 레이아웃에서 그것을 찾아낸다(보통 onCreate() method 안에서 코딩):
Button myButton = (Button) findViewById(R.id.my_button);
ID는 전체 XML 트리 안에서 고유할 필요는 없지만, 검색하고 있는 트리 안(이것이 전체 트리가 될 수 있으므로, 가능하다면 완전히 고유하도록 정하는 것이 좋다)에서는 고유해야 한다.

Layout Parameters: layout_something 형태의 XML 레이아웃 속성이 View에 대한 레이아웃 파라메터이다. 모든 ViewGroup 클래스는 ViewGroup.LayoutParams 를 상속하는 네스티드 클래스를 구현한다. 이 서브클래스에는 각 차일드 뷰의 크기와 위치를 정의하는 속성이 들어 있다. 각 부모 뷰 그룹은 각 자식 뷰의 레이아웃 파라메터를 결정한다.(레이아웃 파라메터 상속 그림 참조)
모든 LayoutParams 서브클래스는 값을 설정하는 자신의 신택스를 갖고 있다. 각 차일드 엘리먼트는 부모에게 맞는 LayoutParams를 정의해야 한다. 하지만 이것은 자신의 차일드를 위해 다른 LayoutParams로 정의할 수도 있다.

모든 뷰 그룹에는 layout_width and layout_height이 포함되어 있고, 각 뷰는 이것을 정의해야 한다. 많은 LayoutParams에는 선택사항인 margin과 border도 포함되어 있다. 정확한 width, height 수치를 지정할 수도 있다. 부모와의 상대적 크기인 wrap_content, fill_parent 로 지정하는 것을 더 권장한다.

ex) LayoutParams 속성 지정
<?xml version="1.0" encoding="utf-8"?>
<!-- res/main_screen.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"    // The object's own orientation property
              android:padding="4"               // Inherited View property
              android:gravity="center"          // The object's own property
              android:layout_width="fill_parent"  // Parent object's LinearLayout.LayoutParams.width
              android:layout_height="fill_parent"> // Parent object's LinearLayout.LayoutParams.height

   <TextView android:layout_width="fill_parent"   // TextView.LayoutParams.width
             android:layout_height="wrap_content" // TextView.LayoutParams.height
             android:layout_weight="0"            // TextView.LayoutParams.weight
             android:paddingBottom="4"            // TextView.paddingBottom
             android:text="@string/redirect_getter"/> // TextView.text

   <EditText android:id="@+id/text"
             android:layout_width="fill_parent"   // EditText.LayoutParams.width
             android:layout_height="wrap_content" // EditText.LayoutParams.height
             android:layout_weight="0"            // EditText.LinearLayoutParams.weight
             android:paddingBottom="4">           // EditText.paddingBottom
       <requestFocus />
   </EditText>

   <Button android:id="@+id/apply"
           android:layout_width="wrap_content"  // Button.LayoutParams.width
           android:layout_height="wrap_content" // Button.LayoutParams.height
           android:text="@string/apply" />      // TextView.text
</LinearLayout>

Position

뷰의 표시영역은 사각형이다. 뷰는 왼쪽 최상단을 나타내는 로케이션과, 넓이와 높이를 나타내느 디멘전을 갖고 있다. 로케이션과 디멘전의 단위는 픽셀이다.
getLeft와 getTop 메쏘드를 사용하여 뷰의 위치를 알아낼 수 있다. getLeft는 사각형의 왼쪽 위치 즉 X좌표를 돌려주고, getTop은 사각형의 최상단, 즉 Y좌표를 돌려준다. 이들 메쏘드는 모두 부모 뷰에 대한 상대적 위치로 좌표를 돌려준다. 예를 들어 getLeft()가 20으로 나오면, 이것은 그 뷰가 부모 뷰의 왼쪽 끝에서 오른쪽으로 20 픽셀 이동한 위치에 있다는 의미이다.
이외에도 getRight, getBottom 등 유용한 메쏘드들이 있다. 사용예로는, getRight() 를 쓰면 getLeft() + getWidth() 를 계산한 것과 같은 결과를 받는다.

Size, Padding, Margin

뷰의 크기는 넓이와 높이로 표현된다. 실제로 뷰는 넓이와 높이 값의 두 쌍을 갖고 있다.
첫번째 쌍은 측정 넓이와 높이라 한다. 이 디멘전은 그 뷰가 부모 뷰 안에서 얼마나 크게 나타날지를 정한다. 이 측정 디멘전은 getMeasuredWidth() 와 getMeasuredHeight()로 구할 수 있다.
두 번째 쌍은 단순한 넓이와 높이 또는 드로잉 넓이와 드로잉 높이이다. 이 디멘전은 화면에서의 실제 뷰의 크기를 정의한다. 이 값은 측정 넓이, 높이와 다를 수 있다. 이 값은 getWidth() 와 getHeight() 메쏘드로 구할 수 있다.
디멘전을 측정하기 위해 뷰는 패딩을 고려한다. 패딩은 뷰의 왼쪽,상단,우측,하단 부분에 대한 픽셀값으로 표현된다. 패딩은 뷰의 내용을 특정 픽셀만큼 떨어져서 표현할 때 사용할 수 있다. 예를 들어, 왼쪽 패딩 2 를 하면 뷰의 내용이 왼쪽 끝에서 2 픽셀만큼 떨어져서 나타난다. 패딩을 설정하려면  setPadding(int, int, int, int) 메쏘드를 이용하고, getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() 메쏘드로 조회할 수 있다.
뷰는 패딩을 정할 수 있지만, 마진은 전혀 지원하지 않는다. 하지만 뷰 그룹은 지원한다.

자원요소-기본자원

기본자원에는 문자열, 문자열배열, 색상, 디멘젼, 단순표시물, 비트맵그래픽, 애니메이션 시퀀스, 메뉴파일, XML 파일, raw 파일, 레이아웃 파일, 스타일, 테마, Asset 자원, Searchable 등이 있다.


문자열

필수디렉토리 파일명(권장)
/res/values/ strings.xml

Strings를 리소스로 저장하고 참조할 수 있다. 스트링을 포맷팅하려면 세 가지 HTML tag를 사용할 수 있다: <b>, <i>, and <u>.
스타일이 적용되지 않은 텍스트만을 얻으려면 CharSequence 객체에 toString() 메쏘드를 호출하면 된다. 문자열 자원을 수용하는 메쏘드를 만들려면 앞서 정의한 태그들을 처리할 수 있어야 한다.

자바 코드로 이 자원에 접근하려면 Resources.getString() 이나 Resources.getText() 메쏘드를 사용한다.

Syntax
<string name=string_name>string_value</string>

Resource reference name:
Java: R.string.some_name
XML: @[package:]string/some_name (where some_name is the name of a specific string)

ex) 문자열 자원 정의 기본 예

<string name="good_example">"This'll work"</string>
<string name="good_example_2">This\'ll also work</string>
<string name="bad_example">This won't work!</string>
<string name="bad_example_2">XML encodings won&apos;t work either!</string>

ex) 포맷된 문자열 정의

<resources>
   <string name="simple_welcome_message">Welcome!</string>
   <string name="styled_welcome_message">We are <b><i>so</i></b> glad to see you.</string>
</resources>

ex) strings.xml에 정의된 문자열 자원을 참조

<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:text="@string/simple_welcome_message"/>


문자열 배열

필수디렉토리 파일명(권장)
/res/values/ arrays.xml


ex) 문자열 배열 정의

<resources>
<array name="honorifics">
<item>Dr.</item>
<item>Mr.</item>
<item>Mrs.</item>
<item>Ms.</item>
</array>
</resources>

* 위 자원을 자바 코드에서 사용하려면
getResources.getStringArray(R.array.honorifics);


색상

필수디렉토리 파일명(권장)
/res/values/ colors.xml

color drawables 와 color string 값을 저장하는데 사용하며, 이 자원에 접근하려면 각각 Resources.getDrawable() 와 Resources.getColor() 을 사용한다.

Syntax
<color name=color_name>#color_value</color>

Resource reference name:
Java: R.color.some_name
XML: @[package:]color/some_name (some_name 은 특정 색상의 이름)

ex) 색상 정의

<resources>
   <color name="opaque_red">#f00</color>
   <color name="translucent_red">#80ff0000</color>
</resources>

ex) 다른데서 정의된 색상을 참조

<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:textColor="@color/translucent_red"
          android:text="Some Text"/>

// 이것을 호출하는 Java 코드인 경우는 다음과 같다.
int color = getResources.getColor(R.color.opaque_red);


디멘젼

필수디렉토리 파일명(권장)
/res/values/ dimen.xml

Syntax
<dimen name=dimen_name>dimen_value</dimen>

Resources.getDimension()

Resource reference name:
Java: R.dimen.some_name
XML: @[package:]dimen/some_name (여기서 some_name은 특정 <dimen> 엘리먼트의 이름)

px : Pixels 실제화면의 픽셀을 말한다. 예:20 px
in : Inches 물리적길이 예:5in
mm : Millimeters 물리적길이 예:3mm
Pt : Points 글자크기단위 예:14pt
dp : Density-independent Pixels  160dpi 화면을 기준으로 한 픽셀단위 예:8dp
sp : Scale-independent Pixels 가변글꼴 표시에 최적임 예:14sp

ex) 기본 디멘젼 정의

<resources>
    <dimen name="one_pixel">1px</dimen>
    <dimen name="double_density">2dp</dimen>
    <dimen name="sixteen_sp">16sp</dimen>
</resources>

ex) 디멘젼 자원 참조

// Example Java code:
float dimen = Resources.getDimen(R.dimen.one_pixel);

// Example XML code:
<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="@dimen/sixteen_sp"/>


단순표시물

필수디렉토리 파일명(권장)
/res/values/ drawables.xml

색상있는 사각형 등 PaintDrawable 객체를 자원으로 정의해서 사용할 수 있다.

Syntax
<drawable name=color_name>color_value</drawable>

Resource reference name:
Java: R.drawable.some_name
XML: @[package:]drawable/some_name (여기서 some_name은 특정 자원의 이름)

ex) 단순표시물 정의

<resources>
    <drawable name="solid_red">#f00</drawable>
    <drawable name="solid_blue">#0000ff</drawable>
    <drawable name="solid_green">#f0f0</drawable>
</resources>

solid_red.xml 파일에 위 코드를 저장

ex) 단순표시물 참조

// Assign a PaintDrawable as the background to
// a TextView on the current screen.
Drawable redDrawable = Resources.getDrawable(R.drawable.solid_red);
TextView tv = (TextView)findViewByID(R.id.text);
tv.setBackground(redDrawable);

Example XML code

<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:background="@drawable/solid_red"/>


비트맵 그래픽

필수디렉토리: /res/drawable/

지원형식:  9.png, png (preferred), jpg (acceptable), gif (discouraged)
이 유형의 자원에 액세스하려면 Resources.getDrawable() 또는 mContext.getResources().getDrawable(R.drawable.imageId) 메쏘드를 사용한다.

Resource reference name:
Java: R.drawable.some_file
XML: @[package:]drawable/some_file

참고) 이미지를 비트맵으로 변환하기 위해 비트 스트림으로 저장하려 한다면, 그 이미지를 res/raw/ 폴더에 저장하면 최적화되지 않은 채로 컴파일된다.


애니메이션 시퀀스

필수디렉토리
/res/anim/

rame by frame animation 또는 tweened animation 객체로 컴파일된 XML 파일을 저장한다.

Resource reference name:
Java: R.anim.some_file
XML: @[package:]anim/some_file

ex) 트윈드 애니메이션 정의

<set android:shareInterpolator=boolean>  // Only required if multiple tags are used.
   <alpha android:fromAlpha=float
          android:toAlpha=float >   |
   <scale android:fromXScale=float
          android:toXScale=float
          android:fromYScale=float
          android:toYScale=float
          android:pivotX=string
          android:pivotY=string >    |
   <translate android:fromX=string
              android:toX=string
              android:fromY=string
              android:toY=string >   |
   <rotate android:fromDegrees=float
           android:toDegrees=float
           android:pivotX=string
           android:pivotY=string > |
   <interpolator tag>
   <set>
</set>


메뉴 파일

필수디렉토리: /res/menu/

Resource reference name:
Java: R.menu.some_file

ex) 옵션메뉴 만들기

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/new_game"
          android:title="New Game" />
    <item android:id="@+id/quit"
          android:title="Quit" />
</menu>

ex) 그룹이 있는 옵션메뉴 만들기

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/example_item
          android:title="Example Item"
          android:icon="@drawable/example_item_icon" />

    <group android:id="@+id/example_group">
        <item android:id="@+id/example_item2
              android:title="Example Item 2"
              android:icon="@drawable/example_item2_icon" />
    </group>

    <item android:id="@+id/example_submenu
          android:title="Example Sub Menu" >
        <menu>
            <item android:id="@+id/example_submenu_item
                  android:title="Example Sub Menu Item" />
        </menu>
    </item>
</menu>


XML 파일

필수디렉토리
/res/xml/

Resources.getXML()


Raw 파일

필수디렉토리
/res/raw/

Resources.openRawResource(R.raw.somefilename);


레이아웃 파일

필수디렉토리: /res/layout/

Resource reference name:
Java: R.layout.some_file
XML: @[package:]layout/some_file

레이아웃 자원 참조 자바 코드:
  setContentView(R.layout.main_screen);

Syntax
<ViewGroupClass xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/string_name" (attributes)>
   <위젯 또는 기타 네스트된 ViewGroupClass>+
   <requestFocus/>(레이아웃 파일당 0또는 1개 지정가능하고, 어떤 엘리먼트든 할당 가능)
</ViewGroupClass>

엘리먼트 설명
<ViewGroupClass>
이 파일의 루트 엘리먼트는 하나만 설정할 수 있다. 루트 엘리먼트는 다른 엘리먼트를 담고 있는 ViewGroup 클래스일 수도 있고, 한 개의 객체일 경우에는 위젯(또는 커스텀 위젯)이 될 수도 있다. 디폴트로, 엘리먼트로서 안드로이드 위젯 또는 ViewGroup 클래스명(대소문자 구분함)을 사용할 수 있다. 유효하지 않은 네스팅이 될 수도 있으니(예를 들면, <ListLayout> 안에 <TextView> 엘리먼트를 네스팅할 수 없다) 주의가 필요하다.
<requestFocus>
View 객체에 속하는 엘리먼트는 어떤 것이든 이 빈 엘리먼트를 포함시킬 수 있다. 그 의미는 화면 생성시 초기에 이 엘리먼트의 부모 태그에 포커스 주도록 하는 것이다. 파일당 한 개만 지정할 수 있다.


스타일

필수디렉토리 파일명(권장)
/res/values/ styles.xml

스타일은 한 엘리먼트(예를 들어 TextView에 적용된 10 pt red Arial font)에 적용되는 한 가지 이상의 속성이다. 스타일은 레이아웃 XML 파일의 엘리먼트에 속성으로 적용될 수 있다.


테마

필수디렉토리 파일명(권장)
/res/values/ themes.xml

테마는 전체 화면에 적용되는 한 가지 이상의 속성이다.
예를 들어 테마를 정의하여 윈도우 프레임의 색상과 패널의 전,후면, 그리고 메뉴의 문자 크기와 색상에 적용하여 애플리케이션의 액티비티에 반영되도록 할 수 있다.

스타일은 개별자원에만 지정할 수 있는 반면, 테마는 뷰 전체에 대해 지정하여 사용할 수 있다.

AndroidManifest.xml 파일의 활동요소(<activity>)의 android:theme 특성에 지정하여 사용한다.

스타일/테마 작성 절차
1.res/values 디렉토리에 styles.xml 파일을 생성한다. 루트에 <resource> 노드를 추가한다.
2.각 스타일 또는 테마에 <style> 요소를 고유한 이름을 주어 생성하고 부모 속성이 있다면 지정한다. 이름은 코드에서 참조할 때 사용하며, 부모 속성은 상속받을 스타일을 지정하는 것이다.
3.<style> 요소 안에, 포맷 값을 <item> 요소로 선언한다.
4.그러면 이제 매니페스트 파일이나 애플리케이션 코드 등 다른 XML 자원에서 이 리소스를 참조할 수 있다.

ex) 테마 선언

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <style name="CustomTheme">      
    <item name="android:windowNoTitle">true</item>
    <item name="windowFrame">@drawable/screen_frame</item>
    <item name="windowBackground">@drawable/screen_background_white</item>
    <item name="panelForegroundColor">#FF000000</item>
    <item name="panelBackgroundColor">#FFFFFFFF</item>
    <item name="panelTextColor">?panelForegroundColor</item>
    <item name="panelTextSize">14</item>
    <item name="menuItemTextColor">?panelTextColor</item>
    <item name="menuItemTextSize">?panelTextSize</item>
  </style>
</resources>

ex) 테마를 매니페스트 파일이 등록

<application ... android:theme="@style/CustomTheme"> <!-- 애플리케이션의 모든 액티비티 에 대해 이 테마가 적용됨 -->

ex) 액티비티에 다이얼로그 테마 적용
<activity ... android:theme="@android:style/Theme.Dialog">

ex) 프로그램 코드에 테마 적용

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); ...
setTheme(android.R.style.Theme_Light);
setContentView(R.layout.linear_layout_3);
}
// setContentView(View)를 호출하기 전 또는 inflate(int,ViewGroup) 전에 setTheme을 설정해야 한다.


Searchable

디렉토리,파일명 : res/xml/searchable.xml

전체 시스템의 기능으로 검색이 나타나도록 하기 위해, 안드로이드 프레임워크는 검색결과가 나타나도록 하는  API를 제공하고 있다. 이 API로 검색이 invoke되고 검색 다이얼로그가 나타나는 방법, 가용한 검색결과의 유형, 그리고 결과의 제시 방법을 설정할 수 있다.
안드로이드 검색 프레임워크를 사용하려면, 애플리케이션은 XML 리소스 형태로 검색 구성을 설정해야 한다.

Resource reference name:
Java: R.xml.filename.
XML: @[package:]xml/filename (e.g., @xml/searchable).