Membuat dialog untuk memilih nada dering

Saya perlu satu proyek di sini untuk melakukan dialog dengan pilihan nada dering di pengaturan. Segera karena 2 alasan - pertama, tidak ada PreferenceFragmentCompat RingtonePreference di perpustakaan dukungan, jadi menggunakan dialog standar di PreferenceFragmentCompat akan gagal. Dan kedua, selain melodi standar, saya harus menambahkan beberapa suara dari sumber daya di sana. Jadi diputuskan untuk menulis dialog Anda.


Saya akan mendemonstrasikan pembuatan dialog semacam itu menggunakan contoh aplikasi sederhana: pada satu layar terdapat tombol "Mainkan nada dering", mengklik tombol yang memutar nada dering yang diatur dalam pengaturan, dan tautan ke layar pengaturan:



Saya tidak akan menjelaskan pembuatan dua layar ini - semuanya ada seperti biasa. Untuk jaga-jaga, pada akhirnya akan ada tautan ke repositori dengan kode aplikasi.


Jadi, mari kita mulai dengan file xml dengan deskripsi layar pengaturan. Tempatkan file settings.xml di res/xml dengan konten berikut:


 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <Preference android:key="ringtone" android:title="Ringtone"/> </PreferenceScreen> 

Dan sekarang mari kita tambahkan pengaturan ini ke fragmen kami:


 class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) } } 

Luncurkan, buka layar pengaturan, lihat hal berikut:



Pendahuluan berakhir di sini, kita beralih ke tujuan artikel. Rencananya adalah ini: ketika Anda mengklik "Nada Dering", dialog akan terbuka dengan daftar nada dering dan tombol OK dan Batalkan, ketika Anda memilih nada dering, nada itu diputar (seperti dalam kasus RingtonePreference Pengaturan nada standar), ketika Anda mengklik OK, ia disimpan dalam pengaturan.


Jadi, buat fragmen dialog:


 class RingtonePreferenceDialog : DialogFragment() { private val prefKey: String get() = arguments?.getString(ARG_PREF_KEY) ?: throw IllegalArgumentException("ARG_PREF_KEY not set") companion object { private const val ARG_PREF_KEY = "ARG_PREF_KEY" fun create(prefKey: String): RingtonePreferenceDialog { val fragment = RingtonePreferenceDialog() fragment.arguments = Bundle().apply { putString(ARG_PREF_KEY, prefKey) } return fragment } } } 

Di prefKey kami mentransfer tombol yang dengannya nada dering saat ini akan diekstraksi, dan di sana itu akan direkam dengan menekan tombol OK.


Untuk pekerjaan lebih lanjut, kita memerlukan Ringtone kelas tambahan, mendeklarasikannya di dalam fragmen kita:


 private data class Ringtone(val title: String, val uri: Uri) 

Dan tulis fungsi pembantu yang akan mengeluarkan semua nada dering bawaan di Android, dan mengembalikan daftar dari Ringtone :


 private fun getAndroidRingtones(): List<Ringtone> { val ringtoneManager = RingtoneManager(context) val cursor = ringtoneManager.cursor return (0 until cursor.count).map { cursor.moveToPosition(it) Ringtone( title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX), uri = ringtoneManager.getRingtoneUri(it) ) } } 

Di sini ringtoneManager.cursor akan mengembalikan kursor dengan semua nada dering yang tersedia, kami cukup memeriksa semua elemen dan memetakannya ke Ringtone kelas pembantu kami (akan lebih mudah untuk menggunakannya).


Pertama, mari kita mengatur kerja dengan daftar nada dering bawaan - menambahkan sumber daya kita nanti akan sangat sederhana. Untuk melakukan ini, buat dialog dengan mengganti metode onCreateDialog :


 private var ringtones: List<Ringtone> = emptyList() private var currentUri: Uri? = null override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { ringtones = getAndroidRingtones() currentUri = getCurrentRingtoneUri() val currentPosition = ringtones.indexOfFirst { currentUri == it.uri } return AlertDialog.Builder(context!!) .setPositiveButton(android.R.string.ok) { _, _ -> saveCurrentUri() } .setNegativeButton(android.R.string.cancel) { _, _ -> dialog.dismiss() } .setSingleChoiceItems(adapter, currentPosition) { _, which -> currentUri = ringtones[which].uri } .create() } 

