Bagikan melalui


Menangani Rotasi

Topik ini menjelaskan cara menangani perubahan orientasi perangkat di Xamarin.Android. Ini mencakup cara bekerja dengan sistem sumber daya Android untuk secara otomatis memuat sumber daya untuk orientasi perangkat tertentu serta cara menangani perubahan orientasi secara terprogram.

Gambaran Umum

Karena perangkat seluler mudah diputar, rotasi bawaan adalah fitur standar dalam OS seluler. Android menyediakan kerangka kerja canggih untuk menangani rotasi dalam aplikasi, baik antarmuka pengguna dibuat secara deklaratif di XML atau secara terprogram dalam kode. Saat menangani perubahan tata letak deklaratif secara otomatis pada perangkat yang diputar, aplikasi dapat memperoleh manfaat dari integrasi yang ketat dengan sistem sumber daya Android. Untuk tata letak terprogram, perubahan harus ditangani secara manual. Ini memungkinkan kontrol yang lebih baik pada runtime, tetapi dengan mengorbankan lebih banyak pekerjaan untuk pengembang. Aplikasi juga dapat memilih untuk memilih keluar dari mulai ulang Aktivitas dan mengambil kontrol manual perubahan orientasi.

Panduan ini memeriksa topik orientasi berikut:

  • Rotasi Tata Letak Deklaratif – Cara menggunakan sistem sumber daya Android untuk membangun aplikasi yang sadar orientasi, termasuk cara memuat tata letak dan drawable untuk orientasi tertentu.

  • Rotasi Tata Letak Terprogram – Cara menambahkan kontrol secara terprogram serta cara menangani perubahan orientasi secara manual.

Menangani Rotasi Secara Deklaratif dengan Tata Letak

Dengan menyertakan file dalam folder yang mengikuti konvensi penamaan, Android secara otomatis memuat file yang sesuai saat orientasi berubah. Ini meliputi dukungan untuk:

  • Sumber Daya Tata Letak – Menentukan file tata letak mana yang ditambungkan untuk setiap orientasi.

  • Sumber Daya yang Dapat Digambar – Menentukan drawable mana yang dimuat untuk setiap orientasi.

Sumber Daya Tata Letak

Secara default, file Android XML (AXML) yang disertakan dalam folder Sumber Daya/tata letak digunakan untuk menyajikan tampilan untuk Aktivitas. Sumber daya folder ini digunakan untuk orientasi potret dan lanskap jika tidak ada sumber daya tata letak tambahan yang disediakan khusus untuk lanskap. Pertimbangkan struktur proyek yang dibuat oleh templat proyek default:

Struktur templat proyek default

Proyek ini membuat satu file Main.axml di folder Sumber Daya/tata letak . Ketika metode Aktivitas OnCreate dipanggil, metode ini mengembang tampilan yang ditentukan dalam Main.axml, yang mendeklarasikan tombol seperti yang ditunjukkan pada XML di bawah ini:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<Button  
  android:id="@+id/myButton"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:text="@string/hello"/>
</LinearLayout>

Jika perangkat diputar ke orientasi lanskap, metode Aktivitas OnCreate dipanggil lagi dan file Main.axml yang sama dilambungkan, seperti yang ditunjukkan pada cuplikan layar di bawah ini:

Layar yang sama tetapi dalam orientasi lanskap

Tata Letak Khusus Orientasi

Selain folder tata letak (yang default ke potret dan juga dapat secara eksplisit dinamai layout-port dengan menyertakan folder bernama layout-land), aplikasi dapat menentukan tampilan yang dibutuhkan ketika dalam lanskap tanpa perubahan kode apa pun.

Misalkan file Main.axml berisi XML berikut:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:text="This is portrait"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
</RelativeLayout>

Jika folder bernama layout-land yang berisi file Main.axml tambahan ditambahkan ke proyek, menambah tata letak saat dalam lanskap sekarang akan mengakibatkan Android memuat Main.axml yang baru ditambahkan. Pertimbangkan versi lanskap dari file Main.axml yang berisi kode berikut (untuk kesederhanaan, XML ini mirip dengan versi potret default kode, tetapi menggunakan string yang berbeda dalam TextView):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:text="This is landscape"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
</RelativeLayout>

Menjalankan kode ini dan memutar perangkat dari potret ke lanskap menunjukkan pemuatan XML baru, seperti yang ditunjukkan di bawah ini:

Cuplikan layar potret dan lanskap mencetak mode potret

Sumber Daya yang Dapat Digambar

Selama rotasi, Android memperlakukan sumber daya yang dapat digambar mirip dengan sumber daya tata letak. Dalam hal ini, sistem mendapatkan drawable dari folder Resources/drawable dan Resources/drawable-land , masing-masing.

