Bài 2:  Tạo Form Login Sử Dụng Blackberry        Component (Tiếp theo)

II.       Xử Lý Tương Tác Người Dùng

Trong ví dụ trên, bạn có thể di chuyển focus giữa các Field, nhập dữ liệu cho TextField, thay đổi giá trị cho ObjectChoiceField, hay đánh dấu chọn cho CheckBox…Tuy nhiên, khi click vào các Button thì vẫn chưa có tương tác gì. Trong mục này, chúng ta sẽ xử lý tiếp các sự kiện trên Button.

1.     Xử lý các sự kiện UI

Blackberry API sử dụng observer pattern để gửi đi (dispatch) các sự kiện. Tất cả các Field có thể đăng ký một listener cho chúng, và listener này được thông báo khi có sự thay đổi sự kiện được phát sinh.

  • Đối với ButtonField, một event được phát sinh khi button được click bởi trackball hay touch (màn hình touch), hay phím Enter được nhấn khi button được highlight.
  • Đối với CheckboxField, một event được phát sinh khi checkbox được check hay uncheck.
  • Đối với ChoiceField, một event được phát sinh khi người dùng lựa chọn một choice khác.

Để đăng khi listener cho Field, sử dụng phương thức Field.setChangeListener().

Lưu ý Blackberry cung cấp một mô hình sự kiện unicast, đó là chỉ có nhiều nhất một change listener cho một Field. Nếu sử dụng Field.setChangeListener(), tức là bạn đã thay thế cho listener đã tồn tại trước đó trong Field, ngăn cản nó nhận các sự kiện.

Một listener phải thực thi một giao diện FieldChangeListener. Trong ví dụ này, chúng ta sẽ để UiFunMainScreen thực thi giao diện net.rim.device.api.ui.FieldChangeListener, trong phương thức này có một phương thức fieldChanged() để xử lý các sự kiện phát sinh trên các Field, cụ thể như sau:

