Bài 2: Screen

I.Display screens

Cấu trúc chính cho một giao diện người dùng đó là đối tượng Screen. Mỗi ứng dụng chỉ hiển thị một đối tượng Screen tại mỗi một thời điểm.

Lưu ý Không nên sử dụng các đối tượng Screen cho text input. Lớp Screen không thực hiện định hướng (bởi việc định hướng đòi hỏi các phương thức input phức tạp). Đối với việc tích hợp các phương thức nhập input khác nhau, bạn có thể sử dụng các lớp kế thừa từ lớp Field hay các lớp con của nó.

1.Display stack

  • Các đối tượng Screen được giữ trong một display stack, một tập các đối tượng Screen có thứ tự. Screen tại top của stack sẽ được active và vẽ lên màn hình. Khi một ứng dụng hiển thị một màn hình, nó đẩy màn hình lên phía trên cùng của ngăn xếp. Khi một ứng dụng đóng một màn hình, nó lấy(pop) màn hình đó ra khỏi ngăn xếp và hiển thị màn hình kế tiếp trên stack, vẽ lại nó khi cần thiết.
  • Lưu ý Mỗi màn hình có thể chỉ xuất hiện một lần trong display stack. VM sẽ ném một ngoại lệ tại thời điểm runtime nếu cùng một màn hình được đẩy vào stack nhiều hơn một lần. Ứng dụng này phải lấy màn hình hiển thị ra khỏi display stack khi người dùng kết thúc tương tác với chúng để giải phóng bộ nhớ. Không sử dụng nhiều modal màn hình cùng một lúc, bởi vì mỗi màn hình sử dụng một thread riêng biệt.

2.Các loại Screen

Trong hầu hết các trường hợp, cách hiệu quả nhất để tạo một Screen là tạo ra một lớp mới kế thừa từ lớp Screen hay các lớp con của nó, là FullScreen hay MainScreen.

Class Description
Screen Sử dụng lớp Screen để định nghĩa trình quản lý layout các component UI trên màn hình và định nghĩa một loại màn hình chuyên biệt sử dụng style(được định nghĩa bởi các hằng constants trên lớp Field).
FullScreen Theo mặc định, một FullScreen chứa một field quản lý đơn theo chiều dọc. Sử dụng FullScreen để cung cấp một màn hình trống, mà bạn có thể thêm các thành phần UI để trong một layout theo chiều dọc tiêu chuẩn. Nếu bạn cần một loại layout khác, chẳng hạn như nằm ngang hoặc chéo, thì sử dụng lớp Screen và thêm một Manager cho nó.
MainScreen Lớp MainScreen cung cấp các tính năng được ứng dụng phổ biến trên các ứng dụng chuẩn BlackBerry. Sử dụng một đối tượng MainScreen cho màn hình đầu tiên của ứng dụng để duy trì tính nhất quán với các ứng dụng khác trên BlackBerry. Lớp MainScreen cung cấp các thành phần UI sau:

• Vị trí mặc định của title, với một SeparatorField sau title.

• Một phần cuộn chính được trong một VerticalFieldManager.

• Một menu mặc định với menu item Close.

• Một action đóng mặc định khi người dùng click vào menu item Close hay nhấn phím Escape.

II.Manage a drawing area

Đối tượng Graphics đại diện cho toàn bộ bề mặt (surface) drawing sẵn có trên các ứng dụng của thiết bị Blackberry. Để giới hạn vùng vẽ, phân chia nó bởi cách đối tượng XYRect. Mỗi đối tượng XYPoint đại diện cho một điểm trên màn hình, trong đó có các tọa độ (X,Y).

1.Import các lớp sau

  • net.rim.device.api.ui.Graphics
  • net.rim.device.api.ui.XYRect
  • net.rim.device.api.ui.XYPoint

2.Tạo đối tượng XYRect

Tạo ra 2 đối tượng XYPoint đại diện 2 điểm topLeft và bottomRight của hình chữ nhật. Tạo một đối tượng XYRect sử dụng 2 đối tượng XYPoint, để tạo ra vùng vẽ hình chữ nhật.

