Mẫu lát cắt

Tài liệu này cung cấp chi tiết về cách sử dụng trình tạo mẫu trong Android Jetpack để tạo Lát cắt.

Xác định mẫu Lát cắt

Lát cắt được tạo bằng cách sử dụng ListBuilder. Trình tạo danh sách cho phép bạn thêm các loại hàng khác nhau được hiển thị trong danh sách. Chiến dịch này mô tả từng loại hàng trong số đó và cách chúng được tạo.

Hành động cắt

Phần tử cơ bản nhất của mẫu Lát cắt là SliceAction. Một SliceAction chứa nhãn cùng với PendingIntent và là một trong những sau:

  • Nút biểu tượng
  • Bật/tắt mặc định
  • Nút bật/tắt tuỳ chỉnh (một đối tượng có thể vẽ có trạng thái bật/tắt)

SliceAction được các trình tạo mẫu mô tả trong phần còn lại của tài liệu này sử dụng . SliceAction có thể có chế độ hình ảnh được xác định để xác định cách hình ảnh cho thao tác:

  • ICON_IMAGE: kích thước nhỏ và có thể phủ màu
  • SMALL_IMAGE: kích thước nhỏ và không phủ màu
  • LARGE_IMAGE: kích thước lớn nhất và không phủ màu

Trình tạo tiêu đề

Trong hầu hết các trường hợp, bạn nên đặt tiêu đề cho mẫu bằng cách sử dụng HeaderBuilder. Tiêu đề có thể hỗ trợ những nội dung sau:

  • Tiêu đề
  • Phụ đề
  • Phụ đề của phần tóm tắt
  • Tác vụ chính

Dưới đây là một số ví dụ về cấu hình tiêu đề. Lưu ý rằng hộp màu xám hiển thị vị trí biểu tượng và khoảng đệm tiềm năng:

Hiển thị tiêu đề trên nhiều nền tảng

Khi cần một Lát cắt, giao diện hiển thị sẽ xác định cách kết xuất Lát cắt. Lưu ý rằng việc hiển thị có thể khác nhau đôi chút giữa các nền tảng lưu trữ.

Ở các định dạng nhỏ hơn, thường chỉ có tiêu đề được hiển thị, nếu có. Nếu bạn đã chỉ định nội dung tóm tắt cho tiêu đề, thì văn bản tóm tắt sẽ được hiển thị thay vì văn bản phụ đề.

Nếu bạn chưa chỉ định tiêu đề trong mẫu, hàng đầu tiên sẽ được thêm vào ListBuilder thường được hiển thị thay thế.

Ví dụ về HeaderBuilder – Lát cắt danh sách đơn giản có tiêu đề

Kotlin

fun createSliceWithHeader(sliceUri: Uri) =
    list(context, sliceUri, ListBuilder.INFINITY) {
        setAccentColor(0xff0F9D) // Specify color for tinting icons
        header {
            title = "Get a ride"
            subtitle = "Ride in 4 min"
            summary = "Work in 1 hour 45 min | Home in 12 min"
        }
        row {
            title = "Home"
            subtitle = "12 miles | 12 min | $9.00"
            addEndItem(
                IconCompat.createWithResource(context, R.drawable.ic_home),
                ListBuilder.ICON_IMAGE
            )
        }
    }

Java

public Slice createSliceWithHeader(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }

    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .setAccentColor(0xff0F9D58) // Specify color for tinting icons.
            .setHeader( // Create the header and add to slice.
                    new HeaderBuilder()
                            .setTitle("Get a ride")
                            .setSubtitle("Ride in 4 min.")
                            .setSummary("Work in 1 hour 45 min | Home in 12 min.")
            ).addRow(new RowBuilder() // Add a row.
                    .setPrimaryAction(
                            createActivityAction()) // A slice always needs a SliceAction.
                    .setTitle("Home")
                    .setSubtitle("12 miles | 12 min | $9.00")
                    .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_home),
                            SliceHints.ICON_IMAGE)
            ); // Add more rows if needed...
    return listBuilder.build();
}

SliceAction trong tiêu đề

Tiêu đề của Lát cắt cũng có thể hiển thị SliceActions:

Kotlin

