Bài 3: GIAO DIỆN NGƯỜI DÙNG CỦA ỨNG DỤNG ANDROID
3.2. Bố cục giao diện thích nghi với hướng màn hình
Một tính năng xuất hiện trên hầu hết các điện thoại thông mình hiện hành là tính năng tự động thay đổi hướng hiển thị của màn hình từ dọc sang ngang hoặc ngược lại khi người dùng xoay điện thoại theo hướng tương ứng. Android cũng không ngoại lệ, khi thiết bị thay đổi hướng từ dọc sang ngang hoặc ngược lại, activity hiện tại sẽ vẽ lại các view con của mình theo hướng mới, khi đó hàm onCreate của Activity sẽ được gọi lại từ đầu. Mặt khác,
41
do diện tích và tỷ lệ vùng hiển thị trong hướng dọc và hướng ngang khác nhau tương đối nhiều, nên khi thiết kế layout ta cần có biện pháp thích hợp cho sự thay đổi này.
Có 2 phương pháp phổ biến để thiết kế layout thích nghi với sự thay đổi này:
Neo – neo (xếp cố định) các view con theo các cạnh của màn hình. Đây là cách dễ làm nhất, khi kích thước màn hình thay đổi, vị trí của các layout con sẽ được xếp lại nhưng vẫn căn theo các cạnh gần nhất.
Thay đổi kích thước và vị trí – cách làm tốn công hơn và linh hoạt hơn và sắp xếp lại toàn bộ layout của các view con khi có sự thay đổi về màn hình. Ngoài ra còn có thể thêm/bớt view con với những hướng nhất định.
3.2.1. Thay đổi kích thước và vị trí
Trong phương pháp này, thông thường mỗi hướng màn hình sẽ có một layout riêng. Layout này có thể được cấu hình trong code, hoặc đặt file layout vào thư mục cấu hình sẵn để hệ thống tự chọn lựa chọn trong quá trình chạy. Để tạo layout riêng cho Activity trên trong màn hình ngang, ta tạo thư mục layout-land trong thư mục res, sau đó tạo file main.xml (trùng trên với file layout trong thư mục res/layout), với nội dung như sau:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Top Left"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Top Right"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bottom Left"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
42 android:layout_height="wrap_content"
android:text="Bottom Right"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true" />
<Button
android:id="@+id/button5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Middle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/button6"
android:layout_width="180px"
android:layout_height="wrap_content"
android:text="Top Middle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true" />
<Button
android:id="@+id/button7"
android:layout_width="180px"
android:layout_height="wrap_content"
android:text="Bottom Middle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Để ý thấy layout này có 7 nút thay vì 5 nút như layout mặc định (cho màn hình dọc). Kết quả hiển thị cho màn hình ngang sẽ xuất hiện thêm 2 nút bấm ở trên và dưới màn hình, căn giữa theo chiều ngang như hình dưới:
43
Ngoài ra khi thay đổi hướng màn hình, Activity sẽ được vẽ lại hoàn toàn từ đầu, và sẽ trạng thái hiện tại sẽ mất, bao gồm giá trị của các trường, nội dung của các view không được đặt tên trong layout… Vì vậy, trong trường hợp cần thiết lưu trữ trạng thái hiện tại của Activity, việc ta cần làm là nạp chồng 2 hàm sau:
@Override
public void onSaveInstanceState(Bundle outState) { //---save whatever you need to persist- --
outState.putString("ID", "1234567890");
super.onSaveInstanceState(outState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); //---retrieve the information persisted earlier---
String ID = savedInstanceState.getString("ID");
}
Dữ liệu cần lưu trữ được chứa trong một đối tượng Bundle, chi tiết về đối tượng này và các loại dữ liệu có thể lưu trữ trong nó bạn đọc tự tìm hiểu coi như bài tập. Trong ví dụ trên ta đã tiến hành lưu và lấy lại giá trị của một chuỗi (“0123456789”) vào Bundle dưới tên là
“ID”.
3.2.2. Điều khiển hướng của màn hình
Trong một số trường hợp, ta cần thiết kế một số Activity chỉ hỗ trợ một loại hướng màn hình cụ thể. Ví dụ màn hình xem phim có thể được thiết lập chỉ có hướng nằm ngang, hay màn hình gọi điện thoại được thiết lập luôn luôn hiển thị theo chiều dọc.
Để làm việc này, ta có thể khai báo thuộc tính của activity tương ứng trong file Manifest hoặc cấu hình trong mã nguồn của hàm onCreate tương ứng với Activity cần thiết lập.
Ví dụ về cấu hình hướng luôn nằm ngang trong mã nguồn:
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.main);
44 //---change to landscape mode---
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
Và trong Manifest:
<activity
android:label="@string/app_name"
android:name=".OrientationsActivity"
android:screenOrientation="landscape" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
</activity>