XYPoint bottomRight = new XYPoint(50, 50);
XYPoint topLeft = new XYPoint(10, 10);
XYRect rectangle = new XYRect(topLeft, bottomRight);

3.Gọi phương thức Graphics.pushContext()

Gọi phương thức Graphics.pushContext() để thực hiện lời gọi drawing, mà chỉ rõ rằng vùng vẽ gốc không nên điều chỉnh vị trí drawing. Gọi Graphics.pushContext() để push vùng clipping hình chữ nhật vào context stack. Gọi Graphics.drawRect() để vẽ một hình chữ nhật, và gọi Graphics.fillRect() để fill hình chữ nhật. Gọi Graphics.popContext() để pop context hiện tại ra khỏi context stack.

graphics.pushContext(rectangle, 0, 0);
graphics.fillRect(10, 10, 30, 30);
graphics.drawRect(15, 15, 30, 30);
graphics.popContext();
graphics.drawRect(15, 15, 30, 30);
graphics.pushContext(rectangle, 0, 0);
graphics.fillRect(10, 10, 30, 30);
graphics.drawRect(15, 15, 30, 30);
graphics.popContext();
graphics.drawRect(15, 15, 30, 30);

4.Gọi phương thức Graphics.pushRegion()

  • Gọi phương thức Graphics.pushRegion() và xác định rằng vùng vẽ gốc nên được điều chỉnh vị trí drawing. Gọi Graphics.drawRect() để vẽ một hình chữ nhật, và gọi Graphics.fillRect() để fill hình chữ nhật. Gọi Graphics.popContext() để pop context hiện tại ra khỏi context stack.

graphics.pushRegion(rectangle);
graphics.fillRect(10, 10, 30, 30);
graphics.drawRect(15, 15, 30, 30);
graphics.popContext();

  • Xác định các phần(portion) của đối tượng Graphics để push vào stack.
  • Sau khi gọi pushContext() (hay pushRegion()), cung cấp portion của đối tượng Graphics để invert.

graphics.pushContext(rectangle);
graphics.invert(rectangle);
graphics.popContext();

5.Gọi phương thức translate()

Gọi phương thức translate() để dịch chuyển XYRect từ tọa độ ban đầu(1,1) sang một tọa độ gốc mới (20,20). Sau khi dịch chuyển.

XYRect rectangle = new XYRect(1, 1, 100, 100);
XYPoint newLocation = new XYPoint(20, 20);
rectangle.translate(newLocation);

III.Tạo sự chuyển đổi màn hình

Bạn có thể tạo ra một sự chuyển đổi màn hình để áp dụng một hiệu ứng visual xuất hiện khi ứng dụng của bạn mở ra hoặc đóng một màn hình trên một thiết bị BlackBerry. Bạn có thể tạo ra các loại sau đây của quá trình chuyển đổi màn hình cho các ứng dụng của bạn bằng cách sử dụng lớp net.rim.device.api.ui.TransitionContext.

Transition Description
TRANSITION_FADE Quá trình chuyển đổi này bộc lộ hoặc loại bỏ một màn hình bằng cách đưa nó vào dần hoặc làm mờ dần nó. Chuyển đổi màn hình này tạo ra một hiệu ứng fading visual bằng cách thay đổi độ mờ của màn hình.
TRANSITION_SLIDE Quá trình chuyển đổi này bộc lộ hoặc loại bỏ một màn hình bằng cách trượt nó ON hoặc OFF trên màn hình hiển thị của thiết bị. Bạn có thể sử dụng các thuộc tính để xác định rằng cả màn hình mới và màn hình slide hiện tại, để tạo ra một hiệu ứng mà cả hai màn hình xuất hiện để di chuyển, hoặc màn hình mới lướt trên màn hình hiện hành.
TRANSITION_WIPE Quá trình chuyển đổi này bộc lộ hoặc loại bỏ một màn hình bằng cách wipe ON hoặc OFF màn hình hiển thị của thiết bị.
TRANSITION_ZOOM Quá trình chuyển đổi này bộc lộ hoặc loại bỏ một màn hình bằng cách phóng to hay thu nhỏ màn hình hiển thị của thiết bị.
TRANSITION_NONE Không sử dụng quá trình chuyển đổi.

