Menentukan tata letak di Wear

Aplikasi Wear OS menggunakan teknik tata letak yang sama dengan perangkat Android genggam, tetapi harus didesain dengan batasan tertentu. Jangan melakukan porting fungsi dan UI dari aplikasi perangkat genggam dan mengharapkan pengalaman pengguna yang baik.

Untuk informasi selengkapnya tentang mendesain aplikasi wearable yang sangat baik, baca pedoman mendesain Wear OS.

Ketika membuat tata letak untuk aplikasi Wear OS, Anda harus memperhitungkan perangkat dengan layar berbentuk persegi dan lingkaran. Konten di dekat sudut layar dapat terpotong jika perangkat Wear OS memiliki bentuk lingkaran. Oleh karena itu, tata letak yang didesain untuk layar berbentuk persegi dapat memiliki masalah tampilan pada perangkat berbentuk lingkaran.

Misalnya, Gambar 1 menunjukkan tampilan tata letak berikut pada layar berbentuk persegi dan lingkaran:

Gambar 1. Demonstrasi tentang bagaimana desain tata letak untuk layar berbentuk persegi tidak sesuai bagi layar berbentuk lingkaran.

Dengan demikian, jika menggunakan setelan berikut untuk tata letak Anda, teks tidak akan ditampilkan dengan benar pada perangkat dengan layar berbentuk lingkaran:

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

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_square" />
    </LinearLayout>
    

Ada dua pendekatan untuk masalah ini:

  1. Menggunakan tata letak dalam Library UI Wear untuk perangkat berbentuk persegi dan lingkaran.
    • BoxInsetLayout - Tata letak ini menerapkan sisipan jendela yang berbeda, bergantung bentuk layar perangkat. Gunakan pendekatan ini ketika Anda ingin menggunakan tata letak yang serupa di kedua bentuk layar tanpa harus memotong tampilan di dekat tepi pada layar berbentuk lingkaran.
    • Tata Letak Melengkung - Gunakan tata letak ini ketika Anda ingin menampilkan dan memanipulasi daftar vertikal item yang dioptimalkan untuk layar berbentuk lingkaran.
  2. Menyediakan resource tata letak alternatif untuk perangkat berbentuk persegi dan lingkaran seperti yang dijelaskan dalam panduan Menyediakan Resource. Saat waktu proses, Wear mendeteksi bentuk layar perangkat dan memuat tata letak yang benar.

Untuk mengompilasi project Android Studio dengan library ini, pastikan paket Tambahan > Repositori Google diinstal dalam pengelola Android SDK. Selain itu, sertakan dependensi berikut dalam file build.gradle pada modul wear Anda:

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:wear:26.0.0'
    }
    

Menggunakan BoxInsetLayout

Gambar 2. Sisipan jendela pada layar berbentuk lingkaran.

Class BoxInsetLayout di Library UI Wear memungkinkan Anda menentukan tata letak tunggal yang sesuai untuk layar berbentuk persegi dan lingkaran. Class ini menerapkan sisipan jendela yang diperlukan sesuai bentuk layar dan memungkinkan Anda dengan mudah menyelaraskan tampilan di tengah atau di dekat tepi layar.

Catatan: Class BoxInsetLayout menggantikan class serupa yang tidak digunakan lagi di Wearable Support Library.

Persegi abu-abu dalam Gambar 2 menampilkan area tempat BoxInsetLayout dapat secara otomatis menempatkan tampilan turunannya pada layar berbentuk lingkaran setelah menerapkan sisipan jendela yang diperlukan. Agar ditampilkan di dalam area ini, tampilan turunan menentukan atribut boxedEdges dengan nilai-nilai berikut:

  • Kombinasi top, bottom, left, dan right. Misalnya, nilai "left|top" menempatkan tepi kiri dan atas turunan di bagian dalam persegi abu-abu pada Gambar 2.
  • Nilai "all" menempatkan semua konten turunan di bagian dalam persegi abu-abu pada Gambar 2.

Pada layar berbentuk persegi, sisipan jendela adalah nol dan atribut boxedEdges diabaikan.

