TÌM HIỂU ACTION BAR COMPAT TRONG ANDROID – PHẦN 1

ACTION BAR

Action Bar là một trong những yếu tố thiết kế quan trọng mà bạn có thể triển khai tới các activity (hoạt động) trong ứng dụng của bạn. Nó cung cấp một số tính năng giao diện người dùng mà làm cho ứng dụng của bạn ngay lập tức quen thuộc với người sử dụng bằng cách cung cấp tính nhất quán giữa các ứng dụng Android khác.

Các chức năng chính:

  • Một không gian dành riêng cho ứng dụng của bạn, nhận dạng và chỉ ra vị trí người sử dụng đang ở đâu trong ứng dụng.

  • Truy cập tới các hành động (Actions) quan trọng một cách dự đoán được (chẳng hạn như action tìm kiếm).

  • Hỗ trợ điều hướng và chuyển đổi giữa các view ( tabs và drop-down list).

Action bar

Action Bar API được thêm vào từ Android 3.0 (API 11) nhưng chúng có sẵn trong gói thư viện hỗ trợ (Android support libraries) với khả năng tương thích với Android 2.1 (API 7) trở lên. Bài hướng dẫn này tập trung vào việc làm thế nào để sử dụng Action bar bằng thư viện hỗ trợ (Android support). Nhưng nếu ứng dụng chỉ support chạy trên Android 3.0 trở lên bạn nên sử dụng ActionBar API framework.

Chú ý: Hãy chắc chắn rằng bạn import các lớp ActionBar (hoặc các API liên quan) từ gói (package) thích hợp:

  • Nếu support Android dưới 3.0 (API 11):
import android.support.v7.app.ActionBar
  • Nếu chỉ support Android 3.0 hoặc cao hơn:
import android.app.ActionBar

Thêm Action Bar:

Như đã đề cập ở trên, hướng dẫn này tập trung vào việc làm thế nào để sử dụng các API ActionBar trong thư viện hỗ trợ. Vì vậy, trước khi bạn có thể thêm action bar (thanh hành động), bạn phải thiết lập dự án của bạn với các thư viện hỗ trợ appcompat v7 bằng cách làm theo các hướng dẫn trong Setup Thư viện hỗ trợ. Một khi dự án của bạn được thiết lập với các thư viện hỗ trợ, đây là cách để thêm Action Bar:

Tạo 1 activity kế thừa từ lớp ActionBarActivity Sử dụng (hoặc kế thừa) một trong những Theme.AppCompat cho activity của bạn. Ví dụ:

  1. Tạo 1 activity kế thừa từ lớp ActionBarActivity

  2. Sử dụng (hoặc kế thừa) một trong những Theme.AppCompat cho activity của bạn. Ví dụ:

<activityandroid:theme="@style/Theme.AppCompat.Light" ... >

Bây giờ các Activity của bạn đã bao gốm Action Bar khi chạy trên Android 2.1 (API cấp 7) hoặc cao hơn.

Loại bỏ Action Bar:

Bạn có thể loại bỏ Action Bar bằng cách gọi phương thức hide(). Ví dụ:

ActionBar actionBar =getSupportActionBar();
actionBar.hide();

Note: Trên API level 11 hoặc cao hơn Nhận về đối tượng ActionBar bằng cách sử dụng phương thức getActionBar().

Sử dụng logo thay cho icon: Theo mặc định, hệ thống sử dụng biểu tượng ứng dụng (icon app) của bạn trong Action Bar, được mô tả trong thuộc tính icon (icon attribute) trong thẻ <application> hoặc <activity> . Tuy nhiên nếu bạn cũng chỉ rõ thuộc tính logo (logo attribute) trong các thẻ thì sau đấy Action Bar sẽ sử dụng logo thay cho icon.

Một logo thường rộng hơn so với các icon (biểu tượng), nhưng không nên bao gồm văn bản (text) không cần thiết. Thông thường bạn nên sử dụng một logo chỉ khi nó đại diện cho thương hiệu của bạn trong một định dạng thông thường mà người dùng nhận ra.

Thêm các mục Hành Động (Adding Action items)

Thanh thao tác cho phép người dùng truy cập vào các mục hành động (action items) quan trọng nhất liên quan đến bối cảnh hiện tại của ứng dụng.