Misalnya, katakanlah proyek menyertakan gambar bernama Monkey.png di folder Sumber Daya/yang dapat digambar, di mana yang dapat digambar direferensikan dari ImageView dalam XML seperti ini:

<ImageView
  android:layout_height="wrap_content"
  android:layout_width="wrap_content"
  android:src="@drawable/monkey"
  android:layout_centerVertical="true"
  android:layout_centerHorizontal="true" />

Mari kita asumsikan lebih lanjut bahwa versi Monkey.png yang berbeda disertakan di bawah Sumber Daya/lahan yang dapat digambar. Sama seperti file tata letak, ketika perangkat diputar, perubahan yang dapat digambar untuk orientasi yang diberikan, seperti yang ditunjukkan di bawah ini:

Versi Monkey.png yang berbeda ditampilkan dalam mode potret dan lanskap

Menangani Rotasi Secara Terprogram

Terkadang kita menentukan tata letak dalam kode. Ini dapat terjadi karena berbagai alasan, termasuk keterbatasan teknis, preferensi pengembang, dll. Ketika kita menambahkan kontrol secara terprogram, aplikasi harus secara manual memperhitungkan orientasi perangkat, yang ditangani secara otomatis ketika kita menggunakan sumber daya XML.

Menambahkan Kontrol dalam Kode

Untuk menambahkan kontrol secara terprogram, aplikasi perlu melakukan langkah-langkah berikut:

  • Buat tata letak.
  • Atur parameter tata letak.
  • Membuat kontrol.
  • Atur parameter tata letak kontrol.
  • Tambahkan kontrol ke tata letak.
  • Atur tata letak sebagai tampilan konten.

Misalnya, pertimbangkan antarmuka pengguna yang terdiri dari satu TextView kontrol yang RelativeLayoutditambahkan ke , seperti yang ditunjukkan dalam kode berikut.

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);
                        
  // create a layout
  var rl = new RelativeLayout (this);

  // set layout parameters
  var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
  rl.LayoutParameters = layoutParams;
        
  // create TextView control
  var tv = new TextView (this);

  // set TextView's LayoutParameters
  tv.LayoutParameters = layoutParams;
  tv.Text = "Programmatic layout";

  // add TextView to the layout
  rl.AddView (tv);
        
  // set the layout as the content view
  SetContentView (rl);
}

Kode ini membuat instans RelativeLayout kelas dan mengatur propertinya LayoutParameters . Kelas LayoutParams ini adalah cara Android untuk merangkum bagaimana kontrol diposisikan dengan cara yang dapat digunakan kembali. Setelah instans tata letak dibuat, kontrol dapat dibuat dan ditambahkan ke dalamnya. Kontrol juga memiliki LayoutParameters, seperti TextView dalam contoh ini. TextView Setelah dibuat, tambahkan ke RelativeLayout dan atur RelativeLayout sebagai tampilan konten menghasilkan aplikasi yang menampilkan seperti yang TextView ditunjukkan:

Tombol penghitung kenaikan ditampilkan dalam mode potret dan lanskap

Mendeteksi Orientasi dalam Kode

Jika aplikasi mencoba memuat antarmuka pengguna yang berbeda untuk setiap orientasi saat OnCreate dipanggil (ini akan terjadi setiap kali perangkat diputar), aplikasi harus mendeteksi orientasi, lalu memuat kode antarmuka pengguna yang diinginkan. Android memiliki kelas yang disebut WindowManager, yang dapat digunakan untuk menentukan rotasi perangkat saat ini melalui properti , seperti yang WindowManager.DefaultDisplay.Rotation ditunjukkan di bawah ini:

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);
                        
  // create a layout
  var rl = new RelativeLayout (this);

  // set layout parameters
  var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
  rl.LayoutParameters = layoutParams;
                        
  // get the initial orientation
  var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
  // create layout based upon orientation
  RelativeLayout.LayoutParams tvLayoutParams;
                
  if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
    tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
  } else {
    tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
    tvLayoutParams.LeftMargin = 100;
    tvLayoutParams.TopMargin = 100;
  }
                        
  // create TextView control
  var tv = new TextView (this);
  tv.LayoutParameters = tvLayoutParams;
  tv.Text = "Programmatic layout";
        
  // add TextView to the layout
  rl.AddView (tv);
        
  // set the layout as the content view
  SetContentView (rl);
}

Kode ini mengatur TextView agar diposisikan 100 piksel dari kiri atas layar, secara otomatis menganimasikan ke tata letak baru, saat diputar ke lanskap, seperti yang ditunjukkan di sini:

Status tampilan dipertahankan di seluruh mode potret dan lanskap