fun createSliceWithActionInHeader(sliceUri: Uri): Slice {
    // Construct our slice actions.
    val noteAction = SliceAction.create(
        takeNoteIntent,
        IconCompat.createWithResource(context, R.drawable.ic_pencil),
        ICON_IMAGE,
        "Take note"
    )

    val voiceNoteAction = SliceAction.create(
        voiceNoteIntent,
        IconCompat.createWithResource(context, R.drawable.ic_mic),
        ICON_IMAGE,
        "Take voice note"
    )

    val cameraNoteAction = SliceAction.create(
        cameraNoteIntent,
        IconCompat.createWithResource(context, R.drawable.ic_camera),
        ICON_IMAGE,
        "Create photo note"
    )

    // Construct the list.
    return list(context, sliceUri, ListBuilder.INFINITY) {
        setAccentColor(0xfff4b4) // Specify color for tinting icons
        header {
            title = "Create new note"
            subtitle = "Easily done with this note taking app"
        }
        addAction(noteAction)
        addAction(voiceNoteAction)
        addAction(cameraNoteAction)
    }
}

Java

public Slice createSliceWithActionInHeader(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct our slice actions.
    SliceAction noteAction = SliceAction.create(takeNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_pencil),
            ListBuilder.ICON_IMAGE, "Take note");

    SliceAction voiceNoteAction = SliceAction.create(voiceNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_mic),
            ListBuilder.ICON_IMAGE,
            "Take voice note");

    SliceAction cameraNoteAction = SliceAction.create(cameraNoteIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_camera),
            ListBuilder.ICON_IMAGE,
            "Create photo note");


    // Construct the list.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .setAccentColor(0xfff4b400) // Specify color for tinting icons
            .setHeader(new HeaderBuilder() // Construct the header.
                    .setTitle("Create new note")
                    .setSubtitle("Easily done with this note taking app")
            )
            .addRow(new RowBuilder()
                    .setTitle("Enter app")
                    .setPrimaryAction(createActivityAction())
            )
            // Add the actions to the ListBuilder.
            .addAction(noteAction)
            .addAction(voiceNoteAction)
            .addAction(cameraNoteAction);
    return listBuilder.build();
}

Trình tạo hàng

Bạn có thể xây dựng một hàng nội dung bằng cách sử dụng RowBuilder. Một hàng có thể hỗ trợ bất kỳ nội dung nào sau đây:

  • Tiêu đề
  • Phụ đề
  • Mục bắt đầu: SliceAction, Biểu tượng hoặc dấu thời gian
  • Mục kết thúc: SliceAction, Biểu tượng hoặc dấu thời gian
  • Tác vụ chính

Bạn có thể kết hợp nội dung hàng theo một số cách, tuỳ thuộc vào hạn chế:

  • Các mục bắt đầu sẽ không xuất hiện ở hàng đầu tiên của Lát cắt
  • Mục cuối không được kết hợp đối tượng SliceAction và đối tượng Icon
  • Một hàng chỉ có thể chứa một dấu thời gian

Các hàng nội dung mẫu sẽ xuất hiện trong các hình ảnh sau. Lưu ý rằng hộp màu xám hiển thị vị trí biểu tượng và khoảng đệm tiềm năng:

Ví dụ về RowBuilder – Bật/tắt Wi-Fi

Ví dụ bên dưới minh hoạ một hàng có thao tác chính và nút bật/tắt mặc định.

Kotlin

fun createActionWithActionInRow(sliceUri: Uri): Slice {
    // Primary action - open wifi settings.
    val wifiAction = SliceAction.create(
        wifiSettingsPendingIntent,
        IconCompat.createWithResource(context, R.drawable.ic_wifi),
        ICON_IMAGE,
        "Wi-Fi Settings"
    )

    // Toggle action - toggle wifi.
    val toggleAction = SliceAction.createToggle(
        wifiTogglePendingIntent,
        "Toggle Wi-Fi",
        isConnected /* isChecked */
    )

    // Create the parent builder.
    return list(context, wifiUri, ListBuilder.INFINITY) {
        setAccentColor(0xff4285) // Specify color for tinting icons / controls.
        row {
            title = "Wi-Fi"
            primaryAction = wifiAction
            addEndItem(toggleAction)
        }
    }
}