Những thứ xuất hiện trực tiếp trong Action Bar với 1 biểu tượng (icon) hoặc văn bản (text) được gọi là các Nút Hành Động ( Action buttons). Những hành động không thể phù hợp (ko đủ vùng hiển thị) trong Action bar hoặc không đủ quan trọng được giấu trong hành động tràn (action overflow). Người dùng có thể tiết lộ một danh sách các hành động khác bằng cách nhấn vào nút tràn (overflow button) phía bên phải (hoặc nút Menu trên thiết bị, nếu có).

Khi hoạt động (Activity) của bạn bắt đầu, hệ thống này sẽ đưa lên các hàng hành động bằng cách gọi phương thức onCreateOptionsMenu () trong activity của bạn. Sử dụng phương pháp này để đưa ra nguồn tài nguyên của Menu mà định nghĩa tất cả các mục Action.

Ví dụ:

res/menu/main_activity_actions.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"/>
    <item android:id="@+id/action_compose"
          android:icon="@drawable/ic_action_compose"
          android:title="@string/action_compose"/></menu>

Sau đó, trong phương thức onCreateOptionsMenu() của bạn, inflate tài nguyên của Menu cho mỗi mục để thêm thanh hành động:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_activity_actions, menu);
    returnsuper.onCreateOptionsMenu(menu);
}

Để yêu cầu một item xuất hiện trực tiếp trong thanh action bar như một nút hành động (action button), thêm vào showAsAction = “ifRoom” trong <item> tag. Ví dụ:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto">
    <itemandroid:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

Nếu nó k đủ chỗ cho các mục trên Action Bar, chúng sẽ được xuất hiện trên action overflow.

Sử dụng thuộc tính XML từ gói thư viện hỗ trợ

Chú ý rằng các thuộc tính showAsAction trên sử dụng một không gian tên (namespaces) tùy chỉnh được định nghĩa trong thẻ <menu>. Điều này là cần thiết khi sử dụng bất kỳ các thuộc tính XML nào được định nghĩa bởi các thư viện hỗ trợ, bởi vì những thuộc tính này không tồn tại trong khuôn khổ Android trên các thiết bị cũ. Vì vậy, bạn phải sử dụng tên miền không gian riêng của bạn (Custom namespace) như là một tiền tố cho tất cả các thuộc tính được mô tả bởi các thư viện hỗ trợ.

Nếu menu của bạn cung cấp cả tiêu đề (title) và icon sử dụng thuộc tính title và icon trong XML, sau đấy menu sẽ chỉ show icon theo mặc định, Nếu bạn muốn hiển thị thêm tiêu đề, thêm thuộc tính “widthText” tới showAsAction. Ví dụ:

<item yourapp:showAsAction="ifRoom|withText" ... />

Chú ý: Các “withText” giá trị là một gợi ý (hint) cho các Action Bar rằng các tiêu đề văn bản sẽ xuất hiện. Action Bar sẽ hiển thị tiêu đề khi có thể, nhưng có thể không nếu một icon có sẵn và Action Bar bị hạn chế về không gian.

Bạn nên luôn luôn xác định “tiêu đề (title)” cho mỗi mục menu ngay cả khi bạn không khai báo rằng các tiêu đề sẽ xuất hiện với mục hành động (action item), vì những lý do sau đây:

  • Nếu không có đủ chỗ trong thanh Action Bar cho mục action, các mục này sẽ xuất hiện trong action tràn (action overflow) nơi chỉ tiêu đề xuất hiện.

  • Đọc tiêu đề màn hình cho người bị khiếm thính

  • Nếu các action item chỉ xuất hiện với Icon thì sau đó người dùng có thể giữ nhấn (long press) để hiển thị tiêu đề của item đó

