1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
page.title=다양한 화면 크기 지원
parent.title=다양한 화면 지원
parent.link=index.html
trainingnavtop=true
next.title=다양한 화면 밀도 지원
next.link=screendensities.html
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>강의 목표</h2>
<ol>
<li><a href="#TaskUseWrapMatchPar">'wrap_content' 및 'match_parent' 사용</a></li>
<li><a href="#TaskUseRelativeLayout">RelativeLayout 사용</a></li>
<li><a href="#TaskUseSizeQuali">크기 한정자 사용</a></li>
<li><a href="#TaskUseSWQuali">최소 너비 한정자 사용</a></li>
<li><a href="#TaskUseAliasFilters">레이아웃 별칭 사용</a></li>
<li><a href="#TaskUseOriQuali">방향 한정자 사용</a></li>
<li><a href="#TaskUse9Patch">나인-패치 비트맵 사용</a></li>
</ol>
<h2>참고자료</h2>
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">다양한 화면 지원</a></li>
</ul>
<h2>다운로드 </h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">샘플 앱 다운로드</a>
<p class="filename">NewsReader.zip</p>
</div>
</div>
</div>
<p>이 강의에서는 다양한 화면 크기를 지원하는 방법을 설명합니다.</p>
<ul>
<li>화면에 맞게 레이아웃 크기 조정</li>
<li>화면 구성에 따라 적합한 UI 레이아웃 제공</li>
<li>올바른 화면에 올바른 레이아웃 적용</li>
<li>정확하게 확대되는 비트맵 제공</li>
</ul>
<h2 id="TaskUseWrapMatchPar">'wrap_content' 및 'match_parent' 사용</h2>
<p>레이아웃이 다양한 화면 크기에 따라 유연하게 조정되도록 하려면 일부 뷰 구성요소의 너비와 높이에 <code>"wrap_content"</code> 및 <code>"match_parent"</code>를 사용해야 합니다. <code>"wrap_content"</code>를 사용하면 뷰의 너비와 높이가 해당 뷰 내에 콘텐츠가 들어가는데 필요한 최소 크기로 설정되는 반면, <code>"match_parent"</code>(API 수준 8 이전에는 <code>"fill_parent"</code>라고도 함)를 사용하면 구성요소가 확장되어 부모뷰의 크기와 일치하게 됩니다.</p>
<p>하드코딩된 크기 대신 <code>"wrap_content"</code> 크기 값을 사용하면 뷰가 해당 뷰에 필요한 여백만을 사용하며 <code>"match_parent"</code> 크기 값을 사용하면 뷰가 확대되어 사용 가능한 여백을 채웁니다. 예를 들면 다음과 같습니다.</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
<p>샘플에서 구성요소 크기에 특정 크기가 아닌 <code>"wrap_content"</code> 및 <code>"match_parent"</code>가 사용된 것을 눈여겨 보시기 바랍니다. 이렇게 하면 레이아웃이 다양한 화면 크기 및 방향에 맞게 조정됩니다.</p>
<p>예를 들어 세로 및 가로 모드에서 레이아웃은 다음과 같이 표시됩니다. 구성요소의 크기가 너비와 높이에 맞게 자동으로 조정됩니다.</p>
<img src="{@docRoot}images/training/layout-hvga.png" />
<p class="img-caption"><strong>그림 1.</strong> 세로 모드(왼쪽) 및 가로 모드(오른쪽)에서의 뉴스 리더 샘플 앱</p>
<h2 id="TaskUseRelativeLayout">RelativeLayout 사용</h2>
<p>비교적 복잡한 레이아웃을 만들려면 <PH>{@link android.widget.LinearLayout}의 중첩 인스턴스와</PH> <code>"wrap_content"</code> 및 <code>"match_parent"</code> 크기의 조합을 사용합니다. 하지만 <PH>{@link android.widget.LinearLayout}</PH> 을 사용하면 자식뷰의 여백 관계를 정확하게 제어할 수 없으며 <PH>{@link android.widget.LinearLayout}</PH> 단순히 나란하게 표시됩니다. 자식뷰를 일직선이 아닌 다양한 방향으로 표시해야 하는 경우 구성요소 사이의 여백 관계를 중심으로 레이아웃을 지정할 수 있는 <PH>{@link android.widget.RelativeLayout}</PH>을 사용하는 것이 더 좋은 방법일 수 있습니다. 예를 들어 화면 왼쪽에 하나의 자식뷰를, 오른쪽에 다른 자식뷰를 정렬할 수 있습니다.</p>
<p>예를 들면 다음과 같습니다.</p>
<pre>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>
<EditText
android:id="@+id/entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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="10dp"
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>
</pre>
<p>그림 2는 이 레이아웃이 QVGA 화면에 어떻게 표시되는지 보여줍니다.</p>
<img src="{@docRoot}images/training/relativelayout1.png" />
<p class="img-caption"><strong>그림 2.</strong> QVGA 화면(작은 화면)의 스크린샷</p>
<p>그림 3은 이 레이아웃이 큰 화면에서 어떻게 표시되는지 보여줍니다.</p>
<img src="{@docRoot}images/training/relativelayout2.png" />
<p class="img-caption"><strong>그림 3.</strong> WSVGA 화면(큰 화면)의 스크린샷</p>
<p>구성요소의 크기가 변하더라도 여백 관계가 <PH>{@link android.widget.RelativeLayout.LayoutParams}</PH>.</p>
<h2 id="TaskUseSizeQuali">크기 한정자 사용</h2>
<p>이전 섹션에서 다룬 유연한 레이아웃이나 상대적 레이아웃으로는 한계가 있습니다. 이러한 레이아웃이 구성요소 내부 및 주위의 여백을 확장하여 다양한 화면에 맞게 조정되긴 하지만 화면 크기별로 최적의 사용자 환경을 제공하지는 못할 수 있습니다. 따라서 애플리케이션은 유연한 레이아웃을 구현할 뿐 아니라 다양한 화면 구성을 타겟팅할 수 있도록 다양한 대체 레이아웃을 제공해야 합니다. 그 방법은 런타임이 현재 기기의 구성에 따라 적합한 리소스(예: 화면 크기별로 다른 레이아웃 디자인)를 자동으로 선택하도록 해 주는 <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">구성 한정자</a>를 사용하는 것입니다.</p>
<p>예를 들어 많은 애플리케이션이 큰 화면에 '이중 창(two pane)' 패턴을 구현합니다(한 쪽 창에는 아이템의 목록을 표시하고 다른 창에는 콘텐츠를 표시). 태블릿 및 TV는 두 개의 창 모두가 화면에 동시에 들어갈 정도로 크지만 휴대전화 화면은 두 창을 따로 표시해야 합니다. 따라서 이러한 레이아웃을 구현하려면 다음 파일이 있어야 합니다.</p>
<ul>
<li><code>res/layout/main.xml</code>, 단일 창(기본값) 레이아웃:
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
</li>
<li><code>res/layout-large/main.xml</code>, 이중 창 레이아웃:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
</li>
</ul>
<p>두 번째 레이아웃의 디렉토리 이름에서 <code>large</code> 한정자를 눈여겨 보시기 바랍니다. 이 레이아웃은 대형(예: 7인치 태블릿 이상)으로 분류된 화면을 가진 기기에서 선택됩니다. 한정자가 없는 다른 레이아웃은 소형 기기에서 선택됩니다.</p>
<h2 id="TaskUseSWQuali">최소 너비 한정자 사용</h2>
<p>Android 3.2 이전 기기에서 개발자가 어려움을 느꼈던 문제 중의 하나는 Dell Streak, 최초의 Galaxy 탭 및 7인치 태블릿에 두루 사용되는 '큰' 화면 크기 빈이었습니다. 하지만 많은 애플리케이션은 화면이 '큰' 기기라 하더라도 이 카테고리(예: 5인치 및 7인치 기기)에 속하는 다양한 기기에 다양한 레이아웃을 표시하고 싶어 합니다. 이것이 Android에서 Android 3.2에 '최소 너비' 한정자를 도입한 이유입니다.</p>
<p>최소 너비 한정자를 사용하면 dp 단위의 특정 최소 너비를 가진 화면을 타겟팅할 수 있습니다. 예를 들어 일반적인 7인치 태블릿에는 600dp라는 최소 너비가 있으므로 이러한 화면에서 두 개의 창에 UI를 사용(작은 화면에서는 단일 목록 사용) 하고 싶은 경우 단일 및 이중 창 레이아웃에 이전 섹션과 동일한 레이아웃을 사용하면 되지만, 이중 창 레이아웃은 최소 너비가 600dp인 화면에 사용한다는 것을 나타내기 위해서 <code>large</code> 크기 한정자 대신 <code>sw600dp</code>를 사용해야 합니다.</p>
<ul>
<li><code>res/layout/main.xml</code>, 단일 창(기본값) 레이아웃:
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
</li>
<li><code>res/layout-sw600dp/main.xml</code>, 이중 창 레이아웃:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
</li>
</ul>
<p>이는 최소 너비가 600dp 이상인 기기는 <code>layout-sw600dp/main.xml</code>(이중 창) 레이아웃을 선택하는 반면 소형 화면은 <code>layout/main.xml</code> (단일 창) 레이아웃을 선택한다는 것을 의미합니다.</p>
<p>하지만 Android 3.2 이전 기기는 <code>sw600dp</code>를 크기 한정자로 인식하지 않기 때문에 최소 너비 한정자가 제대로 작동하지 않으며 따라서 <code>large</code> 한정자도 계속 사용해야 합니다. 따라서 <code>res/layout-large/main.xml</code>라는 이름의 파일이 있어야 하며 이 파일은 <code>res/layout-sw600dp/main.xml</code>과 동일한 파일입니다. 다음 섹션에서는 이런 식으로 레이아웃 파일이 중복되지 않게 하는 기술을 살펴보겠습니다.</p>
<h2 id="TaskUseAliasFilters">레이아웃 별칭 사용</h2>
<p>최소 너비 한정자는 Android 3.2 이상 버전에서만 사용할 수 있습니다. 따라서 이전 버전과 호환되도록 하려면 추상화 크기 빈(소형, 보통, 대형 및 초대형)을 계속 사용해야 합니다. 예를 들어 휴대전화에서는 단일 창 UI가 표시되고 7인치 태블릿, TV 및 기타 대형 기기에서는 다중 창 UI가 표시되도록 UI를 디자인하려면 다음 파일을 제공해야 합니다.</p>
<p><ul>
<li><code>res/layout/main.xml:</code> 단일 창 레이아웃</li>
<li><code>res/layout-large:</code> 다중 창 레이아웃</li>
<li><code>res/layout-sw600dp:</code> 다중 창 레이아웃</li>
</ul></p>
<p>마지막 두 개의 파일은 하나는 Android 3.2 기기와 일치하고 다른 하나는 이전 버전의 Android가 탑재된 태블릿 및 TV를 위한 것으로 서로 동일한 파일입니다.</p>
<p>이 경우 별칭 파일을 사용하면 태블릿 및 TV용으로 동일한 파일이 중복되지 않도록 하고 이를 관리해야 하는 번거로움을 없앨 수 있습니다. 예를 들어 다음 레이아웃을 지정할 수 있습니다.</p>
<ul>
<li><code>res/layout/main.xml</code>, 단일 창 레이아웃</li>
<li><code>res/layout/main_twopanes.xml</code>, 이중 창 레이아웃</li>
</ul>
<p>또한 다음 두 개의 파일을 추가합니다.</p>
<p><ul>
<li><code>res/values-large/layout.xml</code>:
<pre>
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
</pre>
</li>
<li><code>res/values-sw600dp/layout.xml</code>:
<pre>
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
</pre>
</li>
</ul></p>
<p>뒤에 있는 두 개의 파일은 콘텐츠는 동일하지만 실제로 레이아웃을 지정하지는 않으며 단지 <PH>{@code main}</PH> 이 <PH>{@code main_twopanes}에 대한 별칭이 되도록 설정합니다.</PH> 이 파일에는 <code>large</code> 및 <code>sw600dp</code> 선택기가 있으므로 Android 버전에 관계없이 태블릿 및 TV에 적용됩니다(3.2 버전 이전의 태블릿 및 TV는
<PH>{@code large}</PH>,3.2 이후 버전은 <code>sw600dp</code>와 일치).</p>
<h2 id="TaskUseOriQuali">방향 한정자 사용</h2>
<p>일부 레이아웃은 가로 및 세로 방향 모두에서 잘 작동하지만 대부분의 레이아웃은 조정을 통해 많은 이점을 누릴 수 있습니다. 다음은 뉴스 리더 샘플 앱에서 화면 크기와 방향별로 레이아웃이 어떻게 작동하는지 보여줍니다.</p>
<p><ul>
<li><b>소형 화면, 세로:</b> 단일 창, 로고 표시</li>
<li><b>소형 화면, 가로:</b> 단일 창, 로고 표시</li>
<li><b>7인치 태블릿, 세로:</b> 단일 창, 작업 표시줄 표시</li>
<li><b>7인치 태블릿, 가로:</b> 이중 창, 와이드, 작업 표시줄 표시</li>
<li><b>10인치 태블릿, 세로:</b> 이중 창, 내로우, 작업 표시줄 표시</li>
<li><b>10인치 태블릿, 가로:</b> 이중 창, 와이드, 작업 표시줄 표시</li>
<li><b>TV, 가로:</b> 이중 창, 와이드, 작업 표시줄 표시</li>
</ul></p>
<p>따라서 이러한 각 레이아웃은 <code>res/layout/</code> 디렉토리의 XML 파일에서 지정됩니다. 그러면 앱은 각 레이아웃을 다양한 화면 구성에 지정하기 위해 레이아웃 별칭을 사용해 레이아웃을 각 구성과 일치시킵니다.</p>
<p><code>res/layout/onepane.xml:</code></p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
<p><code>res/layout/onepane_with_bar.xml:</code></p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
<p><code>res/layout/twopanes.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
<p><code>res/layout/twopanes_narrow.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all}
<p>가능한 레이아웃을 모두 지정했으므로 구성 한정자를 사용하여 올바른 레이아웃을 각 구성에 매핑하기만 하면 되며 이는 레이아웃 별칭 기술을 사용하면 됩니다.</p>
<p><code>res/values/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all}
<p><code>res/values-sw600dp-land/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml
all}
<p><code>res/values-sw600dp-port/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml
all}
<p><code>res/values-large-land/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all}
<p><code>res/values-large-port/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all}
<h2 id="TaskUse9Patch">나인-패치 비트맵 사용</h2>
<p>일반적으로 다양한 화면 크기를 지원하려면 이미지 리소스도 다양한 크기에 맞게 조정될 수 있어야 합니다. 예를 들어 버튼 배경은 버튼 배경이 적용되는 모든 버튼 모양과 맞아야 합니다.</p>
<p>구성요소에 크기가 바뀔 수 있는 단순한 이미지를 사용하는 경우 런타임이 이미지를 균등하게 확대하거나 축소하기 때문에 기대에 미치지 못하는 결과가 나옵니다. 이에 대한 해결 방법은 확대될 수 있는 영역과 확대될 수 없는 영역을 나타내는 특별한 형식의 PNG 파일인 나인-패치 비트맵을 사용하는 것입니다.</p>
<p>따라서 다양한 크기를 가진 구성요소에 사용할 비트맵을 디자인할 때에는 항상 나인-패치를 사용하시기 바랍니다. 비트맵을 나인-패치로 변환하려면 일반적인 이미지부터 시작합니다(그림 4, 명확하게 보이도록 4배 줌으로 표시).</p>
<img src="{@docRoot}images/training/button.png" />
<p class="img-caption"><strong>그림 4.</strong> <code>button.png</code></p>
<p>그 다음 이 이미지에 <ode
href="{@docRoot}tools/help/draw9patch.html">SDK의 <code>draw9patch</code></a> 유틸리티(<code>tools/</code> 디렉토리에 있음)를 실행합니다. 이 때 왼쪽 및 상단 테두리를 따라 픽셀을 그려 확대되어야 할 영역을 표시할 수 있습니다. 또한 오른쪽 및 하단 테두리를 따라 픽셀을 그려 콘텐츠가 들어가야 할 영역을 표시할 수 있으며 그 결과는 그림 5와 같습니다.</p>
<img src="{@docRoot}images/training/button_with_marks.png" />
<p class="img-caption"><strong>그림 5.</strong> <code>button.9.png</code></p>
<p>테두리를 따라 있는 검은색 픽셀을 눈여겨 보시기 바랍니다. 상단 및 왼쪽 테두리의 픽셀은 이미지가 확대될 수 있는 영역을 나타내며 오른쪽 및 하단 테두리는 콘텐츠가 위치해야 하는 영역을 나타냅니다.</p>
<p>또한 <code>.9.png</code> 확장자를 확인하시기 바랍니다. 프레임워크는 이 확장자를 통해 이미지가 일반적인 PNG 이미지가 아닌 나인-패치 이미지임을 감지할 수 있으므로 이 확장자를 사용해야 합니다.</p>
<p><code>android:background="@drawable/button"</code>을 설정하여 이 배경을 구성요소에 적용하면 그림 6의 다양한 크기로 표시된 것처럼 프레임워크가 버튼의 크기를 수용할 수 있도록 이미지를 올바르게 확대합니다.</p>
<img src="{@docRoot}images/training/buttons_stretched.png" />
<p class="img-caption"><strong>그림 6.</strong> 다양한 크기에 <code>button.9.png</code> 나인-패치를 사용하는 버튼</p>
|