Java

public Slice createActionWithActionInRow(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Primary action - open wifi settings.
    SliceAction primaryAction = SliceAction.create(wifiSettingsPendingIntent,
            IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
            ListBuilder.ICON_IMAGE,
            "Wi-Fi Settings"
    );

    // Toggle action - toggle wifi.
    SliceAction toggleAction = SliceAction.createToggle(wifiTogglePendingIntent,
            "Toggle Wi-Fi", isConnected /* isChecked */);

    // Create the parent builder.
    ListBuilder listBuilder = new ListBuilder(getContext(), wifiUri, ListBuilder.INFINITY)
            // Specify color for tinting icons / controls.
            .setAccentColor(0xff4285f4)
            // Create and add a row.
            .addRow(new RowBuilder()
                    .setTitle("Wi-Fi")
                    .setPrimaryAction(primaryAction)
                    .addEndItem(toggleAction));
    // Build the slice.
    return listBuilder.build();
}

Trình tạo lưới

Bạn có thể xây dựng một lưới nội dung bằng cách sử dụng GridBuilder. Một lưới có thể hỗ trợ các loại hình ảnh sau:

  • ICON_IMAGE: kích thước nhỏ và có thể phủ màu
  • SMALL_IMAGE: kích thước nhỏ và không phủ màu
  • LARGE_IMAGE: kích thước lớn nhất và không phủ màu

Một ô lưới được xây dựng bằng cách sử dụng CellBuilder. Đáp ô có thể hỗ trợ tối đa hai dòng văn bản và một hình ảnh. Không được để trống ô.

Ví dụ về lưới được thể hiện trong các hình sau:

Ví dụ về GridRowBuilder – Nhà hàng lân cận

Ví dụ bên dưới minh hoạ một hàng lưới chứa hình ảnh và văn bản.

Kotlin

fun createSliceWithGridRow(sliceUri: Uri): Slice {
    // Create the parent builder.
    return list(context, sliceUri, ListBuilder.INFINITY) {
        header {
            title = "Famous restaurants"
            primaryAction = SliceAction.create(
                pendingIntent, icon, ListBuilder.ICON_IMAGE, "Famous restaurants"
            )
        }
        gridRow {
            cell {
                addImage(image1, LARGE_IMAGE)
                addTitleText("Top Restaurant")
                addText("0.3 mil")
                contentIntent = intent1
            }
            cell {
                addImage(image2, LARGE_IMAGE)
                addTitleText("Fast and Casual")
                addText("0.5 mil")
                contentIntent = intent2
            }
            cell {
                addImage(image3, LARGE_IMAGE)
                addTitleText("Casual Diner")
                addText("0.9 mi")
                contentIntent = intent3
            }
            cell {
                addImage(image4, LARGE_IMAGE)
                addTitleText("Ramen Spot")
                addText("1.2 mi")
                contentIntent = intent4
            }
        }
    }
}

Java

public Slice createSliceWithGridRow(Uri sliceUri) {
      if (getContext() == null) {
          return null;
      }
      // Create the parent builder.
      ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
              .setHeader(
                      // Create the header.
                      new HeaderBuilder()
                              .setTitle("Famous restaurants")
                              .setPrimaryAction(SliceAction
                                      .create(pendingIntent, icon, ListBuilder.ICON_IMAGE,
                                              "Famous restaurants"))
              )
              // Add a grid row to the list.
              .addGridRow(new GridRowBuilder()
                      // Add cells to the grid row.
                      .addCell(new CellBuilder()
                              .addImage(image1, ListBuilder.LARGE_IMAGE)
                              .addTitleText("Top Restaurant")
                              .addText("0.3 mil")
                              .setContentIntent(intent1)
                      ).addCell(new CellBuilder()
                              .addImage(image2, ListBuilder.LARGE_IMAGE)
                              .addTitleText("Fast and Casual")
                              .addText("0.5 mil")
                              .setContentIntent(intent2)
                      )
                      .addCell(new CellBuilder()
                              .addImage(image3, ListBuilder.LARGE_IMAGE)
                              .addTitleText("Casual Diner")
                              .addText("0.9 mi")
                              .setContentIntent(intent3))
                      .addCell(new CellBuilder()
                              .addImage(image4, ListBuilder.LARGE_IMAGE)
                              .addTitleText("Ramen Spot")
                              .addText("1.2 mi")
                              .setContentIntent(intent4))
                      // Every slice needs a primary action.
                      .setPrimaryAction(createActivityAction())
              );
      return listBuilder.build();
  }

