How to allow clicking on disabled preferences (or mimic disabled preferences functionality)?

a 夏天 提交于 2019-12-12 04:12:51

问题


Background

Some app features require permissions. If a permission is not granted, we need the preference of it to be "semi" disabled (and not change if it's ticked or not), with a text telling that it cannot be used because there aren't enough granted permissions, so that it only partially looks disabled (the text will stay black, with the warning being red). It won't look like a normal disabled preference.

Like a normal disabled preference, though, when it's in this state, all preferences that depend on it will be disabled and un-clickable.

However, unlike a normal disabled preference, Upon clicking such a preference, it will go to a screen of granting the required permissions.

The problem

There are various ways to handle clicking on preferences, but none that I've found to handle clicking on a disabled preference.

Since various other preferences depend on such a preference (so that they get enabled/disabled based on whether it's enabled/disabled), I need to let it become disabled when needed, yet allow to click on it.

What I've tried

I tried various ways to handle clicking:

  • onPreferenceTreeClick inside the PreferenceFragment
  • setOnPreferenceClickListener on the preference itself
  • trying to override performClick of preference, but it's considered a bad thing because it's hidden
  • override onClick of preference.
  • in onCreateView or onBindView of the preference, use setOnClickListener on the view that's created.
  • wrap the view of onCreateView of the preference, and use setOnClickListener on the view or on the new view that wraps it.

All of those do not get called when the preference is disabled, and you try to click on the preference.

The questions

  1. Is it possible to disable a preference yet still handle clicks on it?

  2. Alternatively, is it possible extend the functionality of the dependencies of the preferences ? To make other preferences to be dependent on this preference, but not just based on whether it's enabled or not ? Meaning they are enabled only if this one is enabled AND it's not in this semi-enabled state?

    Currently, only CheckboxPreference is used on the app as the one that needs this new state, so it's easy to just make its checkbox look disabled, yet let the preference itself stay enabled (I just store the CheckBox view by using view.findViewById(android.R.id.checkbox) inside onCreateView method)


回答1:


OK, I've found a workaround for this:

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)
                    }
                }
            }
        }
    }

}

Having such a preference like that, when I called setAlwaysAllowClickingEnabled(true) on it, will cause the preference to really be disabled, yet when you click on it, it will call the callback.

In our case, we wanted to let the checkbox stay disabled, yet enable the title and summary TextViews, but you can do as you wish, depending on your requirements. Updated the code.



来源:https://stackoverflow.com/questions/40490502/how-to-allow-clicking-on-disabled-preferences-or-mimic-disabled-preferences-fun

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!