52
陳信宏 [email protected]

不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Embed Size (px)

Citation preview

Page 1: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

陳信宏

[email protected]

Page 2: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Section 1:

發生了什麼事?解析度與元件的關係。

Section 2:

實機上的畫面,不是都用模擬器設計好了嗎?

Section 3:

憤怒鳥的背景,圖片大小與解析度的對應。

Section 4:

翻來翻去,直立橫放都要處理。

Section 5:

Layout 的意義與應用

Page 3: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

學生實作 發現問題 討論與研究 解法與意義

Page 4: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

問題的起源,就發生在這些手機上..

除了品牌不同,這些都是 Android 手機..

最明顯的不同在哪兒?

Page 5: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

解析度與元件大小

Page 6: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Name Target SD Card Size Skin

AVD_21_QVGA Android 2.1 1024MB QVGA

AVD_21_HVGA Android 2.1 1024MB HVGA

AVD_21_WQVGA400 Android 2.1 1024MB WQVGA400

AVD_21_WVGA800 Android 2.1 1024MB WVGA800

新增完畢後,啟動這四個 AVD,並於啟動時,記錄其螢幕解析度 (如 QVGA = 240 x 320) 與 Density(如 QVGA=120(Low))

Page 7: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

1. 於 Eclipse 中,新增一個 Android Project

2. Project Name = Test1

3. Build Target = 2.1

4. App Name = Test1

5. Package Name = nku.android

6. Create Activity = Test1Activity

7. Min SDK = 7

依照以上資料,建立專案,並於不同的 AVD 執行

Page 8: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

1. 打開 Test1 專案的 res\layout\main.xml

2. 切換到 main.xml 頁(非圖形化介面)

3. 加入以下的按鈕

<Button

android:id="@+id/btnTest1"

android:text="測試"

android:layout_width="fill_parent"

android:layout_height="300px" />

4. 於不同的 AVD 執行看看

Page 9: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

同一個程式,在不同的 AVD 上執行,有何差異?

此差異的原因?

此差異會造成怎樣的困擾?

避免差異的方向?

Page 10: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

元件的 weight 與 height,最好用以下的方式來定義

其大小

◦ fill_parent (填滿 parent)(伏筆:parent 是誰?)

◦ wrap_content(依照內容伸縮其大小)

◦ 使用 dp(Density-independent pixel)為單位

改變一下 Button 的 android:layout_height,再執行

看看

資料來源: http://developer.android.com/guide/practices/screens_support.html

Page 11: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

dp 的意義: A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.

dp 與實際像素的轉換 px = dp * (dpi / 160) 其中 dpi 為此種螢幕的 Density

資料來源: http://developer.android.com/guide/practices/screens_support.html

Page 12: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

討論:為何 Android 推薦用 dp 為單位?

Skin Res Density(dpi) dp px

QVGA 240 x 320 120(Low) 300dp 225px

HVGA 320 x 480 160(Medium) 300dp 300px

WQVGA400 240 x 400 120(Low) 300dp 225px

WVGA800 480 x 800 240(High) 300dp 450px

注意比例關係

Page 13: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

手機真實尺寸

與執行結果

Page 14: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

機型 size res dpi 300dp px px cm

Samsung Note

5.3 吋 800 x 1280 WXGA

大約 285 約 535 px 垂直方向約 4.77 cm (11.42 cm)

HTC EVO 3D

4.3 吋 540 x 960 qHD

大約 256 約 480 px 垂直方向約 4.76 cm (9.52 cm)

Moto Droid 3.7 吋 480 x 854 WVGA854

大約 264 約 495 px 垂直方向約 4.74 cm (8.19 cm)

SE Xperia active

3.0 吋 320 x 480 HVGA

大約 160 約 300 px 垂直方向約 4.38 cm (約 7 cm)

部分數據來源網站:http://members.ping.de/~sven/dpi.html

由於各廠商並未提供螢幕真實尺寸,故以上數據皆由網站而來, 與真實情況可能稍有誤差

Page 15: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

資料來源: http://developer.android.com/guide/practices/screens_support.html http://developer.android.com/resources/dashboard/screens.html

Actual size 定義實機面板大小的等級類別 Actual density 為密度與名稱上的定義

Page 16: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

觀察 “300dp轉換後的尺寸”,得到怎樣的結論?

試分析為何 Android 推薦這樣的轉換?

轉換後,對使用者的影響為何?是好還是壞?

觀念挑戰:若要設計一個”手機皮尺”程式,即利用

手機來量真正物體的長度,會遇到怎樣的問題?

Page 17: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

圖片的大小與解析度

Page 18: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

1. 觀察 drawable-hdpi、 drawable-mdpi、 drawable-ldpi 中,icon.png 的大小。

2. 於 main.xml 中,加入下一列的元件碼。

3. 將專案執行到不同的 AVD 並察看結果。

<ImageView

android:id="@+id/testimg"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/icon"

android:layout_x="50px"

android:layout_y="50px"

/>

Page 19: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

圖片來源:http://developer.android.com/guide/practices/screens_support.html