Gambar 3. Penentuan tata letak yang sesuai untuk layar berbentuk persegi dan lingkaran.

Tata letak yang ditunjukkan dalam Gambar 3 menggunakan elemen <BoxInsetLayout> dan sesuai untuk layar berbentuk persegi dan lingkaran:

    <android.support.wear.widget.BoxInsetLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:padding="15dp">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="5dp"
            app:boxedEdges="all">

            <TextView
                android:gravity="center"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:text="@string/sometext"
                android:textColor="@color/black" />

            <ImageButton
                android:background="@null"
                android:layout_gravity="bottom|left"
                android:layout_height="50dp"
                android:layout_width="50dp"
                android:src="@drawable/ok" />

            <ImageButton
                android:background="@null"
                android:layout_gravity="bottom|right"
                android:layout_height="50dp"
                android:layout_width="50dp"
                android:src="@drawable/cancel" />
        </FrameLayout>
    </android.support.wear.widget.BoxInsetLayout>
    

Perhatikan bagian tata letak yang ditandai dengan huruf tebal:

  • android:padding="15dp"

    Baris ini menentukan padding ke elemen <BoxInsetLayout>. Sisipan jendela pada perangkat berbentuk lingkaran lebih besar dari 15 dp, sehingga padding ini hanya diterapkan untuk layar berbentuk persegi.

  • android:padding="5dp"

    Baris ini menetapkan padding ke elemen FrameLayout bagian dalam. Padding ini diterapkan pada layar berbentuk persegi dan lingkaran. Padding total antara tombol dan sisipan jendela adalah 20 dp pada layar berbentuk persegi (15+5) dan 5 dp pada layar berbentuk lingkaran.

  • app:boxedEdges="all"

    Baris ini memastikan bahwa elemen FrameLayout dan turunannya berada di kotak dalam area yang ditentukan oleh sisipan jendela pada layar berbentuk lingkaran. Baris ini tidak berfungsi pada layar berbentuk persegi.

Menggunakan tata letak melengkung

Class WearableRecyclerView dalam Library UI Wear memungkinkan Anda memilih tata letak melengkung, yang dioptimalkan untuk layar berbentuk lingkaran. Untuk mengaktifkan tata letak melengkung bagi daftar yang dapat di-scroll dalam aplikasi Anda, lihat Membuat Tata Letak Melengkung.

Menggunakan tata letak yang berbeda untuk layar berbentuk persegi dan lingkaran

Perangkat Wear dapat memiliki layar berbentuk persegi atau lingkaran. Aplikasi Anda harus dapat mendukung konfigurasi perangkat mana pun. Untuk melakukannya, Anda harus menyediakan resource alternatif. Terapkan kualifikasi resource -round dan -notround untuk tata letak, dimensi, atau jenis resource lainnya.

Misalnya, pertimbangkan untuk mengatur tata letak seperti berikut:

  • Direktori layout/ berisi tata letak yang sesuai untuk jam tangan berbentuk lingkaran dan persegi.
  • Direktori layout-round/ dan layout-notround/ berisi tata letak yang dikhususkan untuk bentuk suatu layar.

Anda juga dapat menggunakan direktori resource res/values, res/values-round, dan res/values-notround. Dengan mengatur resource menggunakan cara ini, Anda dapat membagikan tata letak tunggal sembari mengubah atribut tertentu saja, berdasarkan jenis perangkat.

Membedakan nilai

Cara mudah membuat jam tangan berbentuk bulat dan persegi adalah menggunakan values/dimens.xml dan values-round/dimens.xml. Dengan menentukan setelan padding yang berbeda, Anda dapat membuat tata letak berikut dengan satu file layout.xml dan dua file dimens.xml:

    <dimen name="header_start_padding">36dp</dimen>
    <dimen name="header_end_padding">22dp</dimen>
    <dimen name="list_start_padding">36dp</dimen>
    <dimen name="list_end_padding">22dp</dimen>
    
Menggunakan values-round/dimens.xml

