Menggunakan DialogFragment di Android

Bagus Aji Santoso 20 November 2017

Menggunakan DialogFragment di Android

Pendahuluan

DialogFragment adalah Fragment khusus yang dipakai saat kita ingin menampilkan sebuah window yang melayang di atas konten lain di Activity.

Biasanya dipakai untuk menampilkan alert dialog, confirm dialog, atau meminta informasi dari pengguna tanpa berpindah Activity.

Penggunaan

Method yang harus di-implement saat membuat sebuah DialogFragment adalah onCreateView atau onCreateDialog. Gunakan onCreateView saat keseluruhan view atau dialog akan menggunakan layout XML sendiri. Gunakan onCreateDialog saat akan membuat dialog standar (seperti alert atau konfirmasi).

Catatan: Tutorial di bawah akan menggunakan kelas Fragment yang diimpor menggunakan android.support.v4.app bukanandroid.app. Jika terjadi error pastikan dulu sudah mengimpor kelas yang seharusnya.

Custom View

Mari mulai dengan membuat dialog yang menggunakan layout XML khusus. Pertama, buat sebuah layout XML di res/layout/fragment_edit_name.xml:

<!-- fragment_edit_name.xml -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/edit_name"
	android:layout_width="wrap_content"	      
	android:layout_height="wrap_content"
	android:layout_gravity="center" android:orientation="vertical"  >
	<TextView
		android:id="@+id/lbl_your_name" android:text="Your name" 
		android:layout_width="wrap_content"       			 
		android:layout_height="wrap_content" />
	<EditText
		android:id="@+id/txt_your_name"
		android:layout_width="match_parent"  
		android:layout_height="wrap_content" 
		android:inputType="text"
		android:imeOptions="actionDone" />
</LinearLayout>

lalu buat kelas Fragment yang meng-extends DialogFragment (perhatikan package yang di import di baris pertama):

import android.support.v4.app.DialogFragment;
// ...
public class EditNameDialogFragment extends DialogFragment {
	private EditText mEditText;
	public EditNameDialogFragment() {
		// Constructor kosong diperlukan untuk DialogFragment.
        // Pastikan tidak memberikan argument/parameter apapun ke 
        // constructor ini.
	}

	public static EditNameDialogFragment newInstance(String title) {
		EditNameDialogFragment frag = new EditNameDialogFragment();
		Bundle args = new Bundle();
		args.putString("title", title);
		frag.setArguments(args);
		return frag;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.fragment_edit_name, container);
	}

	@Override
	public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		// Baca view yang dibuat di XML
		mEditText = (EditText) view.findViewById(R.id.txt_your_name);
		// Ambil argument dari bundle (yang ada di newInstance) lalu mengatur title dari Dialog 	
		// yang ditampilkan dengan data di dalam bundle 
		String title = getArguments().getString("title", "Enter Name");
		getDialog().setTitle(title);
		// Show soft keyboard automatically and request focus to field
		mEditText.requestFocus();
		getDialog().getWindow().setSoftInputMode(
		    WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
	}
}

dan tampilkan dialog di sebuah Activity yang meng-extends AppCompatActivity:

// Note: `FragmentActivity` works here as well

public class DialogDemoActivity extends AppCompatActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      showEditDialog();
  }
  
  private void showEditDialog() {
      FragmentManager fm = getSupportFragmentManager();
      EditNameDialogFragment editNameDialogFragment = EditNameDialogFragment.newInstance("Some Title");
      editNameDialogFragment.show(fm, "fragment_edit_name");
  }

}

Sekali lagi pastikan package yang di impor berasal dari namespace android.support.v4.app.

Menggunakan Dialog Builder

Sekarang, mari kita pelajari bagaimana membuat dialog sederhana tanpa menggunakan layout XML khusus. Untuk jenis dialog yang lain, lihat catatan di bawah.

class MyAlertDialogFragment extends DialogFragment {
    public MyAlertDialogFragment() {
          // Constructor kosong untuk DialogFragment
    }
    
    public static MyAlertDialogFragment newInstance(String title) {
        MyAlertDialogFragment frag = new MyAlertDialogFragment();
    	Bundle args = new Bundle();
    	args.putString("title", title);
    	frag.setArguments(args);
    	return frag;
    }
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        String title = getArguments().getString("title");
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
        alertDialogBuilder.setTitle(title);
        alertDialogBuilder.setMessage("Are you sure?");
        alertDialogBuilder.setPositiveButton("OK",  new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
               // on success
            }
        });

        alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            if (dialog != null && dialog.isShowing()) { 
                 dialog.dismiss();
              }
            }
        });
        return alertDialogBuilder.create();
    }
}

