mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-19 19:42:17 +02:00
chore: allow optionally displaying a ListPreference
This exists as we want a dialog to show either a List or an EditText, and both the framework classes require inheritance For Issue 3114
This commit is contained in:
parent
0d46ac3523
commit
b4ba390061
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2024 David Allison <davidallisongithub@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates code under the following license
|
||||
*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Source: androidx.preference.ListPreferenceDialogFragmentCompat
|
||||
*
|
||||
* Changes:
|
||||
* * Convert to Kotlin
|
||||
* * Remove Hungarian Notation
|
||||
* * Rely on `ListPreferenceTrait` rather than `ListPreference`
|
||||
* * `bundleOf` + `.apply` usage
|
||||
* * `if (preference.callChangeListener(value)) {` - depend on `preference` and `listPreference`
|
||||
*/
|
||||
|
||||
package com.ichi2.preferences
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.preference.ListPreferenceDialogFragmentCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import androidx.preference.R
|
||||
|
||||
/**
|
||||
* A [Preference] may inherit from [ListPreferenceTrait] if it wishes to
|
||||
* optionally display a List-based dialog.
|
||||
* To do so, return a [ListPreferenceDialogFragment] via [DialogFragmentProvider.makeDialogFragment]
|
||||
*/
|
||||
// This exists as we want a dialog to show either a List or an EditText, and both the framework
|
||||
// classes require inheritance
|
||||
interface ListPreferenceTrait : DialogFragmentProvider {
|
||||
var listEntries: List<Entry>
|
||||
val entryKeys get() = listEntries.map { it.key }
|
||||
val entryValues get() = listEntries.map { it.value }
|
||||
|
||||
fun indexOf(value: String) = listEntries.indexOfFirst { it.value == value }
|
||||
|
||||
var listValue: String
|
||||
|
||||
data class Entry(val key: String, val value: String)
|
||||
|
||||
companion object {
|
||||
/** to be passed into defStyleAttr in the [Preference] constructor */
|
||||
val STYLE_ATTR = R.attr.dialogPreferenceStyle
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A fragment which may be launched from a [Preference] implementing a [ListPreferenceTrait]
|
||||
*
|
||||
* Adapted from: [ListPreferenceDialogFragmentCompat]
|
||||
* @see ListPreferenceDialogFragmentCompat
|
||||
*/
|
||||
class ListPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
|
||||
|
||||
/* synthetic access */
|
||||
private var clickedDialogEntryIndex = 0
|
||||
private lateinit var entries: Array<CharSequence>
|
||||
private lateinit var entryValues: Array<CharSequence>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
val preference = listPreference
|
||||
clickedDialogEntryIndex = preference.indexOf(preference.listValue)
|
||||
entries = preference.entryKeys.toTypedArray()
|
||||
entryValues = preference.entryValues.toTypedArray()
|
||||
} else {
|
||||
clickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0)
|
||||
entries = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRIES)!!
|
||||
entryValues = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES)!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putInt(SAVE_STATE_INDEX, clickedDialogEntryIndex)
|
||||
outState.putCharSequenceArray(SAVE_STATE_ENTRIES, entries)
|
||||
outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, entryValues)
|
||||
}
|
||||
|
||||
private val listPreference get() = preference as ListPreferenceTrait
|
||||
|
||||
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
builder.setSingleChoiceItems(
|
||||
entries,
|
||||
clickedDialogEntryIndex
|
||||
) { dialog, which ->
|
||||
clickedDialogEntryIndex = which
|
||||
|
||||
// Clicking on an item simulates the positive button click, and dismisses
|
||||
// the dialog.
|
||||
this.onClick(
|
||||
dialog,
|
||||
DialogInterface.BUTTON_POSITIVE
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// The typical interaction for list-based dialogs is to have click-on-an-item dismiss the
|
||||
// dialog instead of the user having to press 'Ok'.
|
||||
builder.setPositiveButton(null, null)
|
||||
}
|
||||
|
||||
override fun onDialogClosed(positiveResult: Boolean) {
|
||||
if (positiveResult && clickedDialogEntryIndex >= 0) {
|
||||
val value = entryValues[clickedDialogEntryIndex].toString()
|
||||
if (preference.callChangeListener(value)) {
|
||||
listPreference.listValue = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SAVE_STATE_INDEX = "ListPreferenceDialogFragment.index"
|
||||
private const val SAVE_STATE_ENTRIES = "ListPreferenceDialogFragment.entries"
|
||||
private const val SAVE_STATE_ENTRY_VALUES = "ListPreferenceDialogFragment.entryValues"
|
||||
|
||||
fun newInstance(key: String?): ListPreferenceDialogFragment =
|
||||
ListPreferenceDialogFragment().apply {
|
||||
arguments = bundleOf(ARG_KEY to key)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user