OSDN Git Service

Expand more buttons for ActionButtonPreference
authortmfang <tmfang@google.com>
Tue, 27 Nov 2018 09:46:13 +0000 (17:46 +0800)
committertmfang <tmfang@google.com>
Wed, 28 Nov 2018 02:24:07 +0000 (10:24 +0800)
Old design, we only need two action buttons in Settings app.
In the future, we need four buttons for some use cases.

Test: visual, robotest
Bug: 120005054
Change-Id: I859fee8d7167ce59222059cc441e4a3c167c7b34

res/layout/settings_action_buttons.xml [moved from res/layout/two_action_buttons.xml with 70% similarity]
res/values/styles.xml
src/com/android/settings/widget/ActionButtonPreference.java
tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java

similarity index 70%
rename from res/layout/two_action_buttons.xml
rename to res/layout/settings_action_buttons.xml
index 2b4aa5d..56e1a36 100644 (file)
@@ -20,7 +20,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingStart="8dp"
-    android:paddingEnd="8dp"
     android:orientation="horizontal">
 
     <Button
         style="@style/SettingsActionButton"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:paddingTop="20dp"
-        android:paddingBottom="20dp"/>
-    <Space
-        android:layout_width="8dp"
-        android:layout_height="wrap_content" />
+        android:layout_weight="1"/>
 
     <Button
         android:id="@+id/button2"
         style="@style/SettingsActionButton"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:paddingTop="20dp"
-        android:paddingBottom="20dp"/>
+        android:layout_weight="1"/>
+
+    <Button
+        android:id="@+id/button3"
+        style="@style/SettingsActionButton"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
+
+    <Button
+        android:id="@+id/button4"
+        style="@style/SettingsActionButton"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
 </LinearLayout>
\ No newline at end of file
index 4be1bb3..c2ce0e7 100644 (file)
     <style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
         <item name="android:drawablePadding">4dp</item>
         <item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
+        <item name="android:layout_marginEnd">8dp</item>
+        <item name="android:paddingTop">20dp</item>
+        <item name="android:paddingBottom">20dp</item>
     </style>
 
     <style name="LockPatternContainerStyle">
index 7ce84bd..a34d735 100644 (file)
@@ -32,11 +32,30 @@ import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
 