public class UiFunMainScreen extends MainScreen implements FieldChangeListener {

public void fieldChanged(Field field, int context) {

}

2.     Xử lý Clear Button

Đầu tiên, chúng ta sẽ đăng ký sự kiện cho Clear Button như sau:

clearButton.setChangeListener(this);

Sau đó, trong phương thức fieldChanged(), chúng ta xử lý xự kiện cho Clear button; trong ví dụ này mỗi lần người dùng nhấn vào Clear button, chúng ta sẽ xuất một hộp hội thoại thông báo người dùng đã nhấn vào Clear buttton:

public void fieldChanged(Field field, int context) {

if (field == clearButton) {

Dialog.inform(“Clear Button Pressed!”);

}

}

Đến lúc này, nếu bạn chạy ứng dụng và nhấn vào Clear, ứng dụng sẽ hiển thị như sau:

Nếu bạn muốn sử dụng Clear button để xóa chuỗi text trên usename và password, bạn xây dựng một phương thức clearTextField() như sau:

 

private void clearTextFields() {

usernameField.setText(“”);

passwordField.setText(“”);

}

Sau đó, trong phương thức fieldChanged(), gọi phương thức clearTextField() như sau:

 

public void fieldChanged(Field field, int context) {

if (field == clearButton) {

clearTextFields();

}

}

3.     Xử lý Login button

Trong Login button , chúng ta kiểm tra nếu usename và password trống thì sẽ hiển thị một hộp thoại cảnh báo; ngược lại nếu chúng có dữ liệu thì chúng ta sẽ kích hoạt một màn hình mới để thông báo người dùng đã đăng nhập thành công.

3.1.                        Định nghĩa một màn hình mới

Trong mục này, chúng ta tạo ra một màn hình mới có tên LoginSuccessScreen, trong lớp này sẽ có 3 LabelField, label đầu tiên thông báo đã login thành công, 2 label còn lại hiển thị usename và domain.

package blog.mobilesprogramming.uifun;

import net.rim.device.api.ui.component.LabelField;

import net.rim.device.api.ui.container.MainScreen;

public class LoginSuccessScreen extends MainScreen {

public LoginSuccessScreen(String username, String domain) {

add(new LabelField(“Logged in!”));

add(new LabelField(“Username: ” + username));

add(new LabelField(“Domain: ” + domain));

}

}

3.2.                        Xây dựng phương thức login()

Chúng ta xây dựng phương thức login() để kiểm tra xem usename và password có trống hay không, nếu trống thì hiển thị một hộp hội thoại để cảnh báo; ngược lại thì hiển thị màn hình LoginSuccessScreen.
private void login() {

if (usernameField.getTextLength() == 0 || passwordField.getTextLength() == 0) {

Dialog.alert(“You must enter a username and password”);

}

else {

String username = usernameField.getText();

String selectedDomain =

(String)domainField.getChoice(domainField.getSelectedIndex());

LoginSuccessScreen loginSuccessScreen =

new LoginSuccessScreen(username, selectedDomain);

UiApplication.getUiApplication().pushScreen(loginSuccessScreen);

}

}

Tiếp theo,trong phương thức fieldChanged() của lớp UiFunMainScreen, chúng ta gọi phương thức login():

public void fieldChanged(Field field, int context) {

if (field == clearButton) {

clearTextFields();

}

else if (field == loginButton) {

login();

}

}

Lưu ý Bạn phải đăng ký sự kiện cho Login button bằng cách gọi phương thức

loginButton.setChangeListener(this);
Bây giờ, nếu bạn chạy ứng dụng và nhấn vào Login button thì sẽ có giao diện như sau:

Code

III.       Tạo Menu

Trên các thiết bị di động, việc cung cấp menu options cho các chức năng chính sẽ giúp dễ dàng truy cập hơn là sử dụng các button trên màn hình. Màn hình chịu trách nhiệm xử lý việc hiển thị menu và các menu item để thực thi các chức năng cho ứng dụng.

1.     Menu item