Thuộc tính “icon” là không bắt buộc (optional), nhưng khuyến khích sử dụng. Bạn cũng có thể sử dụng “alway” trong showAsAction để tuyên bố rằng một mục luôn luôn xuất hiện như một nút hành động (action buttons). Tuy nhiên, bạn không thể bắt buộc một mục (menu item) xuất hiện trong Action bar theo cách này. Làm như vậy có thể tạo ra các vấn đề về bố cục trên các thiết bị với một màn hình hẹp. Cách tốt nhất sử dụng “ifRoom” trong showAsAction để yêu cầu một mục xuất hiện trong Action bar, nhưng cho phép hệ thống di chuyển nó vào overflow khi không có đủ khoảng trống. Tuy nhiên điều nay là cần thiết để yêu cầu xuất hiện các menu cung cấp các tính năng quan trọng trong màn hình.

Xử lý click tới các mục actions ( Handling clicks on action items )

Khi người dùng nhấn tới 1 action, hệ thông sẽ gọi tới phương thức onOptionsItemSelected() trong activity của bạn. Sử dụng MenuItem như đối số tới phương thức này, bạn có thể xác định các action bằng việc gọi getItemId(). Nó sẽ trả về một ID duy nhất cung cấp bởi thuộc tính “id” trong thẻ <item> vì vậy bạn có thể hoàn thành các hành động phù hợp.

@Override
public boolean onOptionsItemSelected(MenuItem item){
    // Handle presses on the action bar items
    switch(item.getItemId()){
        case R.id.action_search:
            openSearch();
            returntrue;
        case R.id.action_compose:
            composeMessage();
            returntrue;
        default:
            returnsuper.onOptionsItemSelected(item);
    }}

Chú ý: Nếu bạn inflate một menu từ Fragment, thì activity sẽ nhận được callback tới onOptionsItemSelected() trước và sau đó cũng gọi tới Fragment như vậy. Nên lưu ý để đảm bảo tất cả các fragment đều nhận được callback khi nhấn menu trong action bar, luôn luôn return false hoặc gọi super.onOptionsItemSelected(item); khi activity không xử lý chúng.

Sử dụng Action Bar chia rẽ (Using split action bar )

Thanh Action Bar chia rẽ có không gian riêng biệt ở dưới cùng (bottom screen) của màn hình để hiển thị tất cả nút hành động (action items) khi activity này đang chạy trên một màn hình nhỏ (chẳng hạn như một chiếc điện thoại để chiểu thẳng đứng (portrait).

alt

Hình 3. Mock-up hiển thị một Action bar (AB) với các tab (trái), sau đó dùng split AB (giữa); và với các icon app và title bị vô hiệu hóa (phải).

Tách biệt các hành động (action items) theo cách này đảm bảo rằng một không gian hợp lý có sẵn để hiển thị tất cả các hành động của bạn trên một màn hình nhỏ hẹp, khi rời khỏi màn hình này các thanh điều hướng lại trở về đầu trang (on top). Để kích hoạt Split action bar sử dụng thư viện hỗ trợ (android support libraries), bạn phải 2 điều sau đây:

  1. Thêm uiOptions=”splitActionBarWhenNarrow” tới mỗi thành phần <activity> hoặc tới thành phần <application>. Thuộc tính này chỉ được hiểu bởi API level 14 và cao hơn (nó sẽ được bỏ qua bởi các phiên bản cũ).

  2. Để support phiên bản cũ, thêm thành phần <meta-data> nằm trong mỗi thành phần <activity> và khai báo giá trị cho “android.support.UI_OPTIONS” tương tự như trên

Ví dụ:

<manifest ...>
    <activityuiOptions="splitActionBarWhenNarrow" ... >
        <meta-dataandroid:name="android.support.UI_OPTIONS"
                   android:value="splitActionBarWhenNarrow"/>
    </activity>
</manifest>

Sử dụng Split Action bar cũng cho phép các Tab điều hướng (navigation tabs) thu vào Action Bar nếu bạn loại bỏ icon và title (như bên phải Hình 3). Để tạo hiệu ứng này, bạn disable Action Bar icon và title với setDisplayShowHomeEnabled(false)setDisplayShowTitleEnabled(false).

alt

Ví dụ:

Nếu màn hình A sẽ hiển thị một danh sách các mục, và chọn một mục (select item) dẫn đến màn hình B, sau đó màn hình B nên bao gồm nút Up để trở về màn hình A.

Chú ý: Nút Up chuyển hướng khác với việc chuyển hướng trở lại của nút Back trong hệ thống. Các nút Back được sử dụng để di chuyển trong trật tự thời gian đảo ngược thông qua lịch sử của màn hình người sử dụng đã làm việc. Nó thường được dựa trên mối quan hệ thời gian giữa màn hình, chứ không phải là cấu trúc phân cấp của ứng dụng (đó là cơ sở để lập định hướng).

Để kích hoạt App Icon như là nút Up (Up button), gọi phương thức setDisplayHomeAsUpEnabled().

Ví dụ:

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);

    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    ...}

