Thêm bản xem trước vào trình chọn tiện ích

Để cải thiện trải nghiệm của trình chọn tiện ích trong ứng dụng, hãy cung cấp bản xem trước tiện ích đã tạo trên các thiết bị Android 15 trở lên, bản xem trước tiện ích được điều chỉnh theo tỷ lệ (bằng cách chỉ định một previewLayout) cho các thiết bị Android 12 đến Android 14 và một previewImage cho các phiên bản trước đó.

Bản xem trước tiện ích được tạo cho phép bạn tạo bản xem trước động, phù hợp với từng cá nhân cho các tiện ích của mình, phản ánh chính xác cách các tiện ích đó sẽ xuất hiện trên màn hình chính của người dùng. Đối với Android 15 trở lên, các bản xem trước này được cung cấp thông qua một API truyền dữ liệu, tức là ứng dụng của bạn cung cấp bản xem trước tại bất kỳ thời điểm nào trong vòng đời của ứng dụng mà không cần nhận được yêu cầu rõ ràng từ máy chủ lưu trữ tiện ích.

Để biết thêm thông tin, hãy xem video Làm phong phú ứng dụng bằng thông tin cập nhật trực tiếp và tiện ích trên YouTube.

Thêm bản xem trước được tạo

Để hiển thị Bản xem trước của tiện ích đã tạo trên thiết bị Android 15 trở lên, trước tiên, hãy đặt giá trị compileSdk thành 35 trở lên trong tệp build.gradle của mô-đun để có thể cung cấp RemoteViews cho bộ chọn tiện ích

Các ứng dụng có thể sử dụng setWidgetPreview trong AppWidgetManager. Để ngăn chặn hành vi sai trái và giảm thiểu các vấn đề về tình trạng hệ thống, setWidgetPreview là một API bị giới hạn tốc độ. Hạn mức mặc định là khoảng 2 cuộc gọi mỗi giờ.

Không có lệnh gọi lại từ hệ thống để cung cấp bản xem trước, vì vậy, ứng dụng của bạn phải quyết định thời điểm gọi setWidgetPreviews. Chiến lược cập nhật phụ thuộc vào trường hợp sử dụng của tiện ích:

  • Nếu tiện ích có thông tin tĩnh hoặc là một thao tác nhanh, hãy đặt bản xem trước khi ứng dụng được khởi chạy lần đầu.
  • Bạn có thể đặt bản xem trước sau khi ứng dụng có dữ liệu; ví dụ: sau khi người dùng đăng nhập hoặc thiết lập ban đầu.
  • Bạn có thể thiết lập một tác vụ định kỳ để cập nhật bản xem trước theo nhịp độ đã chọn.

Ví dụ sau đây tải một tài nguyên bố cục tiện ích XML và đặt tài nguyên đó làm bản xem trước. Bạn phải có chế độ cài đặt bản dựng compileSdk từ 35 trở lên để setWidgetPreview xuất hiện dưới dạng một phương thức trong đoạn mã này.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    RemoteViews("com.example", R.layout.widget_preview)
)

Thêm bản xem trước tiện ích có thể mở rộng

Kể từ Android 12, bản xem trước tiện ích xuất hiện trong bộ chọn tiện ích có thể điều chỉnh kích thước. Bạn cung cấp bố cục này dưới dạng một bố cục XML được đặt thành kích thước mặc định của tiện ích. Trước đây, bản xem trước tiện ích là một tài nguyên có thể vẽ tĩnh, trong một số trường hợp, điều này dẫn đến việc bản xem trước phản ánh không chính xác cách tiện ích xuất hiện khi được thêm vào màn hình chính.

Để triển khai bản xem trước tiện ích có thể mở rộng, hãy sử dụng thuộc tính previewLayout của phần tử appwidget-provider để cung cấp một bố cục XML thay thế:

<appwidget-provider
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>

Bạn nên sử dụng cùng một bố cục như tiện ích thực tế, với các giá trị mặc định hoặc giá trị kiểm thử thực tế. Hầu hết các ứng dụng đều dùng cùng một previewLayoutinitialLayout. Để biết hướng dẫn về cách tạo bố cục xem trước chính xác, hãy xem phần Tạo bản xem trước chính xác bao gồm các mục động.

Bạn nên chỉ định cả thuộc tính previewLayoutpreviewImage để ứng dụng của bạn có thể quay lại sử dụng previewImage nếu thiết bị của người dùng không hỗ trợ previewLayout. Thuộc tính previewLayout được ưu tiên hơn thuộc tính previewImage.

Thêm bản xem trước tiện ích tĩnh để tương thích ngược

Để cho phép bộ chọn tiện ích trên Android 11 (cấp độ API 30) trở xuống hiển thị bản xem trước tiện ích của bạn hoặc làm phương án dự phòng cho bản xem trước có thể mở rộng, hãy chỉ định thuộc tính previewImage.