+/**
+ * This preference provides a four buttons layout with Settings style.
+ * It looks like below
+ *
+ * --------------------------------------------------
+ *  button1     | button2   | button3   | button4   |
+ * --------------------------------------------------
+ *
+ * User can set title / icon / click listener for each button.
+ *
+ * By default, four buttons are visible.
+ * However, there are two cases which button should be invisible(View.GONE).
+ *
+ * 1. User sets invisible for button. ex: ActionButtonPreference.setButton1Visible(false)
+ * 2. User doesn't set any title or icon for button.
+ *
+ */
 public class ActionButtonPreference extends Preference {
 
     private final String TAG = "ActionButtonPreference";
     private final ButtonInfo mButton1Info = new ButtonInfo();
     private final ButtonInfo mButton2Info = new ButtonInfo();
+    private final ButtonInfo mButton3Info = new ButtonInfo();
+    private final ButtonInfo mButton4Info = new ButtonInfo();
 
     public ActionButtonPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
@@ -60,7 +79,7 @@ public class ActionButtonPreference extends Preference {
     }
 
     private void init() {
-        setLayoutResource(R.layout.two_action_buttons);
+        setLayoutResource(R.layout.settings_action_buttons);
         setSelectable(false);
     }
 
@@ -72,9 +91,21 @@ public class ActionButtonPreference extends Preference {
 
         mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
         mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
+        mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
+        mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
 
         mButton1Info.setUpButton();
         mButton2Info.setUpButton();
+        mButton3Info.setUpButton();
+        mButton4Info.setUpButton();
+    }
+
+    public ActionButtonPreference setButton1Visible(boolean isVisible) {
+        if (isVisible != mButton1Info.mIsVisible) {
+            mButton1Info.mIsVisible = isVisible;
+            notifyChanged();
+        }
+        return this;
     }
 
     public ActionButtonPreference setButton1Text(@StringRes int textResId) {
@@ -110,6 +141,22 @@ public class ActionButtonPreference extends Preference {
         return this;
     }
 
+    public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
+        if (listener != mButton1Info.mListener) {
+            mButton1Info.mListener = listener;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton2Visible(boolean isVisible) {
+        if (isVisible != mButton2Info.mIsVisible) {
+            mButton2Info.mIsVisible = isVisible;
+            notifyChanged();
+        }
+        return this;
+    }
+
     public ActionButtonPreference setButton2Text(@StringRes int textResId) {
         final String newText = getContext().getString(textResId);
         if (!TextUtils.equals(newText, mButton2Info.mText)) {
@@ -143,33 +190,107 @@ public class ActionButtonPreference extends Preference {
         return this;
     }
 
-    public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton1Info.mListener) {
-            mButton1Info.mListener = listener;
+    public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
+        if (listener != mButton2Info.mListener) {
+            mButton2Info.mListener = listener;
             notifyChanged();
         }
         return this;
     }
 
-    public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
-        if (listener != mButton2Info.mListener) {
-            mButton2Info.mListener = listener;
+    public ActionButtonPreference setButton3Visible(boolean isVisible) {
+        if (isVisible != mButton3Info.mIsVisible) {
+            mButton3Info.mIsVisible = isVisible;
             notifyChanged();
         }
         return this;
     }
 
-    public ActionButtonPreference setButton1Visible(boolean isVisible) {
-        if (isVisible != mButton1Info.mIsVisible) {
-            mButton1Info.mIsVisible = isVisible;
+    public ActionButtonPreference setButton3Text(@StringRes int textResId) {
+        final String newText = getContext().getString(textResId);
+        if (!TextUtils.equals(newText, mButton3Info.mText)) {
+            mButton3Info.mText = newText;
             notifyChanged();
         }
         return this;
     }
 
-    public ActionButtonPreference setButton2Visible(boolean isVisible) {
-        if (isVisible != mButton2Info.mIsVisible) {
-            mButton2Info.mIsVisible = isVisible;
+    public ActionButtonPreference setButton3Icon(@DrawableRes int iconResId) {
+        if (iconResId == 0) {
+            return this;
+        }
+
+        final Drawable icon;
+        try {
+            icon = getContext().getDrawable(iconResId);
+            mButton3Info.mIcon = icon;
+            notifyChanged();
+        } catch (Resources.NotFoundException exception) {
+            Log.e(TAG, "Resource does not exist: " + iconResId);
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton3Enabled(boolean isEnabled) {
+        if (isEnabled != mButton3Info.mIsEnabled) {
+            mButton3Info.mIsEnabled = isEnabled;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton3OnClickListener(View.OnClickListener listener) {
+        if (listener != mButton3Info.mListener) {
+            mButton3Info.mListener = listener;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton4Visible(boolean isVisible) {
+        if (isVisible != mButton4Info.mIsVisible) {
+            mButton4Info.mIsVisible = isVisible;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton4Text(@StringRes int textResId) {
+        final String newText = getContext().getString(textResId);
+        if (!TextUtils.equals(newText, mButton4Info.mText)) {
+            mButton4Info.mText = newText;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton4Icon(@DrawableRes int iconResId) {
+        if (iconResId == 0) {
+            return this;
+        }
+
+        final Drawable icon;
+        try {
+            icon = getContext().getDrawable(iconResId);
+            mButton4Info.mIcon = icon;
+            notifyChanged();
+        } catch (Resources.NotFoundException exception) {
+            Log.e(TAG, "Resource does not exist: " + iconResId);
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton4Enabled(boolean isEnabled) {
+        if (isEnabled != mButton4Info.mIsEnabled) {
+            mButton4Info.mIsEnabled = isEnabled;
+            notifyChanged();
+        }
+        return this;
+    }
+
+    public ActionButtonPreference setButton4OnClickListener(View.OnClickListener listener) {
+        if (listener != mButton4Info.mListener) {
+            mButton4Info.mListener = listener;
             notifyChanged();
         }
         return this;
@@ -189,11 +310,24 @@ public class ActionButtonPreference extends Preference {
             mButton.setEnabled(mIsEnabled);
             mButton.setCompoundDrawablesWithIntrinsicBounds(
                     null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
-            if (mIsVisible) {
+
+            if (shouldBeVisible()) {
                 mButton.setVisibility(View.VISIBLE);
             } else {
                 mButton.setVisibility(View.GONE);
             }
         }
+
+        /**
+         * By default, four buttons are visible.
+         * However, there are two cases which button should be invisible.
+         *
+         * 1. User set invisible for this button. ex: mIsVisible = false.
+         * 2. User didn't set any title or icon.
+         *
+         */
+        private boolean shouldBeVisible() {
+            return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null);
+        }
     }
 }
\ No newline at end of file
index 6c555dd..094ec80 100644 (file)
@@ -55,7 +55,8 @@ public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsContr
     public void setUp() {
         super.setUp();
         final View buttons = View.inflate(
-                RuntimeEnvironment.application, R.layout.two_action_buttons, null /* parent */);
+                RuntimeEnvironment.application, R.layout.settings_action_buttons,
+                null /* parent */);
         mConnectButton = buttons.findViewById(R.id.button2);
         mForgetButton = buttons.findViewById(R.id.button1);
         mController =
index 2a15127..34a9872 100644 (file)
@@ -50,52 +50,175 @@ public class ActionButtonPreferenceTest {
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
-        mRootView = View.inflate(mContext, R.layout.two_action_buttons, null /* parent */);
+        mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
         mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
         mPref = new ActionButtonPreference(mContext);
     }
 
     @Test
-    public void setVisibility_shouldUpdateButtonVisibility() {
-        mPref.setButton1Visible(false).setButton2Visible(false);
+    public void onBindViewHolder_setTitle_shouldShowButtonByDefault() {
+        mPref.setButton1Text(R.string.settings_label);
+        mPref.setButton2Text(R.string.settings_label);
+        mPref.setButton3Text(R.string.settings_label);
+        mPref.setButton4Text(R.string.settings_label);
+
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void onBindViewHolder_setIcon_shouldShowButtonByDefault() {
+        mPref.setButton1Icon(R.drawable.ic_settings);
+        mPref.setButton2Icon(R.drawable.ic_settings);
+        mPref.setButton3Icon(R.drawable.ic_settings);
+        mPref.setButton4Icon(R.drawable.ic_settings);
+
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void onBindViewHolder_notSetTitleOrIcon_shouldNotShowButtonByDefault() {
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_setVisibleIsGoneAndSetTitle_shouldNotShowButton() {
+        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
+        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
+        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
+        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
+
         mPref.onBindViewHolder(mHolder);
 
         assertThat(mRootView.findViewById(R.id.button1).getVisibility())
                 .isEqualTo(View.GONE);
         assertThat(mRootView.findViewById(R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_setVisibleIsGoneAndSetIcon_shouldNotShowButton() {
+        mPref.setButton1Icon(R.drawable.ic_settings).setButton1Visible(false);
+        mPref.setButton2Icon(R.drawable.ic_settings).setButton2Visible(false);
+        mPref.setButton3Icon(R.drawable.ic_settings).setButton3Visible(false);
+        mPref.setButton4Icon(R.drawable.ic_settings).setButton4Visible(false);
+
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_setVisibility_shouldUpdateButtonVisibility() {
+        mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
+        mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
+        mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
+        mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
+
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.GONE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.GONE);
+
+        mPref.setButton1Visible(true);
+        mPref.setButton2Visible(true);
+        mPref.setButton3Visible(true);
+        mPref.setButton4Visible(true);
 
-        mPref.setButton1Visible(true).setButton2Visible(true);
         mPref.onBindViewHolder(mHolder);
 
         assertThat(mRootView.findViewById(R.id.button1).getVisibility())
                 .isEqualTo(View.VISIBLE);
         assertThat(mRootView.findViewById(R.id.button2).getVisibility())
                 .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+                .isEqualTo(View.VISIBLE);
+        assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+                .isEqualTo(View.VISIBLE);
     }
 
     @Test
-    public void setEnabled_shouldEnableButton() {
-        mPref.setButton1Enabled(true).setButton2Enabled(false);
+    public void onBindViewHolder_setEnabled_shouldEnableButton() {
+        mPref.setButton1Enabled(true);
+        mPref.setButton2Enabled(false);
+        mPref.setButton3Enabled(true);
+        mPref.setButton4Enabled(false);
+
         mPref.onBindViewHolder(mHolder);
 
         assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
         assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
+        assertThat(mRootView.findViewById(R.id.button3).isEnabled()).isTrue();
+        assertThat(mRootView.findViewById(R.id.button4).isEnabled()).isFalse();
     }
 
     @Test
-    public void setText_shouldShowSameText() {
+    public void onBindViewHolder_setText_shouldShowSameText() {
         mPref.setButton1Text(R.string.settings_label);
+        mPref.setButton2Text(R.string.settings_label);
+        mPref.setButton3Text(R.string.settings_label);
+        mPref.setButton4Text(R.string.settings_label);
+
         mPref.onBindViewHolder(mHolder);
 
         assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
                 .isEqualTo(mContext.getText(R.string.settings_label));
+        assertThat(((Button) mRootView.findViewById(R.id.button2)).getText())
+                .isEqualTo(mContext.getText(R.string.settings_label));
+        assertThat(((Button) mRootView.findViewById(R.id.button3)).getText())
+                .isEqualTo(mContext.getText(R.string.settings_label));
+        assertThat(((Button) mRootView.findViewById(R.id.button4)).getText())
+                .isEqualTo(mContext.getText(R.string.settings_label));
     }
 
     @Test
-    public void setButtonIcon_iconMustDisplayAboveText() {
+    public void onBindViewHolder_setButtonIcon_iconMustDisplayAboveText() {
         mPref.setButton1Text(R.string.settings_label);
         mPref.setButton1Icon(R.drawable.ic_settings);
+
         mPref.onBindViewHolder(mHolder);
         final Drawable[] drawablesAroundText =
                 ((Button) mRootView.findViewById(R.id.button1))
@@ -108,6 +231,7 @@ public class ActionButtonPreferenceTest {
     public void setButtonIcon_iconResourceIdIsZero_shouldNotDisplayIcon() {
         mPref.setButton1Text(R.string.settings_label);
         mPref.setButton1Icon(0);
+
         mPref.onBindViewHolder(mHolder);
         final Drawable[] drawablesAroundText =
                 ((Button) mRootView.findViewById(R.id.button1))
@@ -142,6 +266,18 @@ public class ActionButtonPreferenceTest {
         when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
         when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
         when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton3Text(anyInt())).thenReturn(pref);
+        when(pref.setButton3Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+        when(pref.setButton4Text(anyInt())).thenReturn(pref);
+        when(pref.setButton4Icon(anyInt())).thenReturn(pref);
+        when(pref.setButton4Enabled(anyBoolean())).thenReturn(pref);
+        when(pref.setButton4Visible(anyBoolean())).thenReturn(pref);
+        when(pref.setButton4OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
         return pref;
     }
 }
\ No newline at end of file