在用户设置时更新 Android 中的首选项摘要
Updating a preference summary in Android when the user sets it
我想使用偏好摘要来显示偏好的当前值,因此我想在偏好更改时更新摘要。有问题的首选项是一个存储位置,由用户通过意图以交互方式选择,使用 Android 的存储访问框架。几个小时以来,我一直在为此苦思冥想,尝试在 SO 线程中找到的各种东西,但我无法弄清楚 setSummary
、findPreference
、onSharedPreferenceChanged
的组合,onSharedPreferenceChangeListener
,在其中调用class,我需要
我的代码目前看起来像这样:
const val REQUEST_TARGET_FOLDER = 4
class SettingsActivity : AppCompatActivity() {
private lateinit var prefs: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
// from:
val targetDirPreference: Preference? = findPreference("export_dir")
targetDirPreference?.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
activity?.startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
with(prefs.edit()) {
putString("export_dir", intent.data.toString())
apply()
}
}
}
}
这是涉及的偏好:
<Preference
android:key="export_dir"
android:title="Export to directory:" />
有人可以帮我弄清楚当用户选择目录时如何设置/更新首选项的摘要吗? (目录选择部分本身目前有效。)
由于您是在首选项本身之外手动更改设置,因此您无法使用 SummaryProvider 执行此操作。相反,您必须在 (1) 摘要首次出现时和 (2) 手动更改首选项值并提交时手动更改摘要。 (您可以使用 OnSharedPreferenceChangeListener 自动执行第二步,但这更复杂。)
因此,创建一个更新其摘要的函数并在两个地方调用它:在 onCreatePreferences
和 onActivityResult
中您设置值的地方。
顺便说一下,您可以使用 preferences.edit { ... }
扩展函数而不是 with(preferences.edit) { ... ; apply() }
以获得更简单的代码。
class SettingsFragment : PreferenceFragmentCompat() {
private val TARGET_DIR_KEY = "export_dir"
private val prefs by lazy { preferenceManager.sharedPreferences }
private val targetDirPreference: Preference by lazy {
findPreference<Preference>(TARGET_DIR_KEY) ?: error("Missing target directory preference!")
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
targetDirPreference.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
updateTargetDirPreferenceSummary()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
prefs.edit {
putString(TARGET_DIR_KEY, intent.data.toString())
}
updateTargetDirPreferenceSummary()
}
}
private fun updateTargetDirPreferenceSummary() {
targetDirPreference.summary = prefs.getString("feedback", "")
}
}
或,如果您想以在片段中提供更清晰代码的方式解决此问题,您可以创建 Preference 的子类来帮助管理设置值的更改并在内部使用 SummaryProvider 机制自动更新自身。
class ManualStringPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
): Preference(context, attrs) {
init {
setSummaryProvider { getPersistedString("") }
}
var value: String = ""
set(inValue) {
if (inValue != field) {
field = inValue
persistString(inValue)
notifyChanged()
}
}
override fun onSetInitialValue(defaultValue: Any?) {
value = getPersistedString(defaultValue as? String ?: "")
}
}
您需要在 XML 中将此设置为您的偏好类型。
然后你的片段看起来像这样。请注意,您通过创建的 Preference 子类更改了 SharedPreferences 值。
class SettingsFragment : PreferenceFragmentCompat() {
private val prefs by lazy { preferenceManager.sharedPreferences }
private val targetDirPreference: ManualStringPreference by lazy {
findPreference<ManualStringPreference>("export_dir") ?: error("Missing target directory preference!")
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
targetDirPreference.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
targetDirPreference.value = intent.data.toString()
}
}
}
我想使用偏好摘要来显示偏好的当前值,因此我想在偏好更改时更新摘要。有问题的首选项是一个存储位置,由用户通过意图以交互方式选择,使用 Android 的存储访问框架。几个小时以来,我一直在为此苦思冥想,尝试在 SO 线程中找到的各种东西,但我无法弄清楚 setSummary
、findPreference
、onSharedPreferenceChanged
的组合,onSharedPreferenceChangeListener
,在其中调用class,我需要
我的代码目前看起来像这样:
const val REQUEST_TARGET_FOLDER = 4
class SettingsActivity : AppCompatActivity() {
private lateinit var prefs: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
// from:
val targetDirPreference: Preference? = findPreference("export_dir")
targetDirPreference?.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
activity?.startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
with(prefs.edit()) {
putString("export_dir", intent.data.toString())
apply()
}
}
}
}
这是涉及的偏好:
<Preference
android:key="export_dir"
android:title="Export to directory:" />
有人可以帮我弄清楚当用户选择目录时如何设置/更新首选项的摘要吗? (目录选择部分本身目前有效。)
由于您是在首选项本身之外手动更改设置,因此您无法使用 SummaryProvider 执行此操作。相反,您必须在 (1) 摘要首次出现时和 (2) 手动更改首选项值并提交时手动更改摘要。 (您可以使用 OnSharedPreferenceChangeListener 自动执行第二步,但这更复杂。)
因此,创建一个更新其摘要的函数并在两个地方调用它:在 onCreatePreferences
和 onActivityResult
中您设置值的地方。
顺便说一下,您可以使用 preferences.edit { ... }
扩展函数而不是 with(preferences.edit) { ... ; apply() }
以获得更简单的代码。
class SettingsFragment : PreferenceFragmentCompat() {
private val TARGET_DIR_KEY = "export_dir"
private val prefs by lazy { preferenceManager.sharedPreferences }
private val targetDirPreference: Preference by lazy {
findPreference<Preference>(TARGET_DIR_KEY) ?: error("Missing target directory preference!")
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
targetDirPreference.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
updateTargetDirPreferenceSummary()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
prefs.edit {
putString(TARGET_DIR_KEY, intent.data.toString())
}
updateTargetDirPreferenceSummary()
}
}
private fun updateTargetDirPreferenceSummary() {
targetDirPreference.summary = prefs.getString("feedback", "")
}
}
或,如果您想以在片段中提供更清晰代码的方式解决此问题,您可以创建 Preference 的子类来帮助管理设置值的更改并在内部使用 SummaryProvider 机制自动更新自身。
class ManualStringPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
): Preference(context, attrs) {
init {
setSummaryProvider { getPersistedString("") }
}
var value: String = ""
set(inValue) {
if (inValue != field) {
field = inValue
persistString(inValue)
notifyChanged()
}
}
override fun onSetInitialValue(defaultValue: Any?) {
value = getPersistedString(defaultValue as? String ?: "")
}
}
您需要在 XML 中将此设置为您的偏好类型。
然后你的片段看起来像这样。请注意,您通过创建的 Preference 子类更改了 SharedPreferences 值。
class SettingsFragment : PreferenceFragmentCompat() {
private val prefs by lazy { preferenceManager.sharedPreferences }
private val targetDirPreference: ManualStringPreference by lazy {
findPreference<ManualStringPreference>("export_dir") ?: error("Missing target directory preference!")
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
targetDirPreference.setOnPreferenceClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, REQUEST_TARGET_FOLDER)
true
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
// from:
if (requestCode == REQUEST_TARGET_FOLDER && resultCode == RESULT_OK && intent != null) {
val treeUri = intent.data
if (treeUri != null) {
// do stuff
}
targetDirPreference.value = intent.data.toString()
}
}
}