  • Các item trong menu là các thể hiện của lớp net.rim.device.api.ui.MenuItem. Lớp này là trừu tượng, và thực thi giao diện Runnable (nó có một phương thức run() mà bạn cần phải thực thi).
    Phương thức run() được thực thi trên event thread khi người dùng nhấp vào menu item, vì vậy bạn có thể thay đổi giao diện từ bên trong phương thức run() một cách an toàn. Điều này cũng có nghĩa là bạn không nên thực hiện các xử lý phép toán phức tạp hoặc kết nối mạng trong phương thức run(), thay vào đó bạn tạo một thread mới để thực hiện.
  • Mỗi menu item đều có ba mẩu thông tin liên kết với nó: chuỗi text để hiển thị, một
    thứ tự ưu tiên thực hiện(priority), và vị trí của nó xuất hiện trong menu(ordinal). Priority xác định menu item được highlight khi menu  được xuất hiện lần đầu tiên trên màn hình; item có giá trị thấp nhất thì có quyền ưu tiên cao nhất. Ordinal xác định vị trí mà item sẽ xuất hiện trong menu. Một menu item có giá trị ordinal thấp hơn sẽ nằm gần top của menu. Hai menu item cùng giá trị ordinal sẽ xuất hiện theo thứ tự mà chúng được thêm vào menu, từ trên xuống dưới.

2.     Cài đặt menu item Clear và Login

Chúng ta sẽ cài đặt 2 menu item trong ứng dụng tương ứng với các acton Login và Clear. Chúng ta sẽ tạo mỗi lớp tương ứng với mỗi menu item và khai báo các lớp là lớp lồng của lớp UiFunMainScreen – bởi vì ta chỉ cần sử dụng chúng để truy cập vào các phương thức private login() và clearTextField().

 

public class UiFunMainScreen extends MainScreen implements FieldChangeListener {

class LoginMenuItem extends MenuItem {

public LoginMenuItem() {

super(“Login”, 20, 10);

}

public void run() {

login();

}

}

class ClearMenuItem extends MenuItem {

public ClearMenuItem() {

super(“Clear”, 10, 20);

}

public void run() {

clearTextFields();

}

}

}

Lưu ý ClearMenuItem có giá trị oridinal thấp hơn và giá trị priority cao hơn LoginMenuItem. Vì vậy, item Clear sẽ nằm phía trên Login trong menu, nhưng item Login sẽ được highlight theo mặc định.

Có vài nơi để chúng ta có thể thêm các menu item. Thứ nhất là trong constructor của Screen, bằng cách gọi phương thức getMenu() và thêm các item vào đối tượng Menu. Thứ hai là ta sẽ override phương thức makeMenu() trong lớp Screen. Trong ví dụ này chúng ta sẽ override phương thức makeMenu() trong lớp UiFunMainScreen như sau:

protected void makeMenu(Menu menu, int instance) {

super.makeMenu(menu, instance);

menu.add(new LoginMenuItem());

menu.add(new ClearMenuItem());

}

Tùy thuộc vào mục đích của ứng dụng mà chúng ta muốn giữ item Close mặc định mà MainScreen đã đã tự động thêm vào cho chúng ta. Nếu muốn giữ nó thì gọi phương thức super.makeMenu(); ngược lại thì không cần gọi phương thức này.

Lưu ý Như bạn thấy, ở ví dụ trên chúng ta khai báo các menu item dưới dạng các lớp kế thừa từ lớp MenuItem một cách tường minh; tuy nhiên có một cách viết khác cũng hay được sử dụng đó là khai báo các menu item như là các lớp nội bộ(inner) vô danh, sử dụng cách này thường code ngắn gọn hơn; vì vậy bạn có thể sử dụng một trong 2 cách đã được trình bày. Sau đây là kỹ thuật sử lý lớp inner vô danh:

protected void makeMenu(Menu menu, int instance) {

super.makeMenu(menu, instance);

menu.add(new MenuItem(“Login”, 20, 10) {

public void run() {

login();

}

});

menu.add(new MenuItem(“Clear”, 10, 20) {

public void run() {

clearTextFields();

}

});

}

3.     Các giá trị intance của Menu

Tham số instance trong phương thức makeMenu() được sử dụng để xác định menu mà chúng ta sẽ hiển thị. Các ứng dụng BlackBerry hiển thị một vài menu khác nhau tùy thuộc vào menu được hiển thị và context của màn hình và điều khiển. Có các loại instance như sau:

  • Menu.INSTANCE_CONTEXT: menu được hiển thị bằng cách nhấp vào trackball. Thông thường, menu này là một tập hợp các item có sẵn trong menu mặc định được áp dụng đối với control đang được focus hoặc section của màn hình. Ví dụ, Close sẽ không hiển thị ở đây, thay vào đó BlackBerry sẽ tự động thêm một item Full Menu cho menu này, do tham số instance trong phương thức makeMenu() được gán giá trị INSTANCE_DEFAULT.
  • Menu.INSTANCE_CONTEXT_SELECTION : intance này cũng tương tự như INSTANCE_CONTEXT, nhưng menu được hiển thị khi người dùng có lựa chọn một đoạn văn bản nào đó. Bạn có thể sử dụng instance này khi bạn có thể sao chép văn bản.
  • Menu.INSTANCE_DEFAULT: Trong trường hợp này, menu được hiển thị bằng cách nhấn vào phím menu trên thiết bị. Menu này sẽ chứa tất cả các item trong context menu, item Close cũng được hiển thị ở đây.

Bạn thấy bài viết này thế nào?

Các bài liên quan:
Lập Trình Với Blackberry – Phần 1
Lập Trình Với Blackberry – Phần 2