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:
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:
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:
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:
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 RelativeLayout
ditambahkan 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:
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:
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 surfaceOrientartion
OnCreate
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 ActivityAttribute
kami 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.