同一張圖片,在不同的解析度下的情況

依照不同的解析度,製作不同的圖片(三張),顯示的結果

Page 20: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

發生了什麼現象?

對使用者友善的解決方式為何?

Page 21: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

需要在不同的 dpi 手機上,顯示相同大小的圖片時,有兩種方式: ◦ 寫程式碼,動態針對不同的螢幕解析度,進行縮放

=> 效果不好,且會拖慢執行速度

◦ 製作不同尺寸的圖片,同檔名,放到三個資料夾中 => 效果好,但若圖片太多,到時 apk 會變得比較大

當程式執行時,會根據目前螢幕的dpi,自動到drawable-hdpi、drawable-mdpi、 drawable-ldpi中,找相對應的圖形檔。

圖片設計的流程:先設計出 mdpi 的圖形,放大 150%成為 hdpi,縮小 75% 成為 ldpi 的圖。

Page 22: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

如何設計出如 Angry Bird 般

可以動態縮放的遊戲圖片背景?

Page 23: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

當螢幕翻轉時

Page 24: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

將會結束目前的 Activity, 並重新 Create 一個新的。

所以: 1. 程式中要在適當(OnPause)的時

候,儲存相關資訊,如使用者於 EditText 中輸入的文字

2. 設計直立(LANDSCAPE)與橫向(PORTRAIT),不同的畫面

3. 於 OnCreate 或 OnResume中,

取回儲存的資料,放到程式的資料結構與畫面中

討論: 1. 資料要存去哪兒?

2. 怎麼設計不同的畫面?

Page 25: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

1. 在 Eclipse 的專案目錄下,/res 之下,建立 layout-land 與 layout-port 兩個目錄。

2. layout-land 代表直式的畫面,layout-port 代表橫式的畫面。

3. 依照直與橫的螢幕特性,建立不同的畫面檔

4. 此畫面檔(xml),會在 Activity 的 OnCreate 中,被讀出與建立 setContentView(R.layout.main);

Page 26: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

在兩個畫面中,加入不同的 TextView 來顯示在不同的方向中 <TextView android:layout_width="fill_parent“ android:layout_height="wrap_content“ android:text="It's LAND/PORT layout“ />

在模擬器中,利用 Ctrl+F11 來翻轉螢幕。

Page 27: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

方法如下: 在 AndroidManifest.xml 中,每個 Activity 加入如下的設定: <activity android:name=".SubscribeBusStop“ android:configChanges="orientation"> </activity>

這樣,就不會重新產生 Activity

Page 28: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

若有 layout-land 與 layout-port 時,原來的

layout 是否有作用?

如何強制設定,此 Activity 的限制方向?

如何取得目前螢幕的方向?

如何動態設定 Activity 的方向?

Page 29: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Layout與畫面布局

Page 30: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

畫面上只有單一 Button元件,

layout_width=300dp,layout_height=200dp,

此 Button 不管在何種螢幕尺寸/方向下,

皆保持在螢幕正中央。

Page 31: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Layout 為預先設定好的元件排列方式。

利用 Layout,可以快速、有結構的安排畫面元件,依照預定的方式呈現。

Layout中,除了放置元件之外,還可放入另一個Layout,形成巢狀結構。

Android 中的 Layout 有以下五種 LinearLayout FrameLayout RelativeLayout TableLayout AbsoluteLayout(已不再使用)

Page 32: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

線性佈局就是將在< LinearLayout >內的元件以線性的方式來呈現

Page 33: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<?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:text="這是第一列"

android:textSize="22sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

<TextView

android:text="這是第二列"

android:textSize="22sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

<TextView

android:text="這是第三列"

android:textSize="22sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

</LinearLayout>

布局文件(res/layout/main.xml):

Page 34: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

線性佈局共有兩個方向: ◦ 垂直(vertical)

◦ 水平(horizontal)

◦ 決定垂直或是水平的屬性為Orientation

android:orientation ◦ 在<LinearLayout>中,此屬性代表元件的排列是垂直或水平佈局

Page 35: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_width ◦ 代表此元件佈局的寬度,若值為fill_parent則會填滿

parent的寬度;若值為wrap_content則元件寬度會依照內容大小而調整

android:layout_height ◦ 代表此元件佈局的高度,若值為fill_parent則會填滿

parent的高度;若值為wrap_content則元件高度會依照內容大小而調整

Page 36: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_margin ◦ 指定這個view距離上下左右的額外距離

android: layout_marginBottom ◦ 指定這個view距離下方的額外距離

android: layout_marginLeft ◦ 指定這個view距離左方的額外距離

android: layout_marginRight ◦ 指定這個view距離右方的額外距離

android: layout_marginTop ◦ 指定這個view距離上方的額外距離

Page 37: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

FrameLayout是所有佈局中最單純的

若同個FrameLayout中若有數個元件

◦ 以最上層的元件為主

若同個FrameLayout中有同大小的元件

◦ 只會看到最上層的元件

若同個FrameLayout中有不同大小的元件

◦ 會看到由下至上的元件

