Show a message when disabled preferences are clicked

Now preference is not disabled but view within the preferences are disabled. So the preference can still get the clicks and a message will be displayed.

Bug: 168308383
Test: Manual, paintbooth
Change-Id: I1ae6b1e69ba6b16f9255e711aea280f8ccb79753
Merged-In: I1ae6b1e69ba6b16f9255e711aea280f8ccb79753
diff --git a/car-ui-lib/res/values/attrs.xml b/car-ui-lib/res/values/attrs.xml
index 37c10c1..5698d25 100644
--- a/car-ui-lib/res/values/attrs.xml
+++ b/car-ui-lib/res/values/attrs.xml
@@ -128,6 +128,8 @@
     <declare-styleable name="CarUiPreference">
         <!-- Toggle for showing chevron -->
         <attr name="showChevron" format="boolean" />
+        <!-- Show ripple when disabled preference is clicked -->
+        <attr name="showRippleOnDisabledPreference" format="boolean" />
     </declare-styleable>
 
     <!-- Theme attribute to specify a default style for all CarUiPreferences -->
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
index 5db22cf..2fbbacb 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
@@ -18,9 +18,15 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
 
+import androidx.core.view.ViewCompat;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
 
 import com.android.car.ui.R;
 
@@ -32,6 +38,12 @@
 
     private Context mContext;
     private boolean mShowChevron;
+    private String mMessageToShowWhenDisabledPreferenceClicked;
+
+    private boolean mShouldShowRippleOnDisabledPreference;
+    private boolean mEnabledAppearance = true;
+    private Drawable mBackground;
+    private View mPreference;
 
     public CarUiPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
@@ -61,6 +73,46 @@
                 defStyleRes);
 
         mShowChevron = a.getBoolean(R.styleable.CarUiPreference_showChevron, true);
+        mShouldShowRippleOnDisabledPreference = a.getBoolean(
+                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
+    }
+
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        boolean viewEnabled = isEnabled();
+        if (viewEnabled) {
+            if (mBackground != null) {
+                ViewCompat.setBackground(holder.itemView, mBackground);
+            }
+            enableView(holder.itemView, true, false);
+        } else {
+            holder.itemView.setEnabled(true);
+            mPreference = holder.itemView;
+            if (mBackground == null) {
+                // store the original background.
+                mBackground = mPreference.getBackground();
+            }
+            if (!mShouldShowRippleOnDisabledPreference) {
+                ViewCompat.setBackground(mPreference, null);
+            } else if (mBackground != null) {
+                ViewCompat.setBackground(mPreference, mBackground);
+            }
+            enableView(holder.itemView, false, true);
+        }
+    }
+
+    private void enableView(View view, boolean enabled, boolean isRootView) {
+        if (!isRootView) {
+            view.setEnabled(enabled);
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup grp = (ViewGroup) view;
+            for (int index = 0; index < grp.getChildCount(); index++) {
+                enableView(grp.getChildAt(index), enabled, false);
+            }
+        }
     }
 
     @Override
@@ -80,7 +132,46 @@
         }
     }
 
+    /**
+     * This is similar to {@link Preference#performClick()} with the only difference that we do not
+     * return when view is not enabled.
+     */
+    @Override
+    public void performClick() {
+        if (isEnabled()) {
+            super.performClick();
+        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
+                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
+            Toast toast = Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
+                    Toast.LENGTH_LONG);
+            toast.show();
+        }
+    }
+
     public void setShowChevron(boolean showChevron) {
         mShowChevron = showChevron;
     }
+
+    /**
+     * Sets the ripple on the disabled preference.
+     */
+    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
+        mShouldShowRippleOnDisabledPreference = showRipple;
+        updateRippleStateOnDisabledPreference();
+    }
+
+    private void updateRippleStateOnDisabledPreference() {
+        if (isEnabled()) {
+            return;
+        }
+        if (mShouldShowRippleOnDisabledPreference && mPreference != null) {
+            ViewCompat.setBackground(mPreference, mBackground);
+        } else if (mPreference != null) {
+            ViewCompat.setBackground(mPreference, null);
+        }
+    }
+
+    public void setMessageToShowWhenDisabledPreferenceClicked(String message) {
+        mMessageToShowWhenDisabledPreferenceClicked = message;
+    }
 }
diff --git a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml b/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
index b49dd0d..0a0836a 100644
--- a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
+++ b/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
@@ -19,132 +19,155 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     app:title="@string/preferences_screen_title">
 
-  <PreferenceCategory
-      android:title="@string/basic_preferences">
+    <PreferenceCategory
+        android:title="@string/basic_preferences">
 