Trình tạo phạm vi

RangeBuilder! bạn có thể tạo một hàng chứa thanh tiến trình hoặc dải ô nhập, chẳng hạn như làm thanh trượt.

Ví dụ về tiến trình và thanh trượt được thể hiện trong các hình sau:

Ví dụ về RangeBuilder – Thanh trượt

Ví dụ bên dưới minh hoạ cách tạo một Lát cắt chứa một ổ đĩa thanh trượt bằng cách sử dụng InputRangeBuilder. Để tạo một hàng tiến trình, hãy sử dụng addRange().

Kotlin

fun createSliceWithRange(sliceUri: Uri): Slice {
    return list(context, sliceUri, ListBuilder.INFINITY) {
        inputRange {
            title = "Ring Volume"
            inputAction = volumeChangedPendingIntent
            max = 100
            value = 30
        }
    }
}

Java

public Slice createSliceWithRange(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new RowBuilder() // Every slice needs a row.
                    .setTitle("Enter app")
                      // Every slice needs a primary action.
                    .setPrimaryAction(createActivityAction())
            )
            .addInputRange(new InputRangeBuilder() // Create the input row.
                    .setTitle("Ring Volume")
                    .setInputAction(volumeChangedPendingIntent)
                    .setMax(100)
                    .setValue(30)
            );
    return listBuilder.build();
}

Nội dung bị trễ

Bạn nên trả về một Lát cắt nhanh nhất có thể từ SliceProvider.onBindSlice(). Cuộc gọi tốn thời gian có thể dẫn đến các sự cố hiển thị, chẳng hạn như nhấp nháy và đột ngột đổi kích thước.

Nếu nội dung Lát cắt không thể tải nhanh chóng, bạn có thể tạo Lát cắt với nội dung giữ chỗ trong khi lưu ý trong trình tạo rằng đang tải nội dung. Khi nội dung đã sẵn sàng để hiển thị, hãy gọi getContentResolver().notifyChange(sliceUri, null) bằng cách sử dụng URI Lát cắt của bạn. Điều này dẫn đến một cuộc gọi khác tới SliceProvider.onBindSlice(), nơi bạn có thể tạo lại Lát cắt bằng nội dung.

Ví dụ về nội dung bị trễ – Đi đến cơ quan

Trong hàng Đi đến nơi làm việc bên dưới, khoảng cách đến cơ quan được xác định tự động và có thể chưa dùng được ngay. Mã ví dụ minh hoạ việc sử dụng làm tiêu đề phụ rỗng trong khi tải nội dung:

Kotlin

fun createSliceShowingLoading(sliceUri: Uri): Slice {
    // We’re waiting to load the time to work so indicate that on the slice by
    // setting the subtitle with the overloaded method and indicate true.
    return list(context, sliceUri, ListBuilder.INFINITY) {
        row {
            title = "Ride to work"
            setSubtitle(null, true)
            addEndItem(IconCompat.createWithResource(context, R.drawable.ic_work), ICON_IMAGE)
        }
    }
}

Java

public Slice createSliceShowingLoading(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    // Construct the parent.
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            // Construct the row.
            .addRow(new RowBuilder()
                    .setPrimaryAction(createActivityAction())
                    .setTitle("Ride to work")
                    // We’re waiting to load the time to work so indicate that on the slice by
                    // setting the subtitle with the overloaded method and indicate true.
                    .setSubtitle(null, true)
                    .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_work),
                            ListBuilder.ICON_IMAGE)
            );
    return listBuilder.build();
}

private SliceAction createActivityAction() {
    return SliceAction.create(
            PendingIntent.getActivity(
                    getContext(),
                    0,
                    new Intent(getContext(), MainActivity.class),
                    0
            ),
            IconCompat.createWithResource(getContext(), R.drawable.ic_home),
            ListBuilder.ICON_IMAGE,
            "Enter app"
    );
}