Mencegah Menghidupkan Ulang Aktivitas

Selain menangani segala sesuatu di OnCreate, aplikasi juga dapat mencegah Aktivitas dimulai ulang ketika orientasi berubah dengan mengatur ConfigurationChanges sebagai ActivityAttribute berikut:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]

Sekarang ketika perangkat diputar, Aktivitas tidak dimulai ulang. Untuk menangani perubahan orientasi secara manual dalam hal ini, Aktivitas dapat mengambil alih OnConfigurationChanged metode dan menentukan orientasi dari Configuration objek yang diteruskan, seperti dalam implementasi baru Aktivitas di bawah ini:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
  TextView _tv;
  RelativeLayout.LayoutParams _layoutParamsPortrait;
  RelativeLayout.LayoutParams _layoutParamsLandscape;
                
  protected override void OnCreate (Bundle bundle)
  {
    // create a layout
    // set layout parameters
    // get the initial orientation

    // create portrait and landscape layout for the TextView
    _layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
                
    _layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
    _layoutParamsLandscape.LeftMargin = 100;
    _layoutParamsLandscape.TopMargin = 100;
                        
    _tv = new TextView (this);
                        
    if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
      _tv.LayoutParameters = _layoutParamsPortrait;
    } else {
      _tv.LayoutParameters = _layoutParamsLandscape;
    }
                        
    _tv.Text = "Programmatic layout";
    rl.AddView (_tv);
    SetContentView (rl);
  }
                
  public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
  {
    base.OnConfigurationChanged (newConfig);
                        
    if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
      _tv.LayoutParameters = _layoutParamsPortrait;
      _tv.Text = "Changed to portrait";
    } else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
      _tv.LayoutParameters = _layoutParamsLandscape;
      _tv.Text = "Changed to landscape";
    }
  }
}

Di sini parameter tata letak diinisialisasi TextView's untuk lanskap dan potret. Variabel kelas menyimpan parameter, bersama dengan parameter itu TextView sendiri, karena Aktivitas tidak akan dibuat ulang saat orientasi berubah. Kode masih menggunakan in surfaceOrientartionOnCreate untuk mengatur tata letak awal untuk TextView. Setelah itu, OnConfigurationChanged menangani semua perubahan tata letak berikutnya.

Saat kami menjalankan aplikasi, Android memuat perubahan antarmuka pengguna saat rotasi perangkat terjadi, dan tidak memulai ulang Aktivitas.

Mencegah Mulai Ulang Aktivitas untuk Tata Letak Deklaratif

Mulai ulang aktivitas yang disebabkan oleh rotasi perangkat juga dapat dicegah jika kita menentukan tata letak di XML. Misalnya, kita dapat menggunakan pendekatan ini jika kita ingin mencegah restart Aktivitas (karena alasan performa, mungkin) dan kita tidak perlu memuat sumber daya baru untuk orientasi yang berbeda.

Untuk melakukan ini, kita mengikuti prosedur yang sama yang kita gunakan dengan tata letak terprogram. Cukup atur ConfigurationChanges dalam , seperti yang ActivityAttributekami lakukan di CodeLayoutActivity sebelumnya. Kode apa pun yang perlu dijalankan untuk perubahan orientasi dapat diimplementasikan lagi dalam OnConfigurationChanged metode .

Mempertahankan Status Selama Perubahan Orientasi

Baik menangani rotasi secara deklaratif atau terprogram, semua aplikasi Android harus menerapkan teknik yang sama untuk mengelola status saat orientasi perangkat berubah. Mengelola status penting karena sistem memulai ulang Aktivitas yang sedang berjalan saat perangkat Android diputar. Android melakukan ini untuk memudahkan pemuatan sumber daya alternatif, seperti tata letak dan drawable yang dirancang khusus untuk orientasi tertentu. Saat dimulai ulang, Aktivitas kehilangan status sementara yang mungkin disimpan dalam variabel kelas lokal. Oleh karena itu, jika Aktivitas bergantung pada status, aktivitas harus bertahan pada tingkat aplikasi. Aplikasi perlu menangani penyimpanan dan pemulihan status aplikasi apa pun yang ingin dipertahankan di seluruh perubahan orientasi.

Untuk informasi selengkapnya tentang status bertahan di Android, lihat panduan Siklus Hidup Aktivitas.

Ringkasan

Artikel ini membahas cara menggunakan kemampuan bawaan Android untuk bekerja dengan rotasi. Pertama, ini menjelaskan cara menggunakan sistem sumber daya Android untuk membuat aplikasi sadar orientasi. Kemudian disajikan cara menambahkan kontrol dalam kode serta cara menangani perubahan orientasi secara manual.