Page 38: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<?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"> <FrameLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"> <!-- 最底層的元件 --> <EditText android:text="That is a framelayout example" android:id="@+id/text01" android:layout_width="wrap_content" android:layout_height="wrap_content" />

布局文件-1 (res/layout/main.xml) :

Page 39: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<!-- 最上層的元件 -->

<EditText android:text="This is"

android:id="@+id/text02"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

</FrameLayout>

</LinearLayout>

下層元件為"That is a framelayout example"

上層元件為"Thit is"

布局文件-2(res/layout/main.xml):

Page 40: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式
Page 41: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<!-- 顯示第一行的TextView -->

android:id="@+id/TextView01"

<!-- 顯示第二行的TextView -->

android:id="@+id/ TextView02"

android:layout_below="@id/ TextView01"

<!-- 顯示第三行的TextView -->

android:id="@+id/ TextView03"

android:layout_below="@id/ TextView02"

程式以TextView01為參考,TextView02置放在TextView01下方,TextView03放置在TextView02下方

布局文件架構(res/layout/main.xml):

Page 42: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<?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="fill_parent">

<TextView

android:text="這是第一列"

android:id="@+id/TextView01"

android:textSize="30sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

<TextView

android:text="這是第二列"

android:id="@+id/TextView02"

android:textSize="30sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/TextView01" />

<TextView

android:text="這是第三列"

android:id="@+id/TextView03"

android:textSize="30sp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/TextView02" />

</RelativeLayout>

布局文件架構(res/layout/main.xml):

此範例用到三個TextView,利用三個TextView作RelativeLayout

Page 43: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_above ◦ 置於目標id元件的上方

android:layout_alignBaseline ◦ 置於與目標id元件同樣的基準線上

android:layout_alignBottom ◦ 讓自己的下邊界與目標id元件的下邊界在同一個位置

android:layout_alignLeft ◦ 讓自己的左邊界與目標id元件的左邊界在同一位置

android:layout_alignParentBottom ◦ 若為true,讓自己的下邊界與Parent的下邊界同位置

android:layout_alignParentLeft ◦ 若為true,讓自己的左邊界與Parent的左邊界同位置

Page 44: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_alignParentRight ◦ 若為true,讓自己的右邊界與Parent的右邊界同位置

android:layout_alignParentTop ◦ 若為true,讓自己的上邊界與Parent的上邊界同位置

android:layout_alignRight ◦ 讓自己的右邊界與目標id元件的右邊界在同一位置

android:layout_alignTop ◦ 讓自己的上邊界與目標id元件的上邊界在同一個位置

android:layout_alignWithParentIfMissing ◦ 若設為true,當參考的目標id不可用時,會以Parent為參考目標

android:layout_below ◦ 置於目標id元件的下方

Page 45: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_centerHorizontal ◦ 若為true,置於Parent水平位置的中心

android:layout_centerInParent ◦ 若為true,置於Parent水平以及垂直位置的中心

android:layout_centerVertical ◦ 若為true,置於Parent垂直位置的中心

android:layout_toLeftOf/toRightOf ◦ 置於目標id元件的左方/右方

Page 46: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式
Page 47: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

<?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"> <TableRow android:layout_marginTop="20px"> <TextView android:layout_column="0" android:text="第一列\n第一行" android:textSize="22sp" android:layout_marginLeft="60px"/> <TextView android:layout_column="1" android:text="第一列\n第二行" android:textSize="22sp" android:layout_marginLeft="60px"/>/> </TableRow>

<TableRow android:layout_marginTop="20px">

<TextView

布局文件-1(res/layout/main.xml):

Page 48: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

android:layout_column="0"

android:text="第二列\n第一行"

android:textSize="22sp"

android:layout_marginLeft="60px"/>

<TextView

android:layout_column="1"

android:text="第二列\n第二行"

android:textSize="22sp"

android:layout_marginLeft="60px"/>/>

</TableRow>

<TableRow android:layout_marginTop="20px">

<TextView

android:layout_column="0"

android:text="第三列\n第一行"

android:textSize="22sp"

android:layout_marginLeft="60px"/>

<TextView

android:layout_column="1"

android:text="第三列\n第二行"

android:textSize="22sp"

android:layout_marginLeft="60px"/>/>

</TableRow>

</TableLayout>

布局文件-2(res/layout/main.xml):

Page 49: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

相關的屬性,和 TableRow 的架構與組成,很多..

所以,TableLayout 的完全設計..

這是,另外一個故事了..

Page 50: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

會選擇用哪個 Layout 來完成

”按鈕皆保持在螢幕正中央”

呢?

Page 51: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

在不同的 Layout 中,或是在巢狀的 Layout 內,

Parent 是誰?

fill_parent 會有何結果?是否為最佳的設計方式?

利用程式碼來取得 parent 的 parent,並用來做為

元件的大小標準,是否可行?有何意義?

所有元件,最根的parent是誰?

Page 52: 不同尺寸與解析度的螢幕下,Android 程式 UI 的設計與解決方式

Q & A 請不要鞭得太用力 :-)