Обычный Preference не будет обрабатывать нажатия, если его отключить (установить setEnabled(false)). Но обработать события нажатия ( OnPreferenceClickListener) на деакцивированную опцию иногда может понадобится.
Я использовал такой способ, но может есть способ проще.
К сожалению в родительском классе Preference метод, в котором происходит непосредственная проверка возможности нажатия и вызов обработчика, закрыт от переопределения.
Поэтому пришлось переопределять несколько переменных, в которых хранится некоторые состояния вьюшки ( IsEnabled, DependencyMet, ParentDependencyMet), и методов класса, которые используют эти состояния.
Но есть косяк – если необходимо получить актуальное значение активности вьюшки, то нужно использовать отдельный метод isEnabled2().
Для классов ListPreference и CheckBoxPreference все аналогично.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
public class DisabledPreference extends Preference { protected boolean mIsEnabled2 = true; protected boolean mDependencyMet2 = true; protected boolean mParentDependencyMet2 = true; @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public DisabledPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public DisabledPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public DisabledPreference(Context context, AttributeSet attrs) { super(context, attrs); } public DisabledPreference(Context context) { super(context); } @Override public void setEnabled(boolean enabled) { // меняем "системный" isEnabled на свой, // т.к. при установке false у системного - у опции отключается вызов обработчика нажатия (onClick) if (mIsEnabled2 != enabled) { mIsEnabled2 = enabled; // Enabled state can change dependent preferences' states, so notify notifyDependencyChange(shouldDisableDependents()); notifyChanged(); } } @Override public boolean isEnabled() { // возвращаем всегда true, чтобы не отключилась вьюшка "системой" и не // заблокировался вызов обработчика нажатия onClick return true; } public boolean isEnabled2() { return mIsEnabled2 && mDependencyMet2 && mParentDependencyMet2; } @Override protected void onClick() { // если опция не активна, блокируем ее установку в методе setChecked(), который // вызывается в специальном обработчике onClick() if (isEnabled2()) { super.onClick(); } } @Override public boolean shouldDisableDependents() { // проверка нужно ли отключать зависимые опции return !isEnabled2(); } @Override public void onDependencyChanged(Preference dependency, boolean disableDependent) { // проверка активности вьюшки, от которой зависим this.mDependencyMet2 = !disableDependent; super.onDependencyChanged(dependency, disableDependent); } @Override public void onParentChanged(Preference parent, boolean disableChild) { // проверка активности родительской вьюшки this.mParentDependencyMet2 = !disableChild; super.onParentChanged(parent, disableChild); } @Override protected void onBindView(View view) { super.onBindView(view); // отключаем вьюшки, если нужно (при этом сохраняется обработчик нажатия onClick) if (getShouldDisableView()) { setEnabledStateOnViews(view, isEnabled2()); } } } |
Для Preference из библиотеки совместимости AndroidX достаточно будет изменить метод onBindView на onBindViewHolder:
1 2 3 4 5 6 7 8 9 10 11 |
@Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); // отключаем вьюшки, если нужно (при этом сохраняется обработчик нажатия onClick) if (getShouldDisableView()) { ViewUtils.setEnabledStateOnViews(holder.itemView, isEnabled2()); holder.itemView.setEnabled(true); } else { setEnabledStateOnViews(holder.itemView, true); } } |
Метод setEnabledStateOnViews был взят из Preference как есть:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * Makes sure the view (and any children) get the enabled state changed. */ public static void setEnabledStateOnViews(View v, boolean enabled) { if (v == null) return; v.setEnabled(enabled); if (v instanceof ViewGroup) { final ViewGroup vg = (ViewGroup) v; for (int i = vg.getChildCount() - 1; i >= 0; i--) { setEnabledStateOnViews(vg.getChildAt(i), enabled); } } } |
Пример использования:
1 2 3 4 5 6 |
Preference pref = findPreference("pref_key_test"); pref.setEnabled(false); pref.setOnPreferenceClickListener(pref1 -> { Toast.show(getContext(), "Option available in Pro", Toast.LENGTH_SHORT); return true; }); |