Xử lý thao tác cuộn bị vô hiệu hoá trong Lát cắt của bạn

Nền tảng thể hiện mẫu Lát cắt có thể không hỗ trợ cuộn trong mẫu. Trong trường hợp này, một số nội dung của bạn có thể không hiển thị.

Ví dụ: hãy xem xét một Lát cắt hiển thị danh sách các mạng Wi-Fi:

Nếu danh sách Wi-Fi dài và nếu tính năng cuộn bị tắt, bạn có thể thêm Nút Xem thêm nhằm đảm bảo rằng người dùng có thể xem tất cả các mục trong danh sách. Bạn có thể thêm nút này bằng cách sử dụng addSeeMoreAction()! như trong ví dụ sau:

Kotlin

fun seeMoreActionSlice(sliceUri: Uri) =
    list(context, sliceUri, ListBuilder.INFINITY) {
        // [START_EXCLUDE]
        // [END_EXCLUDE]
        setSeeMoreAction(seeAllNetworksPendingIntent)
        // [START_EXCLUDE]
        // [END_EXCLUDE]
    }

Java

public Slice seeMoreActionSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    // [START_EXCLUDE]
    listBuilder.addRow(new RowBuilder()
            .setTitle("Hello")
            .setPrimaryAction(createActivityAction())
    );
    // [END_EXCLUDE]
    listBuilder.setSeeMoreAction(seeAllNetworksPendingIntent);
    // [START_EXCLUDE]
    // [END_EXCLUDE]
    return listBuilder.build();
}

Thao tác này sẽ hiển thị như trong hình ảnh sau đây:

Thao tác nhấn vào Xem thêm sẽ gửi seeAllNetworksPendingIntent.

Ngoài ra, nếu bạn muốn cung cấp một hàng hoặc thông điệp tuỳ chỉnh, hãy cân nhắc việc thêm một Trình tạo hàng:

Kotlin

fun seeMoreRowSlice(sliceUri: Uri) =
    list(context, sliceUri, ListBuilder.INFINITY) {
        // [START_EXCLUDE]
        // [END_EXCLUDE]
        seeMoreRow {
            title = "See all available networks"
            addEndItem(
                IconCompat.createWithResource(context, R.drawable.ic_right_caret), ICON_IMAGE
            )
            primaryAction = SliceAction.create(
                seeAllNetworksPendingIntent,
                IconCompat.createWithResource(context, R.drawable.ic_wifi),
                ListBuilder.ICON_IMAGE,
                "Wi-Fi Networks"
            )
        }
    }

Java

public Slice seeMoreRowSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            // [START_EXCLUDE]
            .addRow(new RowBuilder()
                    .setTitle("Hello")
                    .setPrimaryAction(createActivityAction())
            )
            // [END_EXCLUDE]
            .setSeeMoreRow(new RowBuilder()
                    .setTitle("See all available networks")
                    .addEndItem(IconCompat
                                    .createWithResource(getContext(), R.drawable
                                            .ic_right_caret),
                            ListBuilder.ICON_IMAGE)
                    .setPrimaryAction(SliceAction.create(seeAllNetworksPendingIntent,
                            IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
                            ListBuilder.ICON_IMAGE,
                            "Wi-Fi Networks"))
            );
    // [START_EXCLUDE]
    // [END_EXCLUDE]
    return listBuilder.build();
}

Hàng hoặc hành động được thêm thông qua phương pháp này chỉ hiển thị khi một trong các điều kiện sau được đáp ứng:

  • Người trình bày trong Lát cắt của bạn đã tắt tính năng cuộn trên khung hiển thị
  • Không phải tất cả hàng của bạn đều có thể hiển thị trong không gian có sẵn

Kết hợp các mẫu

Bạn có thể tạo một Lát cắt động và phong phú bằng cách kết hợp nhiều loại hàng. Cho Ví dụ: Lát cắt có thể chứa hàng tiêu đề, lưới chứa một hình ảnh và một lưới gồm hai ô văn bản.

Đây là một Lát cắt có hàng tiêu đề cùng với một lưới chứa 3 ô.