استغرق الأمر مني هنا لمشروع واحد لجعل حواري مع اختيار نغمة الرنين في الإعدادات. على الفور لسببين - أولاً ، لا يوجد RingtonePreference
في مكتبة الدعم ، لذلك سيفشل استخدام مربع الحوار القياسي في PreferenceFragmentCompat
. وثانيًا ، بالإضافة إلى الألحان القياسية ، كان عليّ إضافة بعض الأصوات من الموارد هناك. لذلك تقرر كتابة حوارك.
سأوضح إنشاء مثل هذا الحوار باستخدام مثال لتطبيق بسيط: على شاشة واحدة يوجد زر "تشغيل نغمة رنين" ، والنقر فوق الذي يتم تشغيل نغمة الرنين في الإعدادات ، ورابط إلى شاشة الإعدادات:
لن أصف إنشاء هاتين الشاشتين - كل شيء موجود كما هو الحال دائمًا. فقط في الحالة ، في النهاية سيكون هناك رابط إلى المستودع برمز التطبيق.
لذا ، لنبدأ بملف xml مع وصف شاشة الإعدادات. ضع ملف settings.xml
في res/xml
بالمحتويات التالية:
<?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>
والآن دعنا نضيف هذه الإعدادات إلى الجزء الخاص بنا:
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) } }
قم بتشغيل ، افتح شاشة الإعدادات ، انظر ما يلي:
المقدمة تنتهي هنا ، ننتقل إلى الغرض من المقالة. الخطة هي: عند النقر على "نغمة الرنين" ، يفتح مربع حوار بقائمة من نغمات الرنين وأزرار "موافق" و "إلغاء" ، عند تحديد نغمة رنين ، يتم تشغيلها (كما في حالة RingtonePreference
القياسية) ، عند النقر فوق "موافق" ، يتم حفظها في الإعدادات.
لذا ، قم بإنشاء جزء حوار:
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 } } }
في prefKey
نقوم بنقل المفتاح الذي سيتم من خلاله استخراج نغمة الرنين الحالية ، وسيتم تسجيله بالضغط على الزر موافق.
لمزيد من العمل ، نحن بحاجة إلى Ringtone
الدرجة المساعدة ، نعلنها داخل الجزء الخاص بنا:
private data class Ringtone(val title: String, val uri: Uri)
وكتابة وظيفة مساعدة ستسحب جميع نغمات الرنين المدمجة في Android ، وتعيد القائمة من 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) ) } }
هنا ringtoneManager.cursor
سيعيد المؤشر مع جميع النغمات المتاحة ، ننتقل فقط عبر جميع العناصر ونعينها إلى فئة Ringtone
المساعد لدينا (إنه أكثر ملاءمة للعمل معها).
أولاً ، دعنا ننظم العمل مع قائمة نغمات الرنين المدمجة - إضافة مواردنا لاحقًا ستكون بسيطة للغاية. للقيام بذلك ، قم بإنشاء مربع حوار عن طريق تجاوز طريقة 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() }
مطلوب محول لعرض قائمة بالعناصر في مربع حوار ؛ يمكن تعريفه على النحو التالي:
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) ) }
وتحتاج إلى طريقة مساعدة أخرى لحفظ الوضع المحدد (سيتم استدعاؤها عند النقر فوق الزر موافق):
private fun saveCurrentUri() { PreferenceManager.getDefaultSharedPreferences(context) .edit() .putString(prefKey, currentUri?.toString()) .apply() }
يبقى ربط عنصرنا بمربع الحوار ، لذلك نحدد وظيفة مساعدة في الملف مع مربع الحوار:
fun Preference.connectRingtoneDialog(fragmentManager: FragmentManager?) = setOnPreferenceClickListener { RingtonePreferenceDialog.create(key).apply { fragmentManager?.let { show(it, "SOUND") } } true }
وأضف findPreference("ringtone").connectRingtoneDialog(fragmentManager)
إلى SettingsFragment
، الآن يجب أن يبدو findPreference("ringtone").connectRingtoneDialog(fragmentManager)
:
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) findPreference("ringtone").connectRingtoneDialog(fragmentManager) } }
إذا انتقلنا الآن إلى شاشة الإعدادات ونقرنا على "نغمة الرنين" ، فسوف نرى شيئًا مثل هذا:
أضف الآن نغمات من الموارد إلى حوارنا. على سبيل المثال ، لدينا نغمة رنين sample.mp3
في المجلد res/raw
، ونريد عرضها في أعلى القائمة. أضف طريقة أخرى إلى فئة الحوار:
private fun getResourceRingtones(): List<Ringtone> = listOf( Ringtone( title = "Sample ringtone", uri = Uri.parse("${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context!!.packageName}/raw/sample") ) )
وتغيير السطر الأول في طريقة onCreateDialog
:
ringtones = getResourceRingtones() + getAndroidRingtones()
نبدأ ، انظر ، نفرح بأن كل شيء بسيط للغاية:
يبقى إضافة "معاينة" لنغمات الرنين. للقيام بذلك ، أدخل حقلًا إضافيًا:
private var playingRingtone: android.media.Ringtone? = null
setSingleChoiceItems
بتغيير طريقة رد الاتصال قليلاً لـ setSingleChoiceItems
:
playingRingtone?.stop() ringtones[which].also { currentUri = it.uri playingRingtone = it.uri?.let { RingtoneManager.getRingtone(context, it) } playingRingtone?.play() }
ما يحدث هنا: نتوقف عن تشغيل نغمة الرنين الحالية (إذا لم تكن فارغة) ، قم بتعيين النغمة المحددة كنغمة الرنين الحالية ، وبدء التشغيل. الآن عند تحديد نغمة رنين في الحوار ، سيتم تشغيلها. لإيقاف التشغيل عند إغلاق مربع الحوار ، onPause
تعريف طريقة onPause
:
override fun onPause() { super.onPause() playingRingtone?.stop() }
حسنًا ، كل ما تبقى هو إرفاق الزر على الشاشة الرئيسية بنغمة الرنين ، على سبيل المثال ، مثل:
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() } }
هذا كل شيء. كما وعدت ، يمكن أن تؤخذ التعليمات البرمجية المصدر هنا .