Nếu bạn thay đổi giao diện của tiện ích, hãy cập nhật hình ảnh xem trước.

Thuộc tính này cũng được dùng làm phương án dự phòng cho bản xem trước được tạo nếu bạn chưa đặt một bản xem trước bằng cách sử dụng setWidgetPreview.

Tạo bản xem trước chính xác có chứa các mục động

Hình 1: Bản xem trước tiện ích không hiển thị mục nào trong danh sách.

Phần này giải thích phương pháp được đề xuất để hiển thị nhiều mục trong bản xem trước tiện ích cho một tiện ích có khung hiển thị tập hợp, tức là một tiện ích sử dụng ListView, GridView hoặc StackView. Điều này áp dụng cho bản xem trước của tiện ích có thể mở rộng, chứ không áp dụng cho bản xem trước được tạo.

Nếu tiện ích của bạn sử dụng một trong các thành phần hiển thị này, thì việc tạo bản xem trước có thể mở rộng bằng cách cung cấp trực tiếp bố cục tiện ích thực tế trong previewLayout có thể làm giảm trải nghiệm khi bản xem trước tiện ích không hiển thị mục nào. Điều này xảy ra vì dữ liệu của khung hiển thị bộ sưu tập được đặt linh động trong thời gian chạy và trông tương tự như hình ảnh minh hoạ trong hình 1.

Để bản xem trước của các tiện ích có khung hiển thị tập hợp hiển thị đúng cách trong bộ chọn tiện ích, bạn nên duy trì một tệp bố cục riêng biệt chỉ dành cho bản xem trước. Tệp bố cục riêng biệt này phải bao gồm những nội dung sau:

  • Bố cục thực tế của tiện ích.
  • Một khung hiển thị tập hợp phần giữ chỗ có các mục giả. Ví dụ: bạn có thể mô phỏng một ListView bằng cách cung cấp một phần giữ chỗ LinearLayout với một số mục danh sách giả.

Để minh hoạ ví dụ về ListView, hãy bắt đầu bằng một tệp bố cục riêng biệt:

// res/layout/widget_preview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/widget_background"
   android:orientation="vertical">

    // Include the actual widget layout that contains ListView.
    <include
        layout="@layout/widget_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    // The number of fake items you include depends on the values you provide
    // for minHeight or targetCellHeight in the AppWidgetProviderInfo
    // definition.

    <TextView android:text="@string/fake_item1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

    <TextView android:text="@string/fake_item2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

</LinearLayout>

Chỉ định tệp bố cục xem trước khi cung cấp thuộc tính previewLayout của siêu dữ liệu AppWidgetProviderInfo. Bạn vẫn chỉ định bố cục tiện ích thực tế cho thuộc tính initialLayout và sử dụng bố cục tiện ích thực tế khi tạo RemoteViews trong thời gian chạy.

<appwidget-provider
    previewLayout="@layout/widget_preview"
    initialLayout="@layout/widget_view" />

Các mục phức tạp trong danh sách

Ví dụ trong phần trước cung cấp các mục giả trong danh sách, vì các mục trong danh sách là các đối tượng TextView. Việc cung cấp các mục giả có thể phức tạp hơn nếu các mục đó có bố cục phức tạp.

Hãy xem xét một mục danh sách được xác định trong widget_list_item.xml và bao gồm hai đối tượng TextView:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView android:id="@id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_title" />

    <TextView android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_content" />
</LinearLayout>

Để cung cấp các mục giả trong danh sách, bạn có thể thêm bố cục nhiều lần, nhưng điều này khiến mỗi mục trong danh sách đều giống hệt nhau. Để cung cấp các mục duy nhất trong danh sách, hãy làm theo các bước sau:

  1. Tạo một nhóm thuộc tính cho các giá trị văn bản:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. Sử dụng các thuộc tính này để đặt văn bản:

    <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        <TextView android:id="@id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetTitle" />
    
        <TextView android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetContent" />
    </LinearLayout>
    
  3. Tạo bao nhiêu kiểu tuỳ ý cho bản xem trước. Xác định lại các giá trị trong từng kiểu:

    <resources>
    
        <style name="Theme.Widget.ListItem">
            <item name="widgetTitle"></item>
            <item name="widgetContent"></item>
        </style>
        <style name="Theme.Widget.ListItem.Preview1">
            <item name="widgetTitle">Fake Title 1</item>
            <item name="widgetContent">Fake content 1</item>
        </style>
        <style name="Theme.Widget.ListItem.Preview2">
            <item name="widgetTitle">Fake title 2</item>
            <item name="widgetContent">Fake content 2</item>
        </style>
    
    </resources>
    
  4. Áp dụng các kiểu cho các mục giả trong bố cục xem trước:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" ...>
    
        <include layout="@layout/widget_view" ... />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview1" />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview2" />
    
    </LinearLayout>