經過這幾天對 XML、介面元件 (View)、資源 (Resource) 的介紹,今天我們終於可以回到「寶寶生活記錄 App」了,若讀者還記得前幾天用筆畫在紙上的設計圖的話,可能還記得第一個畫面是一個月曆,Android 有提供 CalendarView 這個介面元件,因此我們嘗試將 activity_calendar.xml 修改成如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".CalendarActivity">
<CalendarView
android:id="@+id/calview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
然而這裡有一點要提醒大家的,到 Android Developers 網站查詢 CalendarView 這個 Class ([1]),會發現這個 Class 是「Added in API Level 11」,API Level 與 Android 版本的關係亦可於 Android Developers 網站中查詢得到,然而當初建立新專案時,筆者選擇的 Minimum SDK 為 API 8: Android 2.2 (Froyo),因此若要使用 CalendarView,要不就是在程式中判斷使用者手機的 Android 版本是否是 Android 3.0.x (API Level 11) 以上(若是才使用,若不是就不使用),要不就是修改 Minimum SDK,筆者示範後者的做法。修改 Minimum SDK 的方法很簡單,先打開 app 資料夾下的 build.gradle 這個檔案,然後將 minSdkVersion 的值改成 11 就可以了,如下所示:
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "lincyu.babylog"
minSdkVersion 11
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:20.0.0'
}
CalendarView 的執行結果如下:
然而筆者閱讀了 CalendarView 這個 Class 的說明文件 [1] 後發現,CalendarView 可能不能滿足筆者的需求,例如它不能在某個日期上加上個圖示 (我們可能會希望日曆上會有特殊的圖示表示「寶寶誕生日」、「卡介苗施打日」等),雖然說在網路上搜尋可以找到許多有用的資源 [3][4],但是想到自己開發過月曆形態為主的「班表小幫手」,我想就以「班表小幫手」為例,開發自己的 Calendar。
首先改寫了 activity_calendar.xml,內容如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="6dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:id="@+id/rootview"
android:paddingTop="5dp"
android:background="#EBEBEB" >
<RelativeLayout android:id="@+id/rl_ivbtns"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:layout_alignParentTop="true">
<ImageView android:id="@+id/iv_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share"
android:layout_alignParentRight="true"
/>
<ImageView android:id="@+id/iv_stat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stat"
android:layout_toLeftOf="@id/iv_share"
android:paddingRight="10dp"
/>
<ImageView android:id="@+id/iv_today"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/today"
android:layout_toLeftOf="@id/iv_stat"
android:paddingRight="10dp"
android:visibility="gone"
/>
</RelativeLayout>
<RelativeLayout android:id="@+id/rl_calendartitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_below="@id/rl_ivbtns">
<ImageView android:id="@+id/iv_arrowleft"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/arrow_left"
/>
<ImageView android:id="@+id/iv_arrowright"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/arrow_right"
/>
<TextView android:id="@+id/tv_calendartitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_centerVertical="true"
android:text="@string/loading"
android:layout_toRightOf="@id/iv_arrowleft"
android:layout_toLeftOf="@id/iv_arrowright"
/>
<LinearLayout android:id="@+id/ll_loadcalendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
android:layout_toRightOf="@id/iv_arrowleft"
android:layout_toLeftOf="@id/iv_arrowright"
android:gravity="center_horizontal"
>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
/>
<TextView android:id="@+id/tv_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="@string/loading"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</RelativeLayout>
<LinearLayout android:id="@+id/ll_week"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="7"
android:orientation="horizontal"
android:layout_below="@id/rl_calendartitle"
>
</LinearLayout>
<LinearLayout android:id="@+id/ll_calendar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="6"
android:orientation="vertical"
android:layout_below="@id/ll_week"
android:layout_alignParentBottom="true"
>
</LinearLayout>
</RelativeLayout>
這份 XML 文件裡,相信讀者對於 TextView, ImageView 等基礎介面元件應該不陌生了,但是對於RelativeLayout, LinearLayout 可能就有點疑惑了,它們都繼承了 ViewGroup,從名稱上我們很容易了解,ViewGroup 就是把 View 群組起來,也就是一個 ViewGroup 裏面可以包含其它的 View/ViewGroup,也就是 RelativeLayout 和 LinearLayout 裏面可以包含其它 View/ViewGroup,而它們的差異在於排版的方式不一樣。
RelativeLayout 顧名思義是依據「相對位置」來排版,例如 View A 可以利用 layout_above, layout_below, layout_toLeftOf, layout_toRightOf 等指定它要在 View B 的上下左右,當然一個 View 也可以透過 layout_alignParentTop 等指定它要在 Parent View (讀者還記得一份 XML 文件是一個樹狀架構吧) 的上下左右。
LinearLayout 顧名思義則是將 View/ViewGroup 依據撰寫的順序從上到下或從左到右「線性」做排版,LinearLayout 裏有一個很重要的屬性為 android:orientation,若設為 vertical,撰寫在 LinearLayout 裏的View/ViewGroup 就會從上到下依序排列,若設為 horizontal,則撰寫在 LinearLayout 裏的View/ViewGroup 就會從左到右依序排列。
至此,讀者應該對於 RelativeLayout 和 LinearLayout 有了初步的瞭解,若想更進一步的瞭解 ViewGroup,可參閱筆者的書籍《Android程式設計入門與應用 (附範例光碟)》http://www.opentech.com.tw/search/bookinfo.asp?isbn=9789572194126&companyID=04383129,明天筆者會詳細地來說明 activity_calendar.xml 的各項細節。
參考資料
[1] CalendarView | Android Developers, http://developer.android.com/reference/android/widget/CalendarView.html
[2] <uses-sdk> | Android Developers, http://developer.android.com/guide/topics/manifest/uses-sdk-element.html
[3] Android CalendarView for Showing Events - Stack Overflow, http://stackoverflow.com/questions/16556254/android-calendarview-for-showing-events
[4] tyczj/ExtendedCalendarView · GitHub, https://github.com/tyczj/ExtendedCalendarView