Membuat UI yang Fleksibel

Ketika mendesain aplikasi kita untuk mendukung ukuran layar yang berbeda-beda, kita bisa menggunakan kembali 'fragment-fragment' kita dalam berbagai konfigurasi layout yang berbeda-beda untuk mengoptimalkan 'user experience' berdasarkan ruang layar yang tersedia.

Contohnya, pada perangkat handset mungkin akan pas untuk menampilkan hanya satu 'fragment' dalam satu saat untuk UI 'single-pane'. Sebaliknya, kita mungkin ingin men-set 'fragment-fragment' saling ber-sisi-an (bersebelahan) pada perangkat tablet yang memiliki ukuran layar yang lebih lebar untuk menampilkan informasi yang lebih banyak ke user.

Gambar 1. Dua 'fragment', yang ditampilkan dalam konfigurasi yang berbeda untuk 'activity' yang sama. Di layar besar, kedua 'fragment' bisa tepat ber-sisi-an (bersebelahan), tetapi pada perangkat handset, hanya satu 'fragment' bisa tepat tampil sehingga 'fragment-fragment' harus saling bergantian satu sama lain sesuai navigasi user.

Class 'FragmentManager' menyediakan method-method yang membebaskan kita untuk menambahkan, memindahkan/menghilangkan, mengganti 'fragment-fragment' ke 'activity' saat runtime supaya bisa membuat tampilan yang dinamis.

Menambahkan 'Fragment' ke 'Activity' saat Runtime

Daripada membuat 'fragment-fragment' untuk suatu 'activity' di dalam file layout -- seperti yang ditunjukkan dalam latihan sebelumnya dengan elemen <fragment> -- kita bisa menambahkan suatu fragment ke 'activity' saat runtime. Ini diperlukan bila kita berencana mengubah 'fragment-fragment' selama hidup 'activity'.

Untuk melakukan suatu transaksi seperti menambahkan atau menghilangkan suatu 'fragment', kita harus menggunakan 'FragmentManager' untuk membuat suatu 'FragmentTransaction', yang menyediakan API-API untuk menambahkan, menghilangkan, mengganti, dan melakukan transaksi-transaski 'fragment' lainnya.

Bila 'activity' kita memperbolehkan 'fragment-fragment' tersebut untuk dihilangkan dan diganti, kita seharusnya menambahkan 'fragment' di saat awal ke 'activity' pada method 'onCreate()' di 'activity' tersebut.

Aturan penting ketika menerapkan 'fragment' -- terutama ketika menambahkan 'fragment-fragment' saat runtime -- adalah bahwa layout 'activity' kita harus memasukkan suatu kontainer 'View' dimana kita bisa memasukkan/menempatkan 'fragment' tersebut.

Layout berikut adalah suatu alternatif dari layout yang ditunjukkan pada latihan sebelumnya yang menampilkan hanya satu fragment saja dalam satu saat. Supaya bisa mengganti satu 'fragment' dengan 'fragment' yang lain, layout 'activity' akan memasukkan 'FrameLayout' kosong yang akan bertindak sebagai kontainer 'fragment'.

Perhatikan bahwa nama file-nya adalah sama dengan file layout dalam latihan sebelumnya, tetapi direktori layout tidak memiliki qualifier 'large', sehingga layout ini digunakan ketika layar perangkat lebih kecil dibanding 'large' karena layar tersebut tidak akan cocok dengan kedua 'fragment' pada saat yang sama.

"res/layout/news_articles.xml":
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
Di dalam 'activity' kita, panggillah 'getSupportFragmentManager()' untuk mendapat 'FragmentManager' yang menggunakan API-API library pendukung. Kemudian panggillah 'beginTransaction()' untuk membuat suatu 'FragmentTransaction' dan panggillah 'add()' untuk menambahkan satu 'fragment'.

Kita bisa melakukan banyak transaksi 'fragment' untuk 'activity' yang menggunakan 'FragmentTransaction' yang sama. Ketika kita siap untuk membuat perubahan, kita harus memanggil 'commit()'.

Contohnya, dibawah ini adalah bagaimana kita menambahkan suatu 'fragment' ke layout sebelumnya: 
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create a new Fragment to be placed in the activity layout
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an
            // Intent, pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

Karena 'fragment' tersebut sudah ditambahkan ke kontainer 'FrameLayout' saat runtime -- sebagai ganti dari mendefinisikannya di dalam layout 'activity' dengan menggunakan elemen <fragment> -- 'activity' tersebut bisa menghilangkan 'fragment' tersebut dan menggantinya dengan 'fragment' yang lain.

Mengganti satu 'Fragment' dengan 'Fragment' lainnya

Prosedur untuk mengganti suatu 'fragment' mirip dengan menambahkan 'fragment', tetapi memerlukan method 'replace()' sebagai ganti 'add()'.

Jangan lupa bahwa ketika kita melakukan transaksi-transaksi 'fragment', misalnya mengganti atau menghilangkan satu fragment, seringkali pas untuk membebaskan user menavigasi dengan tombol 'backward' dan 'membatalkan/undo' perubahannya. Untuk membebaskan user menavigasi tombol 'backward' melalui transaksi 'fragment', kita harus memanggil 'addToBackStack()' sebelum kita melakukan 'commit' pada 'FragmentTransaction'
Catatan:
Ketika kita memindahkan/menghilangkan atau mengganti suatu 'fragment dan menambahkan transaksi ke tumpukan belakang, 'fragment' yang dipindahkan di-stop (bukan di-destroy). Bila user menavigasi kembali untuk mengembalikan 'fragment' tersebut, dia akan 'restart'. Bila kita tidak menambahkan transaksi ke tumpukan belakang, maka 'fragment' tersebut di-destroy ketika dipindahkan atau diganti.
Contoh mengganti satu 'fragment' dengan 'fragment' lainnya:
// Create fragment and give it an argument specifying the article it should show
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();

Method 'addToBackStack()' akan mengambil parameter string opsional yang menentukan nama yang unique untuk transaksi tersebut. Nama tersebut tidaklah diperlukan kecuali jika kita merencanakan untuk melakukan pekerjaan-pekerjaan menggunakan 'fagment' tingkat lanjut dengan menggunakan API-API 'FragmentManager.BackStackEntry'.

lisensi: cc by

No comments: