From e88f7ab7a7526d089289a6939fc6cf1e6aa45be5 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Mon, 14 Jan 2019 09:06:44 -0500 Subject: [PATCH] Update appearance of channel preferences Test: atest Change-Id: Ie58e7a27601ee23b1cd2caf990cc5c10006c0162 Fixes: 122671854 --- .../ChannelSummaryPreference.java | 115 ++++++++++++ .../NotificationSettingsBase.java | 3 +- .../ChannelSummaryPreferenceTest.java | 169 ++++++++++++++++++ 3 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 src/com/android/settings/notification/ChannelSummaryPreference.java create mode 100644 tests/robotests/src/com/android/settings/notification/ChannelSummaryPreferenceTest.java diff --git a/src/com/android/settings/notification/ChannelSummaryPreference.java b/src/com/android/settings/notification/ChannelSummaryPreference.java new file mode 100644 index 00000000000..c716038f60f --- /dev/null +++ b/src/com/android/settings/notification/ChannelSummaryPreference.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.widget.CheckBox; + +import com.android.settings.R; +import com.android.settingslib.TwoTargetPreference; + +import androidx.preference.PreferenceViewHolder; + +/** + * A custom preference that provides inline checkbox and tappable target. + */ +public class ChannelSummaryPreference extends TwoTargetPreference { + + private Context mContext; + private Intent mIntent; + private CheckBox mCheckBox; + private boolean mChecked; + private boolean mEnableCheckBox = true; + + public ChannelSummaryPreference(Context context) { + super(context); + setLayoutResource(R.layout.preference_checkable_two_target); + mContext = context; + setWidgetLayoutResource(R.layout.zen_rule_widget); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder view) { + super.onBindViewHolder(view); + View settingsWidget = view.findViewById(android.R.id.widget_frame); + View divider = view.findViewById(R.id.two_target_divider); + if (mIntent != null) { + divider.setVisibility(View.VISIBLE); + settingsWidget.setVisibility(View.VISIBLE); + settingsWidget.setOnClickListener(v -> mContext.startActivity(mIntent)); + } else { + divider.setVisibility(View.GONE); + settingsWidget.setVisibility(View.GONE); + settingsWidget.setOnClickListener(null); + } + + View checkboxContainer = view.findViewById(R.id.checkbox_container); + if (checkboxContainer != null) { + checkboxContainer.setOnClickListener(mOnCheckBoxClickListener); + } + mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox); + if (mCheckBox != null) { + mCheckBox.setChecked(mChecked); + mCheckBox.setEnabled(mEnableCheckBox); + } + } + + public boolean isChecked() { + return mChecked; + } + + @Override + public void setIntent(Intent intent) { + mIntent = intent; + } + + @Override + public void onClick() { + mOnCheckBoxClickListener.onClick(null); + } + + public void setChecked(boolean checked) { + mChecked = checked; + if (mCheckBox != null) { + mCheckBox.setChecked(checked); + } + } + + public void setCheckBoxEnabled(boolean enabled) { + mEnableCheckBox = enabled; + if (mCheckBox != null) { + mCheckBox.setEnabled(enabled); + } + } + + private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mCheckBox != null && !mCheckBox.isEnabled()) { + return; + } + setChecked(!mChecked); + if (!callChangeListener(mChecked)) { + setChecked(!mChecked); + } else { + persistBoolean(mChecked); + } + } + }; +} diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java index ed0b1235ef4..7053bb341e2 100644 --- a/src/com/android/settings/notification/NotificationSettingsBase.java +++ b/src/com/android/settings/notification/NotificationSettingsBase.java @@ -273,8 +273,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment { protected Preference populateSingleChannelPrefs(PreferenceGroup parent, final NotificationChannel channel, final boolean groupBlocked) { - MasterCheckBoxPreference channelPref = new MasterCheckBoxPreference( - getPrefContext()); + ChannelSummaryPreference channelPref = new ChannelSummaryPreference(getPrefContext()); channelPref.setCheckBoxEnabled(mSuspendedAppsAdmin == null && isChannelBlockable(channel) && isChannelConfigurable(channel) diff --git a/tests/robotests/src/com/android/settings/notification/ChannelSummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/ChannelSummaryPreferenceTest.java new file mode 100644 index 00000000000..408b2b66f25 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/ChannelSummaryPreferenceTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; +import android.widget.LinearLayout; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +@RunWith(RobolectricTestRunner.class) +public class ChannelSummaryPreferenceTest { + + private Context mContext; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + } + + @Test + public void createNewPreference_shouldSetLayout() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + assertThat(preference.getLayoutResource()).isEqualTo( + R.layout.preference_checkable_two_target); + assertThat(preference.getWidgetLayoutResource()).isEqualTo( + R.layout.zen_rule_widget); + } + + @Test + public void setChecked_shouldUpdateButtonCheckedState() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final LayoutInflater inflater = LayoutInflater.from(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + inflater.inflate(R.layout.preference_checkable_two_target, null)); + final LinearLayout widgetView = holder.itemView.findViewById(R.id.checkbox_container); + inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true); + final CheckBox toggle = (CheckBox) holder.findViewById(com.android.internal.R.id.checkbox); + preference.onBindViewHolder(holder); + + preference.setChecked(true); + assertThat(toggle.isChecked()).isTrue(); + + preference.setChecked(false); + assertThat(toggle.isChecked()).isFalse(); + } + + @Test + public void setCheckboxEnabled_shouldUpdateButtonEnabledState() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final LayoutInflater inflater = LayoutInflater.from(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + inflater.inflate(R.layout.preference_checkable_two_target, null)); + final LinearLayout widgetView = holder.itemView.findViewById(R.id.checkbox_container); + inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true); + final CheckBox toggle = (CheckBox) holder.findViewById(com.android.internal.R.id.checkbox); + preference.onBindViewHolder(holder); + + preference.setCheckBoxEnabled(true); + assertThat(toggle.isEnabled()).isTrue(); + + preference.setCheckBoxEnabled(false); + assertThat(toggle.isEnabled()).isFalse(); + } + + @Test + public void setCheckBoxEnabled_shouldUpdateButtonEnabledState_beforeViewBound() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final LayoutInflater inflater = LayoutInflater.from(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + inflater.inflate(R.layout.preference_checkable_two_target, null)); + final LinearLayout widgetView = holder.itemView.findViewById(R.id.checkbox_container); + inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true); + final CheckBox toggle = (CheckBox) holder.findViewById(com.android.internal.R.id.checkbox); + + preference.setCheckBoxEnabled(false); + preference.onBindViewHolder(holder); + assertThat(toggle.isEnabled()).isFalse(); + } + + @Test + public void clickWidgetView_shouldToggleButton() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final LayoutInflater inflater = LayoutInflater.from(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + inflater.inflate(R.layout.preference_checkable_two_target, null)); + final LinearLayout widgetView = holder.itemView.findViewById(R.id.checkbox_container); + assertThat(widgetView).isNotNull(); + + inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true); + final CheckBox toggle = (CheckBox) holder.findViewById(com.android.internal.R.id.checkbox); + preference.onBindViewHolder(holder); + + widgetView.performClick(); + assertThat(toggle.isChecked()).isTrue(); + + widgetView.performClick(); + assertThat(toggle.isChecked()).isFalse(); + } + + @Test + public void clickWidgetView_shouldNotToggleButtonIfDisabled() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final LayoutInflater inflater = LayoutInflater.from(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + inflater.inflate(R.layout.preference_checkable_two_target, null)); + final LinearLayout widgetView = holder.itemView.findViewById(R.id.checkbox_container); + assertThat(widgetView).isNotNull(); + + inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true); + final CheckBox toggle = (CheckBox) holder.findViewById(com.android.internal.R.id.checkbox); + preference.onBindViewHolder(holder); + toggle.setEnabled(false); + + widgetView.performClick(); + assertThat(toggle.isChecked()).isFalse(); + } + + @Test + public void clickWidgetView_shouldNotifyPreferenceChanged() { + final ChannelSummaryPreference preference = new ChannelSummaryPreference(mContext); + final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests( + LayoutInflater.from(mContext).inflate( + R.layout.preference_checkable_two_target, null)); + final View widgetView = holder.findViewById(R.id.checkbox_container); + final Preference.OnPreferenceChangeListener + listener = mock(Preference.OnPreferenceChangeListener.class); + preference.setOnPreferenceChangeListener(listener); + preference.onBindViewHolder(holder); + + preference.setChecked(false); + widgetView.performClick(); + verify(listener).onPreferenceChange(preference, true); + + preference.setChecked(true); + widgetView.performClick(); + verify(listener).onPreferenceChange(preference, false); + } +}