Mỗi loại chuyển đổi màn hình có các thuộc tính mà bạn có thể sử dụng để tuỳ chỉnh các hiệu ứng visual của sự chuyển đổi màn hình. Ví dụ, bạn có thể tùy chỉnh hiệu ứng trượt để một màn hình trượt từ bottom của màn hình hiển thị đến top màn hình. Nếu bạn không tùy chỉnh sự chuyển đổi màn hình, ứng dụng sử dụng các thuộc tính mặc định.

Sau khi bạn tạo ra một sự chuyển đổi màn hình, bạn phải đăng ký nó bên trong ứng dụng của bạn bằng cách gọi UiEngineInstance.setTransition() và chỉ định các màn hình outgoing để loại bỏ và màn hình incoming để hiển thị, các sự kiện làm cho quá trình chuyển đổi xảy ra, và hiển thị lên màn hình.

Ví dụ: Tạo một screen transition

Đoạn mã sau minh họa một slide transition và một fade transition. Khi người dùng mở ứng dụng, màn hình đầu tiên xuất hiện trên thiết bị BlackBerry và hiển thị một Button. Khi người dùng click vào Button, một màn hình hiển thị thứ hai slide vào từ bên phải. Màn hình thứ hai sẽ tự động fade off màn hình hiển thị sau hai giây.

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;

public class ScreenTransitionSample extends UiApplication implements FieldChangeListener {
    private Screen _secondaryScreen;
    private Runnable _popRunnable;

    public static void main(String[] args) {
        ScreenTransitionSample theApp = new ScreenTransitionSample();
        theApp.enterEventDispatcher();
    }

    public ScreenTransitionSample () {        
        _secondaryScreen = new FullScreen();
        _secondaryScreen.setBackground( BackgroundFactory.createSolidBackground(Color.LIGHTBLUE));

        LabelField labelField = new LabelField("The screen closes automatically in two seconds by using a fade transition");
        _secondaryScreen.add(labelField);

        TransitionContext transition = new TransitionContext(TransitionContext.TRANSITION_SLIDE);
        transition.setIntAttribute(TransitionContext.ATTR_DURATION, 500);
        transition.setIntAttribute(TransitionContext.ATTR_DIRECTION, TransitionContext.DIRECTION_RIGHT);
        transition.setIntAttribute(TransitionContext.ATTR_STYLE, TransitionContext.STYLE_PUSH);

        UiEngineInstance engine = Ui.getUiEngineInstance();
        engine.setTransition(null, _secondaryScreen, UiEngineInstance.TRIGGER_PUSH, transition);

        transition = new TransitionContext(TransitionContext.TRANSITION_FADE);
        transition.setIntAttribute(TransitionContext.ATTR_DURATION, 500);
        transition.setIntAttribute(TransitionContext.ATTR_KIND, TransitionContext.KIND_OUT);
        engine.setTransition(_secondaryScreen, null, UiEngineInstance.TRIGGER_POP, transition); 

        MainScreen baseScreen = new MainScreen();
        baseScreen.setTitle("Screen Transition Sample");  

        ButtonField buttonField = new ButtonField("View Transition", ButtonField.CONSUME_CLICK) ;
        buttonField.setChangeListener(this);
        baseScreen.add(buttonField);

        pushScreen(baseScreen);

        _popRunnable = new Runnable() {
            public void run() {
                popScreen(_secondaryScreen);
            }
        };
    }

    public void fieldChanged(Field field, int context)
    {
        pushScreen(_secondaryScreen);
        invokeLater(_popRunnable, 2000, false);
    }
}

Các bài viết liên quan:
Tìm hiểu Blackberry - Phần 1