Untuk menampilkan fragment di atas, panggil dari sebuah Activity yang meng-extends AppCompatActivity:

public class DialogDemoActivity extends AppCompatActivity {

  @Override

  public void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);

      showAlertDialog();

  }



  private void showAlertDialog() {

      FragmentManager fm = getSupportFragmentManager();

      MyAlertDialogFragment alertDialog = MyAlertDialogFragment.newInstance("Some title");

      alertDialog.show(fm, "fragment_alert");

  }

}

Mengirim Data dari Dialog ke Activity

Untuk mengirim data dari dialog ke sebuah Activity, gunakan cara berikut:

  1. Buat sebuah interface dengan method yang bisa dipanggil untuk mengirim data ke activity
  2. Buat event yang akan memanggil listener
  3. Implement interface di Activity

Contoh di bawah mendemonstrasikan bagaimana cara mengirim data se activity setelah tombol "Done" di tekan di keyboard:

public class EditNameDialogFragment extends DialogFragment implements OnEditorActionListener {

    private EditText mEditText;

    // 1. Membuat interface dengan method yang akan dipakai untuk mengirim data

    public interface EditNameDialogListener {
        void onFinishEditDialog(String inputText);
    }

    // ...

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        // ...
        // 2. Buat sebuah callback saat tombol Done keyboard di click. 
        mEditText.setOnEditorActionListener(this);

    }

    // Method akan selalu dipanggil setiap kali melakukan aksi di
    // text field. Dalam kasus di bawha ini kita akan memeriksa jika 
    // tombol "Done" di tekan
    // memerlukan 'soft keyboard' (virtual keyboard)
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (EditorInfo.IME_ACTION_DONE == actionId) {

            // Mengembalikan data kembali ke activity melalui listener yang di implement

            EditNameDialogListener listener = (EditNameDialogListener) getActivity();
            listener.onFinishEditDialog(mEditText.getText().toString());

            // Tutup dialog dan kembali ke activity
            dismiss();
            return true;
        }
        return false;
    }
}

kemudian buat Activity agar meng-implement interface yang tadi dibuat:

public class DialogDemoActivity extends AppCompatActivity implements EditNameDialogListener {

  // ...

  // 3. Method akan di jalankan setiap kali dipanggil dari DialogFragment
  // Ambil data yang dikirimkan ke activity di sini

  @Override

  public void onFinishEditDialog(String inputText) {
  	Toast.makeText(this, "Hi, " + inputText, Toast.LENGTH_SHORT).show();
  }
}

Catatan: setOnEditorActionListener di atas memerlukan soft keyboard. Jika tidak ingin menggunakna soft keyboard kita juga bisa menggunakan onClick button.

Mengirimkan Data dari Dialog ke Fragment Lain

Dalam beberapa situasi, sebuah dialog fragment mungkin dipanggil dari fragment lain, bukan Activity. Misalnya, sebuah activity memiliki sebuah form yang ada di dalam fragment (ditampilkan dengan tabs). Form tersebut memiliki kolom untuk memilih tanggal dengan date picker di sbuah dialog. Dalam kasus ini kita ingin mengirimkan tanggal yang dipilih tadi kembali ke fragment yang memanggilnya. Berikut caranya:

import android.support.v4.app.DialogFragment;

public class EditNameDialogFragment extends DialogFragment {

    // Membuat interface
    public interface EditNameDialogListener {
        void onFinishEditDialog(String inputText);
    }

    // Panggil method ini untuk mengirim data kembali ke parent fragment
    public void sendBackResult() {
      // Perhatikan penggunaaan `getTargetFragment` saat menampilkan Dialog ini
      EditNameDialogListener listener = (EditNameDialogListener) getTargetFragment();
      listener.onFinishEditDialog(mEditText.getText().toString());
      dismiss();
    }
}

Tampilkan dialog yang baru kita buat di fragment dengan cara:

import android.support.v4.app.Fragment;

