Giao diện người dùng

Tài liệu này trình bày cách làm theo phong cách Glass và triển khai các phương pháp phổ biến nhất về giao diện người dùng để có thể tối ưu hoá trải nghiệm người dùng. Thư viện này bao gồm các thành phần giao diện người dùng sau đây:

Chủ đề

Giao diện Glass chúng tôi đề xuất bạn sử dụng có các đặc điểm sau:

  • Hiển thị hoạt động ở chế độ toàn màn hình và không có thanh hành động.
  • Áp dụng nền đen tối.
  • Đặt màu sáng hơn cho hiệu ứng cạnh màu.
  • Áp dụng màu văn bản trắng.

Sau đây là các chế độ cài đặt giao diện đề xuất cho Glass:

 <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
   <item name="android:windowBackground">@android:color/black</item>
   <item name="android:colorEdgeEffect">@android:color/white</item>
   <item name="android:textColor">@android:color/white</item>
 </style>

Bố cục XML

Dưới đây là hai bố cục thẻ cơ bản mà mảnh của bạn có thể tăng cường:

Bố cục chính

Bố cục này xác định khoảng đệm và chân trang chuẩn được đề xuất cho thẻ. Đặt chế độ xem của riêng bạn vào FrameLayout trống.

Hộp trung tâm chiếm phần lớn nội dung của màn hình với kích thước 560 x 240 pixel, với một thanh nhỏ ở dưới cùng là 560 x 40 pixel ở dưới cùng.
          Ngoài ra còn có bốn khối nhỏ 40 x 40 pixel, mỗi khối một góc

Dưới đây là một bố cục XML mẫu:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/body_layout"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_margin="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put your widgets inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toStartOf="parent" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Bố cục cột bên trái

Bố cục này xác định cột chiều rộng một phần ba bên trái và cột chiều rộng hai phần ba bên phải ở dạng hai lớp FrameLayout mà bạn có thể đặt chế độ xem của mình vào. Hãy tham khảo hình ảnh sau đây để xem ví dụ.

Hiển thị một cột bên trái ở 240 x 360 pixel, giúp đẩy bố cục chính lên trên.
          Kích thước của kích thước này vừa với kích thước, vùng chính là 330 x 240 pixel, với một thanh nhỏ hơn
          là 330 x 40 pixel. Hai góc bên phải có hai hộp nhỏ 40 x 40 pixel và có bốn hộp khác 30 x 40 pixel, hai hộp ở góc dưới của cột bên trái và hai hộp ở bên trái bố cục chính, một ở trên cùng và một ở dưới cùng.

Dưới đây là một bố cục XML mẫu:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/left_column"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:background="#303030"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintWidth_percent=".333">

    <!-- Put widgets for the left column inside this FrameLayout. -->

  </FrameLayout>

  <FrameLayout
      android:id="@+id/right_column"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_marginTop="@dimen/glass_card_two_column_margin"
      android:layout_marginStart="@dimen/glass_card_two_column_margin"
      android:layout_marginBottom="@dimen/glass_card_two_column_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toEndOf="@id/left_column"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put widgets for the right column inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toEndOf="@id/left_column" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Phương diện chuẩn

Sử dụng nội dung sau cùng với các bố cục trước đó hoặc bố cục của riêng bạn để tạo một tệp tuân thủ Glass38; kiểu chuẩn. Tạo tệp này dưới dạng res/values/dimens.xml trong dự án Android.

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <!-- The recommended margin for the top, left, and right edges of a card. -->
  <dimen name="glass_card_margin">40dp</dimen>

  <!-- The recommended margin between the bottom of the card and the footer. -->
  <dimen name="glass_card_footer_margin">50dp</dimen>

  <!-- The recommended margin for the left column of the two-column card. -->
  <dimen name="glass_card_two_column_margin">30dp</dimen>

</resources>

Bạn nên sử dụng RecyclerView để tạo trình đơn. Các tệp này phải dựa trên tệp trình đơn Android tiêu chuẩn trong tài nguyên dự án của Android Studio. Android cho phép bạn ghi đè chế độ tạo trình đơn tiêu chuẩn và thay thế bằng phương thức triển khai. Để thực hiện điều này, hãy làm theo các bước sau:

  1. Tạo bố cục bằng RecyclerView và đặt làm chế độ xem cho Activity.
  2. Thiết lập RecyclerView và bộ chuyển đổi tương ứng để sử dụng bộ sưu tập các mục mới trong trình đơn.
  3. Ghi đè phương thức onCreateOptionsMenu.
    1. Tăng cường trình đơn và thêm phần tử mới vào bộ sưu tập cho từng mục trong trình đơn.
    2. Gọi phương thức notifyDataSetChanged trên bộ chuyển đổi.

    Kotlin

        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            val menuResource = intent
                .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE)
            if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
                menuInflater.inflate(menuResource, menu)
                for (i in 0 until menu.size()) {
                    val menuItem = menu.getItem(i)
                    menuItems.add(
                        GlassMenuItem(
                            menuItem.itemId, menuItem.icon,
                            menuItem.title.toString()
                        )
                    )
                    adapter.notifyDataSetChanged()
                }
            }
            return super.onCreateOptionsMenu(menu)
        }
        

    Java

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
          final int menuResource = getIntent()
              .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE);
          if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
            final MenuInflater inflater = getMenuInflater();
            inflater.inflate(menuResource, menu);
    
            for (int i = 0; i < menu.size(); i++) {
              final MenuItem menuItem = menu.getItem(i);
              menuItems.add(
                  new GlassMenuItem(menuItem.getItemId(), menuItem.getIcon(),
                      menuItem.getTitle().toString()));
              adapter.notifyDataSetChanged();
            }
          }
          return super.onCreateOptionsMenu(menu);
        }
        
  4. Sử dụng OnScrollListener cùng với LayoutManagerSnapHelper để xác định tuỳ chọn nào đã được chọn.
  5. Theo dõi cử chỉ TAP để xử lý sự kiện chọn mục trong trình đơn.
  6. Tạo Intent với thông tin về mục trong trình đơn đã chọn.
  7. Thiết lập một kết quả cho hoạt động này và hoàn tất nó.
  8. Gọi startActivityForResult từ mảnh hoặc hoạt động mà bạn muốn có trình đơn. Sử dụng cử chỉ TAP cho mục đích này.
  9. Ghi đè onActivityResult trong mảnh gọi hoặc hoạt động để xử lý mục trong trình đơn đã chọn.

Nguyên tắc

Sau đây là danh sách các đề xuất về cách thiết lập bố cục trình đơn:

Hình ảnh sau đây là ví dụ về bố cục trình đơn tuỳ chỉnh:

Hình ảnh đơn giản này hiển thị nền đen với các từ &quot;bố cục&quot; trong trình đơn;

Xem lại ứng dụng mẫu Thẻ để biết thông tin chi tiết về cách triển khai.

Các trang có thể vuốt

Màn hình Glass và bàn di chuột kết hợp với nhau để hiển thị các thẻ có thể vuốt một cách thuận tiện. Bạn có thể tạo các trang có thể vuốt trong hoạt động bằng API ViewPager tiêu chuẩn của Android.

Truy cập vào tài liệu đào tạo về Trang trình bày màn hình để biết thêm thông tin về cách sử dụng Android ViewPager để cuộn qua các thẻ hoặc màn hình.