Bây giờ App Icon sẽ được hiển thị như hình 4. Tuy nhiên, nó sẽ không làm bất cứ điều gì theo mặc định. Để xác định các hoạt động để mở ra khi người dùng nhấn nút Up, bạn có hai lựa chọn:

Đây là tùy chọn tốt nhất khi để thực hiện việc nhấn Up. Bằng cách khai báo trong Manifest 1 activity là parrent class (lớp cha), Action Bar sẽ tự động thực hiện các hành động chính xác khi người dùng nhấn nút Up. Bắt đầu từ Android 4.1 (API 16), bạn có thể khai báo parrent class cho activity với thuộc tính parentActivityName trong thành phần <activity>. Để hỗ trợ các thiết bị API cũ hơn với thư viện hỗ trợ, cũng thêm vào một thành phần <meta-data> cung cấp parrent class cho activity như là giá trị của android.support.PARENT_ACTIVITY. Ví dụ:

<application ... >
    ...
    <!-- The main/home activity (has no parent activity) -->
    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity">
        <!-- Parent activity meta-data to support API level 7+ -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity"/>
    </activity>
</application>

Một khi lớp cha mẹ cho 1 activiy được mô tả trong manifest như trên và bạn kích hoạt nút Up với setDisplayHomeAsUpEnabled(), công việc của bạn đã hoàn thành và Activity đã có thể điều hướng Up.

Hoặc ghi đè (Override) getSupportParentActivityIntent()onCreateSupportNavigateUpTaskStack() trong activity của bạn.

Điều này phù hợp khi các lớp cha mẹ có thể khác nhau tùy thuộc vào cách sử dụng màn hình hiện tại.

Hệ thống gọi getSupportParentActivityIntent () khi người dùng nhấn nút Up trong khi điều hướng ứng dụng của bạn. Sau đó bạn ghi đề lại phương thức này và trả về Intent phù hợp với tương tác ở thời điểm hiện tại.

Hệ thống gọi onCreateSupportNavigateUpTaskStack () cho hoạt động của bạn khi người dùng nhấn nút Up trong khi hoạt động của bạn đang chạy trong một nhiệm vụ mà không thuộc về ứng dụng của bạn. Như vậy, bạn phải sử dụng các TaskStackBuilder truyền tới phương pháp này để xây dựng các ngăn xếp lại phù hợp cần được tổng hợp khi người dùng điều hướng Up lên.

Thậm chí nếu bạn ghi đè lên getSupportParentActivityIntent () để xác định điều hướng Up, bạn có thể tránh được sự cần thiết phải thực hiện onCreateSupportNavigateUpTaskStack () bằng cách tuyên bố “default” tới các activity cha mẹ trong các tập tin manifest như trên. Sau đó thực hiện mặc định của onCreateSupportNavigateUpTaskStack () sẽ tổng hợp một chồng lại dựa trên các hoạt động cha mẹ tuyên bố trong biểu hiện. Sau đó thực hiện mặc định của onCreateSupportNavigateUpTaskStack () sẽ tổng hợp lại stack dựa trên các parent activity được khai báo trong Manifest. Chú ý: Nếu bạn đã xây dựng hệ thống phân cấp ứng dụng của bạn bằng cách sử dụng một loạt các Fragment thay vì nhiều activities, sau đó không phương thức nào trong số các tùy chọn ở trên sẽ làm việc. Thay vào đó, để di chuyển lên (Up) qua những fragment của bạn, bạn phải ghi đè onSupportNavigateUp () để thực hiện Fragment transaction – thường xuyên bằng cách popping current Fragment từ các ngăn xếp bằng cách gọi popBackStack ().

Mã nguồn: ActionBarCompat

Require: Android Support Libraries V7


All Rights Reserved