public class MyParentFragment extends Fragment implements EditNameDialogListener {
    // Panggil method ini untuk menjalankan dialog edit
    private void showEditDialog() {
        FragmentManager fm = getFragmentManager();
        EditNameDialogFragment editNameDialogFragment = EditNameDialog.newInstance("Some Title");
        // mengatur target fragment yang akan menjadi tempat kembali dari dialog        
        editNameDialogFragment.setTargetFragment(MyParentFragment.this, 300);
        editNameDialogFragment.show(fm, "fragment_edit_name");
    }

    // Dipanggil setelah selesai mengambil data dari dialog
    @Override
    public void onFinishEditDialog(String inputText) {
        Toast.makeText(this, "Hi, " + inputText, Toast.LENGTH_SHORT).show();
    }
}

Jenis-jenis Dialog

Saat menggunakan onCreateDialog ada beberapa jenis Dialog yang bisa langsung kita pakai.

  • AlertDialog - Dapat menampilkan pesan, ikon dan 1-3 tombol dengan teks khusus.
  • ProgressDialog - Dapat menampilkan progress indicator dengan pesan teks khusus
  • TimePickerDialog - Membuat pengguna dapat memilih waktu
  • DatePickerDialog - Membuat pengguna dapat memilih tanggal
  • BottomSheetDialog - Menampilkan dialog yang muncul dari bawah.

Menampilkan ProgressDialog

Saat melakukan proses di belakang layar yang agak lama, salah satu cara memberi tahu pengguna bahwa aplikasi kita sedang berjalan ialah dengan menampilkan sebuah ProgressDialog.

Image
ProgressDialog pd = new ProgressDialog(context);
pd.setTitle("Loading...");
pd.setMessage("Please wait.");
pd.setCancelable(false);

Dialog dapat ditampilkan dengan:

pd.show();

Lalu dapat ditutup dengan:

pd.dismiss();

Menampilkan Date atau Time Picker Dialog

Image
Image

Jika menggunakan dialog ini, pastikan Activity yang memanggilnya meng-implement method yang diperlukan (misalnya DatePickerDialog.OnDateSetListener untuk DatePickerFragment). Jika ingin menampilkan dari Fragment bukan Activity, lihat lagi pembahasan di atas.

Berikut ini contoh kode untuk dialog DatePicker:

import java.util.Calendar;  // jangan impor java.icu.utils.Calendar
public class DatePickerFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Gunakan waktu sekarang sebagai waktu default
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);
        // Activity perlu mengimplement listener ini
        DatePickerDialog.OnDateSetListener listener = (DatePickerDialog.OnDateSetListener) getActivity();
        // Buat TimePickerDialog dan panggil return
        return new DatePickerDialog(getActivity(), listener, year, month, day);
    }

Berikut ini contoh kode Activity yang memanggil dialog di atas (:

public class MyActivity extends AppCompatActivity implements DatePickerDialog.OnDateSetListener {
  // ... kode disingkat
  
  // panggil untuk menampilkan date picker
  public void showDatePickerDialog(View v) {
     DatePickerFragment newFragment = new DatePickerFragment();
     newFragment.show(getSupportFragmentManager(), "datePicker");
  }

  // handle the date selected
  @Override
  public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
    // store the values selected into a Calendar instance
    final Calendar c = Calendar.getInstance();
    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, monthOfYear);
    c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
  }

Cara yang sama juga berlaku untuk time picker:

public class TimePickerFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Gunakan waktu sekarang sebagai waktu default
        final Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        
        // Activity harus meng-implement interface inI

        TimePickerDialog.OnTimeSetListener listener = (TimePickerDialog.OnTimeSetListener) getActivity();

        // Create a new instance of TimePickerDialog and return it
        return new TimePickerDialog(getActivity(), listener, hour, minute, DateFormat.is24HourFormat(getActivity()));
    }

}

Modal Bottom Sheets

Image

Berkat deisn support library, kita dapat mengubah dialog menjadi bottom sheets menajdi lebih mudah. Daripada menggunakan DialogFragment, kita akan menggunakan BottomSheetDialogFragment:

public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_bottom_sheet, container);
    }
    
}

Saat ditampilkan, ia akan muncul dari bagian bawah:

MyBottomSheetDialogFragment myDialog = new MyBottomSheetDialogFragment();

FragmentManager fm = getSupportFragmentManager();
myDialog.show(fm, "test");

Diterjemahkan dari Using DialogFragment