-    <Preference
-        android:key="preference"
-        android:title="@string/title_basic_preference"
-        android:summary="@string/summary_basic_preference"/>
+        <Preference
+            android:key="preference"
+            android:summary="@string/summary_basic_preference"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="stylized"
-        android:title="@string/title_stylish_preference"
-        android:summary="@string/summary_stylish_preference"/>
+        <Preference
+            android:key="preference_disabled_without_ripple"
+            android:summary="Without ripple"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="icon"
-        android:title="@string/title_icon_preference"
-        android:summary="@string/summary_icon_preference"
-        android:icon="@drawable/ic_settings_wifi"/>
+        <Preference
+            android:key="preference_disabled_with_ripple"
+            android:summary="With ripple"
+            android:title="@string/title_basic_preference"/>
 
-    <Preference
-        android:key="single_line_title"
-        android:title="@string/title_single_line_title_preference"
-        android:summary="@string/summary_single_line_title_preference"
-        app:singleLineTitle="true"/>
+        <Preference
+            android:key="stylized"
+            android:dependency="preference"
+            android:summary="@string/summary_stylish_preference"
+            android:title="@string/title_stylish_preference"/>
 
-    <Preference
-        android:key="single_line_no_summary"
-        android:title="@string/title_single_line_no_summary"
-        app:singleLineTitle="true"/>
-  </PreferenceCategory>
+        <Preference
+            android:icon="@drawable/ic_settings_wifi"
+            android:key="icon"
+            android:summary="@string/summary_icon_preference"
+            android:title="@string/title_icon_preference"/>
 
-  <PreferenceCategory
-      android:title="@string/widgets">
+        <Preference
+            android:key="single_line_title"
+            android:summary="@string/summary_single_line_title_preference"
+            android:title="@string/title_single_line_title_preference"
+            app:singleLineTitle="true"/>
 
-    <CheckBoxPreference
-        android:key="checkbox"
-        android:title="@string/title_checkbox_preference"
-        android:summary="@string/summary_checkbox_preference"/>
+        <Preference
+            android:key="single_line_no_summary"
+            android:title="@string/title_single_line_no_summary"
+            app:singleLineTitle="true"/>
+    </PreferenceCategory>
 
-    <SwitchPreference
-        android:key="switch"
-        android:title="@string/title_switch_preference"
-        android:summary="@string/summary_switch_preference"/>
+    <PreferenceCategory
+        android:title="@string/widgets">
 
-    <DropDownPreference
-        android:key="dropdown"
-        android:title="@string/title_dropdown_preference"
-        android:entries="@array/entries"
-        app:useSimpleSummaryProvider="true"
-        android:entryValues="@array/entry_values"/>
+        <CheckBoxPreference
+            android:key="checkbox"
+            android:summary="@string/summary_checkbox_preference"
+            android:title="@string/title_checkbox_preference"/>
 
-    <SeekBarPreference
-        android:key="seekbar"
-        android:title="@string/title_seekbar_preference"
-        android:max="10"
-        android:defaultValue="5"/>
-  </PreferenceCategory>
+        <DropDownPreference
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="dropdown"
+            android:title="@string/title_dropdown_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-  <PreferenceCategory
-      android:title="@string/dialogs">
+        <SeekBarPreference
+            android:defaultValue="5"
+            android:key="seekbar"
+            android:max="10"
+            android:title="@string/title_seekbar_preference"/>
 
-    <EditTextPreference
-        android:key="edittext"
-        android:title="@string/title_edittext_preference"
-        app:useSimpleSummaryProvider="true"
-        android:dialogTitle="@string/dialog_title_edittext_preference"/>
+        <SwitchPreference
+            android:key="switch"
+            android:summary="@string/summary_switch_preference"
+            android:title="@string/title_switch_preference"/>
 
-    <ListPreference
-        android:key="list"
-        android:title="@string/title_list_preference"
-        app:useSimpleSummaryProvider="true"
-        android:entries="@array/entries"
-        android:entryValues="@array/entry_values"
-        android:dialogTitle="@string/dialog_title_list_preference"/>
+        <com.android.car.ui.preference.CarUiTwoActionPreference
+            android:key="twoaction"
+            android:summary="@string/summary_twoaction_preference"
+            android:title="@string/title_twoaction_preference"
+            android:widgetLayout="@layout/details_preference_widget"/>
+    </PreferenceCategory>
 
-    <MultiSelectListPreference
-        android:key="multi_select_list"
-        android:title="@string/title_multi_list_preference"
-        android:summary="@string/summary_multi_list_preference"
-        android:entries="@array/entries"
-        android:entryValues="@array/entry_values"
-        android:dialogTitle="@string/dialog_title_multi_list_preference"/>
-  </PreferenceCategory>
+    <PreferenceCategory
+        android:title="@string/dialogs">
 