Adaptor diperlukan untuk menampilkan daftar elemen dalam dialog, dapat didefinisikan sebagai berikut:


 private val adapter by lazy { SimpleAdapter( context, ringtones.map { mapOf("title" to it.title) }, R.layout.simple_list_item_single_choice, arrayOf("title"), intArrayOf(R.id.text1) ) } 

Dan Anda memerlukan metode pembantu lain untuk menyimpan posisi yang dipilih (itu akan dipanggil ketika Anda mengklik tombol OK):


 private fun saveCurrentUri() { PreferenceManager.getDefaultSharedPreferences(context) .edit() .putString(prefKey, currentUri?.toString()) .apply() } 

Masih mengikat elemen kami ke dialog, untuk ini kami mendefinisikan fungsi bantu dalam file dengan dialog:


 fun Preference.connectRingtoneDialog(fragmentManager: FragmentManager?) = setOnPreferenceClickListener { RingtonePreferenceDialog.create(key).apply { fragmentManager?.let { show(it, "SOUND") } } true } 

Dan tambahkan findPreference("ringtone").connectRingtoneDialog(fragmentManager) ke SettingsFragment kami, sekarang akan terlihat seperti ini:


 class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) findPreference("ringtone").connectRingtoneDialog(fragmentManager) } } 

Jika sekarang kita pergi ke layar pengaturan dan klik "Ringtone", kita akan melihat sesuatu seperti ini:



Sekarang tambahkan nada dering dari sumber daya ke dialog kami. Misalnya, kami memiliki nada dering sample.mp3 di folder res/raw , dan kami ingin menampilkannya di bagian atas daftar. Tambahkan metode lain ke kelas dialog:


 private fun getResourceRingtones(): List<Ringtone> = listOf( Ringtone( title = "Sample ringtone", uri = Uri.parse("${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context!!.packageName}/raw/sample") ) ) 

Dan ubah baris pertama dalam metode onCreateDialog :


 ringtones = getResourceRingtones() + getAndroidRingtones() 

Kami mulai, lihat, bersukacitalah karena semuanya sangat sederhana:



Tetap menambahkan "pratinjau" untuk nada dering. Untuk melakukan ini, masukkan bidang tambahan:


 private var playingRingtone: android.media.Ringtone? = null 

Dan sedikit mengubah metode panggilan balik untuk setSingleChoiceItems :


 playingRingtone?.stop() ringtones[which].also { currentUri = it.uri playingRingtone = it.uri?.let { RingtoneManager.getRingtone(context, it) } playingRingtone?.play() } 

Apa yang terjadi di sini: kita berhenti memainkan nada dering saat ini (jika bukan nol), atur yang dipilih sebagai nada saat ini, dan mulai pemutaran. Sekarang ketika Anda memilih nada dering dalam dialog, itu akan diputar. Untuk menghentikan pemutaran ketika dialog ditutup, onPause metode onPause :


 override fun onPause() { super.onPause() playingRingtone?.stop() } 

Nah, yang tersisa hanyalah menempelkan tombol di layar utama ke nada dering, misalnya, seperti ini:


 findViewById<Button>(R.id.playRingtone).setOnClickListener { val ringtone = PreferenceManager.getDefaultSharedPreferences(this) .getString("ringtone", null) ?.let { RingtoneManager.getRingtone(this, Uri.parse(it)) } if (ringtone == null) { Toast.makeText(this, "Select ringtone in settings", Toast.LENGTH_SHORT).show() } else { ringtone.play() } } 

Itu saja. Seperti yang dijanjikan, kode sumber dapat diambil di sini .

Source: https://habr.com/ru/post/id417883/


All Articles