Gambar 4. Menggunakan values-round/dimens.xml.

    <dimen name="header_start_padding">16dp</dimen>
    <dimen name="header_end_padding">16dp</dimen>
    <dimen name="list_start_padding">10dp</dimen>
    <dimen name="list_end_padding">10dp</dimen>
    
Menggunakan values/dimens.xml

Gambar 5. Menggunakan values/dimens.xml.

Anda harus melakukan uji coba dengan nilai yang berbeda untuk melihat mana yang paling sesuai.

Menggunakan XML untuk mengimbangi chin

Beberapa jam tangan memiliki sisipan (juga dikenal dengan "chin") di layar berbentuk lingkaran. Jika Anda tidak mengimbanginya, beberapa desain Anda mungkin tertutupi chin tersebut.

Misalnya, Anda mungkin memiliki desain berikut:

Desain inti dasar

Gambar 6. Desain inti dasar.

Cuplikan activity_main.xml ini menentukan tata letaknya.

    <FrameLayout
      ...>
      <android.support.wear.widget.RoundedDrawable
        android:id="@+id/androidbtn"
        android:src="@drawable/ic_android"
        .../>
       <ImageButton
        android:id="@+id/lovebtn"
        android:src="@drawable/ic_favourite"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:layout_gravity="bottom"
        .../>
    </FrameLayout>
    

Jika Anda tidak melakukan apa pun, bagian desain ini akan hilang ke dalam chin.

Desain inti dasar

Gambar 7. Tidak ada perbaikan yang diterapkan.

Anda dapat menggunakan atribut fitsSystemWindows untuk menyetel padding guna menghindari chin. Cuplikan activity_main.xml berikut menunjukkan penggunaan fitsSystemWindows:

    <ImageButton
      android:id="@+id/lovebtn"
      android:src="@drawable/ic_favourite"
      android:paddingTop="5dp"
      android:paddingBottom="5dp"
      android:fitsSystemWindows="true"
      .../>
    
Menggunakan fitsSystemWindows

Gambar 8. Menggunakan atribut fitsSystemWindows.

Perhatikan bahwa nilai padding atas dan bawah yang Anda terapkan diganti untuk membuat semuanya sesuai di jendela sistem. Cara memperbaikinya adalah mengganti nilai padding menggunakan InsetDrawable.

Buat file inset_favourite.xml untuk menentukan nilai padding:

    <inset
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:drawable="@drawable/ic_favourite"
      android:insetTop="5dp"
      android:insetBottom="5dp" />
    

Hapus padding dari activity_main.xml:

    <ImageButton
      android:id="@+id/lovebtn"
      android:src="@drawable/inset_favourite"
      android:paddingTop="5dp"
      android:paddingBottom="5dp"
      android:fitsSystemWindows="true"
      .../>
    
Menggunakan InsetDrawables

Gambar 9. Menggunakan InsetDrawables.

Mengelola chin secara terprogram

Jika memerlukan kontrol lebih dari yang mungkin dilakukan dengan XML secara deklaratif, Anda dapat menyesuaikan tata letak secara terprogram. Untuk memperoleh ukuran chin, Anda harus melampirkan View.OnApplyWindowInsetsListener ke tampilan terluar tata letak Anda.

Tambahkan kode berikut ke MainActivity.java:

Kotlin

    private var chinSize: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // find the outermost element
        findViewById<View>(R.id.outer_container).apply {
            // attach a View.OnApplyWindowInsetsListener
            setOnApplyWindowInsetsListener { v, insets ->
                chinSize = insets.systemWindowInsetBottom
                // The following line is important for inner elements which react to insets
                v.onApplyWindowInsets(insets)
                insets
            }
        }
    }
    

Java

    private int chinSize;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // find the outermost element
        final View container = findViewById(R.id.outer_container);
        // attach a View.OnApplyWindowInsetsListener
        container.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
            @Override
            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                chinSize = insets.getSystemWindowInsetBottom();
                // The following line is important for inner elements which react to insets
                v.onApplyWindowInsets(insets);
                return insets;
            }
        });
    }