-  <PreferenceCategory
-      android:key="@string/advanced_preference"
-      android:title="@string/advanced_attributes"
-      app:initialExpandedChildrenCount="1">
+        <EditTextPreference
+            android:dialogTitle="@string/dialog_title_edittext_preference"
+            android:key="edittext"
+            android:title="@string/title_edittext_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-    <Preference
-        android:key="expandable"
-        android:title="@string/title_expandable_preference"
-        android:summary="@string/summary_expandable_preference"/>
+        <ListPreference
+            android:dialogTitle="@string/dialog_title_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="list"
+            android:title="@string/title_list_preference"
+            app:useSimpleSummaryProvider="true"/>
 
-    <Preference
-        android:title="@string/title_intent_preference"
-        android:summary="@string/summary_intent_preference">
+        <MultiSelectListPreference
+            android:dialogTitle="@string/dialog_title_multi_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="multi_select_list"
+            android:summary="@string/summary_multi_list_preference"
+            android:title="@string/title_multi_list_preference"/>
 
-      <intent android:action="android.intent.action.VIEW"
-          android:data="http://www.android.com"/>
+        <com.android.car.ui.preference.CarUiSeekBarDialogPreference
+            android:dialogTitle="Seekbar Dialog"
+            android:key="seekbarDialog"
+            android:summary="@string/summary_seekbar_preference"
+            android:title="@string/title_seekbar_preference"/>
+    </PreferenceCategory>
 
-    </Preference>
+    <PreferenceCategory
+        android:key="@string/advanced_preference"
+        android:title="@string/advanced_attributes"
+        app:initialExpandedChildrenCount="1">
 
-    <SwitchPreference
-        android:key="parent"
-        android:title="@string/title_parent_preference"
-        android:summary="@string/summary_parent_preference"/>
+        <Preference
+            android:key="expandable"
+            android:summary="@string/summary_expandable_preference"
+            android:title="@string/title_expandable_preference"/>
 
-    <SwitchPreference
-        android:key="child"
-        android:dependency="parent"
-        android:title="@string/title_child_preference"
-        android:summary="@string/summary_child_preference"/>
+        <Preference
+            android:summary="@string/summary_intent_preference"
+            android:title="@string/title_intent_preference">
 
-    <SwitchPreference
-        android:key="toggle_summary"
-        android:title="@string/title_toggle_summary_preference"
-        android:summaryOn="@string/summary_on_toggle_summary_preference"
-        android:summaryOff="@string/summary_off_toggle_summary_preference"/>
+            <intent android:action="android.intent.action.VIEW"
+                    android:data="http://www.android.com"/>
 
-    <Preference
-        android:key="copyable"
-        android:title="@string/title_copyable_preference"
-        android:summary="@string/summary_copyable_preference"
-        android:selectable="false"
-        app:enableCopying="true"/>
-  </PreferenceCategory>
+        </Preference>
+
+        <Preference
+            android:key="copyable"
+            android:selectable="false"
+            android:summary="@string/summary_copyable_preference"
+            android:title="@string/title_copyable_preference"
+            app:enableCopying="true"/>
+
+        <SwitchPreference
+            android:dependency="parent"
+            android:key="child"
+            android:summary="@string/summary_child_preference"
+            android:title="@string/title_child_preference"/>
+
+        <SwitchPreference
+            android:key="toggle_summary"
+            android:summaryOff="@string/summary_off_toggle_summary_preference"
+            android:summaryOn="@string/summary_on_toggle_summary_preference"
+            android:title="@string/title_toggle_summary_preference"/>
+
+        <SwitchPreference
+            android:key="parent"
+            android:summary="@string/summary_parent_preference"
+            android:title="@string/title_parent_preference"/>
+    </PreferenceCategory>
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
index ccd21ef..e9f990d 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 
 import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.preference.CarUiPreference;
 import com.android.car.ui.preference.PreferenceFragment;
 
 /**
@@ -30,5 +31,18 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         // Load the preferences from an XML resource
         setPreferencesFromResource(R.xml.preference_samples, rootKey);
+        CarUiPreference preferenceDisabledWithoutRipple = findPreference(
+                "preference_disabled_without_ripple");
+        preferenceDisabledWithoutRipple.setEnabled(false);
+        preferenceDisabledWithoutRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithoutRipple.setShouldShowRippleOnDisabledPreference(false);
+
+        CarUiPreference preferenceDisabledWithRipple = findPreference(
+                "preference_disabled_with_ripple");
+        preferenceDisabledWithRipple.setEnabled(false);
+        preferenceDisabledWithRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithRipple.setShouldShowRippleOnDisabledPreference(true);
     }
 }