如何允许点击禁用的首选项(或模拟禁用的首选项功能)?
How to allow clicking on disabled preferences (or mimic disabled preferences functionality)?
背景
某些应用功能需要权限。如果未授予权限,我们需要将它的首选项设置为“半”禁用(并且无论是否勾选都不会更改),并带有一条文本告诉它无法使用,因为没有足够的授予权限,因此它看起来只是部分禁用(文本将保持黑色,警告为红色)。它看起来不像是正常的禁用偏好。
不过,与正常的禁用首选项一样,当它处于此状态时,所有依赖于它的首选项都将被禁用且不可点击。
但是,与正常禁用的首选项不同,单击此类首选项后,它将转到授予所需权限的屏幕。
问题
有多种方法可以处理点击首选项,但 none 我发现可以处理点击已禁用的首选项。
由于其他各种偏好都依赖于这种偏好(因此它们会根据是否为 enabled/disabled 而获得 enabled/disabled),因此我需要在需要时将其禁用,但允许点击它。
我试过的
我尝试了多种处理点击的方法:
- PreferenceFragment 内的 onPreferenceTreeClick
- 在首选项本身上设置OnPreferenceClickListener
- 试图覆盖首选项的 performClick,但它被认为是一件坏事,因为它是隐藏的
- 覆盖首选项的 onClick。
- 在首选项的 onCreateView 或 onBindView 中,对创建的视图使用 setOnClickListener。
- 包装preference的onCreateView视图,并在视图或包装它的新视图上使用setOnClickListener。
当首选项被禁用时,所有这些都不会被调用,并且您尝试单击首选项。
问题
是否可以禁用首选项但仍然处理对它的点击?
或者,是否可以扩展首选项依赖项的功能?要使其他首选项依赖于此首选项,而不仅仅是基于它是否启用?意味着它们只有在这个启用并且不处于半启用状态时才启用?
目前,只有 CheckboxPreference 在应用程序上用作需要此新状态的应用程序,因此很容易使其复选框看起来已禁用,但让首选项本身保持启用状态(我只是通过使用存储 CheckBox 视图view.findViewById(android.R.id.checkbox) 在 onCreateView 方法中)
好的,我找到了一个解决方法:
class CheckboxPreferenceEx : android.preference.CheckBoxPreference {
var alwaysAllowClickingEnabled: Boolean = false
private val onPreferenceViewClickListener: View.OnClickListener
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
init {
onPreferenceViewClickListener = View.OnClickListener {
if (onPreferenceChangeListener != null && !isEnabled)
if (onPreferenceChangeListener.onPreferenceChange(this@CheckboxPreferenceEx, !isChecked))
isChecked = !isChecked
if (this@CheckboxPreferenceEx.isEnabled)
this@CheckboxPreferenceEx.onClick()
}
}
override fun onCreateView(parent: ViewGroup): View {
val view = super.onCreateView(parent)
setPreferenceTitleTextViewToHaveMultipleLines(view)
//mTitleTextView = (TextView) view.findViewById(android.R.id.title);
//mSummaryTextView = (TextView) view.findViewById(android.R.id.summary);
return view
}
override fun onBindView(view: View) {
super.onBindView(view)
view.setOnClickListener(onPreferenceViewClickListener)
val dependency = dependency
if (!TextUtils.isEmpty(dependency) && !isEnabled) {
//if the reason this preference is disabled is because of dependency, act as normal
val dependencyPreference = preferenceManager.findPreference(dependency)
if (!dependencyPreference!!.isEnabled || dependencyPreference is TwoStatePreference && !dependencyPreference.isChecked)
return
}
if (alwaysAllowClickingEnabled) {
//we chose to enable all except for the checkbox, which will still look disabled
view.isEnabled = true
setEnabledToViewAndItsDescendants(view, true)
}
}
companion object {
fun setPreferenceTitleTextViewToHaveMultipleLines(v: View) {
if (v is TextView && v.getId() == android.R.id.title) {
v.setSingleLine(false)
return
}
if (v is ViewGroup) {
for (i in 0 until v.childCount) {
val child = v.getChildAt(i)
setPreferenceTitleTextViewToHaveMultipleLines(child)
}
}
}
fun setEnabledToViewAndItsDescendants(v: View?, enabled: Boolean) {
if (v == null)
return
v.isEnabled = enabled
if (v is ViewGroup) {
val viewGroups = ArrayList<ViewGroup>()
viewGroups.add(v)
while (!viewGroups.isEmpty()) {
val viewGroup = viewGroups.removeAt(0)
val childCount = viewGroup.childCount
for (i in 0 until childCount) {
val childView = viewGroup.getChildAt(i)
childView.isEnabled = enabled
if (childView is ViewGroup)
viewGroups.add(childView)
}
}
}
}
}
}
有这样的偏好设置,当我在它上面调用setAlwaysAllowClickingEnabled(true)时,会导致偏好设置真的被禁用,但是当你点击它时,它会调用回调。
在我们的例子中,我们想让复选框保持禁用状态,但启用标题和摘要 TextView,但您可以根据自己的要求按您的意愿进行操作。更新了代码。
背景
某些应用功能需要权限。如果未授予权限,我们需要将它的首选项设置为“半”禁用(并且无论是否勾选都不会更改),并带有一条文本告诉它无法使用,因为没有足够的授予权限,因此它看起来只是部分禁用(文本将保持黑色,警告为红色)。它看起来不像是正常的禁用偏好。
不过,与正常的禁用首选项一样,当它处于此状态时,所有依赖于它的首选项都将被禁用且不可点击。
但是,与正常禁用的首选项不同,单击此类首选项后,它将转到授予所需权限的屏幕。
问题
有多种方法可以处理点击首选项,但 none 我发现可以处理点击已禁用的首选项。
由于其他各种偏好都依赖于这种偏好(因此它们会根据是否为 enabled/disabled 而获得 enabled/disabled),因此我需要在需要时将其禁用,但允许点击它。
我试过的
我尝试了多种处理点击的方法:
- PreferenceFragment 内的 onPreferenceTreeClick
- 在首选项本身上设置OnPreferenceClickListener
- 试图覆盖首选项的 performClick,但它被认为是一件坏事,因为它是隐藏的
- 覆盖首选项的 onClick。
- 在首选项的 onCreateView 或 onBindView 中,对创建的视图使用 setOnClickListener。
- 包装preference的onCreateView视图,并在视图或包装它的新视图上使用setOnClickListener。
当首选项被禁用时,所有这些都不会被调用,并且您尝试单击首选项。
问题
是否可以禁用首选项但仍然处理对它的点击?
或者,是否可以扩展首选项依赖项的功能?要使其他首选项依赖于此首选项,而不仅仅是基于它是否启用?意味着它们只有在这个启用并且不处于半启用状态时才启用?
目前,只有 CheckboxPreference 在应用程序上用作需要此新状态的应用程序,因此很容易使其复选框看起来已禁用,但让首选项本身保持启用状态(我只是通过使用存储 CheckBox 视图view.findViewById(android.R.id.checkbox) 在 onCreateView 方法中)
好的,我找到了一个解决方法:
class CheckboxPreferenceEx : android.preference.CheckBoxPreference {
var alwaysAllowClickingEnabled: Boolean = false
private val onPreferenceViewClickListener: View.OnClickListener
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
init {
onPreferenceViewClickListener = View.OnClickListener {
if (onPreferenceChangeListener != null && !isEnabled)
if (onPreferenceChangeListener.onPreferenceChange(this@CheckboxPreferenceEx, !isChecked))
isChecked = !isChecked
if (this@CheckboxPreferenceEx.isEnabled)
this@CheckboxPreferenceEx.onClick()
}
}
override fun onCreateView(parent: ViewGroup): View {
val view = super.onCreateView(parent)
setPreferenceTitleTextViewToHaveMultipleLines(view)
//mTitleTextView = (TextView) view.findViewById(android.R.id.title);
//mSummaryTextView = (TextView) view.findViewById(android.R.id.summary);
return view
}
override fun onBindView(view: View) {
super.onBindView(view)
view.setOnClickListener(onPreferenceViewClickListener)
val dependency = dependency
if (!TextUtils.isEmpty(dependency) && !isEnabled) {
//if the reason this preference is disabled is because of dependency, act as normal
val dependencyPreference = preferenceManager.findPreference(dependency)
if (!dependencyPreference!!.isEnabled || dependencyPreference is TwoStatePreference && !dependencyPreference.isChecked)
return
}
if (alwaysAllowClickingEnabled) {
//we chose to enable all except for the checkbox, which will still look disabled
view.isEnabled = true
setEnabledToViewAndItsDescendants(view, true)
}
}
companion object {
fun setPreferenceTitleTextViewToHaveMultipleLines(v: View) {
if (v is TextView && v.getId() == android.R.id.title) {
v.setSingleLine(false)
return
}
if (v is ViewGroup) {
for (i in 0 until v.childCount) {
val child = v.getChildAt(i)
setPreferenceTitleTextViewToHaveMultipleLines(child)
}
}
}
fun setEnabledToViewAndItsDescendants(v: View?, enabled: Boolean) {
if (v == null)
return
v.isEnabled = enabled
if (v is ViewGroup) {
val viewGroups = ArrayList<ViewGroup>()
viewGroups.add(v)
while (!viewGroups.isEmpty()) {
val viewGroup = viewGroups.removeAt(0)
val childCount = viewGroup.childCount
for (i in 0 until childCount) {
val childView = viewGroup.getChildAt(i)
childView.isEnabled = enabled
if (childView is ViewGroup)
viewGroups.add(childView)
}
}
}
}
}
}
有这样的偏好设置,当我在它上面调用setAlwaysAllowClickingEnabled(true)时,会导致偏好设置真的被禁用,但是当你点击它时,它会调用回调。
在我们的例子中,我们想让复选框保持禁用状态,但启用标题和摘要 TextView,但您可以根据自己的要求按您的意愿进行操作。更新了代码。