diff options
-rw-r--r-- | packages/SettingsLib/Android.bp | 1 | ||||
-rw-r--r-- | packages/SettingsLib/AppPreference/Android.bp | 3 | ||||
-rw-r--r-- | packages/SettingsLib/EntityHeaderWidgets/Android.bp | 2 | ||||
-rw-r--r-- | packages/SettingsLib/RadioButtonPreference/Android.bp | 14 | ||||
-rw-r--r-- | packages/SettingsLib/RadioButtonPreference/AndroidManifest.xml | 23 | ||||
-rw-r--r-- | packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml | 107 | ||||
-rw-r--r-- | packages/SettingsLib/RadioButtonPreference/res/layout/preference_widget_radiobutton.xml | 25 | ||||
-rw-r--r-- | packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java | 161 | ||||
-rw-r--r-- | packages/SettingsLib/SettingsTheme/Android.bp | 8 | ||||
-rw-r--r-- | packages/SettingsLib/SettingsTheme/AndroidManifest.xml | 23 | ||||
-rw-r--r-- | packages/SettingsLib/SettingsTheme/res/values/dimens.xml (renamed from packages/SettingsLib/AppPreference/res/values/dimens.xml) | 4 | ||||
-rw-r--r-- | packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/RadioButtonPreferenceTest.java | 103 |
12 files changed, 470 insertions, 4 deletions
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index b532621cd617..7760e0ef7246 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -23,6 +23,7 @@ android_library { "SettingsLibBarChartPreference", "SettingsLibProgressBar", "SettingsLibAdaptiveIcon", + "SettingsLibRadioButtonPreference", ], // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES diff --git a/packages/SettingsLib/AppPreference/Android.bp b/packages/SettingsLib/AppPreference/Android.bp index b56181d75e6a..b07176a064f9 100644 --- a/packages/SettingsLib/AppPreference/Android.bp +++ b/packages/SettingsLib/AppPreference/Android.bp @@ -4,9 +4,10 @@ android_library { srcs: ["src/**/*.java"], resource_dirs: ["res"], - libs: [ + static_libs: [ "androidx.annotation_annotation", "androidx.preference_preference", + "SettingsLibSettingsTheme", ], sdk_version: "system_current", min_sdk_version: "21", diff --git a/packages/SettingsLib/EntityHeaderWidgets/Android.bp b/packages/SettingsLib/EntityHeaderWidgets/Android.bp index 3ca4ecd33ce4..280848a0d7c4 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/Android.bp +++ b/packages/SettingsLib/EntityHeaderWidgets/Android.bp @@ -6,7 +6,7 @@ android_library { static_libs: [ "androidx.annotation_annotation", - "SettingsLibAppPreference" + "SettingsLibSettingsTheme" ], sdk_version: "system_current", diff --git a/packages/SettingsLib/RadioButtonPreference/Android.bp b/packages/SettingsLib/RadioButtonPreference/Android.bp new file mode 100644 index 000000000000..136d6daad99a --- /dev/null +++ b/packages/SettingsLib/RadioButtonPreference/Android.bp @@ -0,0 +1,14 @@ +android_library { + name: "SettingsLibRadioButtonPreference", + + srcs: ["src/**/*.java"], + resource_dirs: ["res"], + + static_libs: [ + "androidx.preference_preference", + "SettingsLibSettingsTheme", + ], + + sdk_version: "system_current", + min_sdk_version: "21", +} diff --git a/packages/SettingsLib/RadioButtonPreference/AndroidManifest.xml b/packages/SettingsLib/RadioButtonPreference/AndroidManifest.xml new file mode 100644 index 000000000000..fda7fde29404 --- /dev/null +++ b/packages/SettingsLib/RadioButtonPreference/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.settingslib.widget"> + + <uses-sdk android:minSdkVersion="21" /> + +</manifest> diff --git a/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml new file mode 100644 index 000000000000..dcb014d6ed57 --- /dev/null +++ b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_radio.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?android:attr/selectableItemBackground" + android:gravity="center_vertical" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + <LinearLayout + android:id="@android:id/widget_frame" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center" + android:minWidth="56dp" + android:layout_marginEnd="16dp" + android:orientation="vertical"/> + + <LinearLayout + android:id="@+id/icon_frame" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:minWidth="32dp" + android:orientation="horizontal" + android:layout_marginEnd="16dp" + android:paddingTop="4dp" + android:paddingBottom="4dp"> + <androidx.preference.internal.PreferenceImageView + android:id="@android:id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + settings:maxWidth="@dimen/secondary_app_icon_size" + settings:maxHeight="@dimen/secondary_app_icon_size"/> + </LinearLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:orientation="vertical" + android:paddingTop="16dp" + android:paddingBottom="16dp"> + + <TextView + android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" + android:ellipsize="marquee" + android:fadingEdge="horizontal"/> + + <LinearLayout + android:id="@+id/summary_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone"> + <TextView + android:id="@android:id/summary" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small" + android:textAlignment="viewStart" + android:textColor="?android:attr/textColorSecondary"/> + + <TextView + android:id="@+id/appendix" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small" + android:textAlignment="viewEnd" + android:textColor="?android:attr/textColorSecondary" + android:maxLines="1" + android:ellipsize="end"/> + </LinearLayout> + <ProgressBar + android:id="@android:id/progress" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="4dp" + android:max="100" + android:visibility="gone"/> + </LinearLayout> + +</LinearLayout> diff --git a/packages/SettingsLib/RadioButtonPreference/res/layout/preference_widget_radiobutton.xml b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_widget_radiobutton.xml new file mode 100644 index 000000000000..cb7b8eb289ea --- /dev/null +++ b/packages/SettingsLib/RadioButtonPreference/res/layout/preference_widget_radiobutton.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<RadioButton xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:background="@null" + android:focusable="false" + android:clickable="false" /> diff --git a/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java b/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java new file mode 100644 index 000000000000..08287ac628d5 --- /dev/null +++ b/packages/SettingsLib/RadioButtonPreference/src/com/android/settingslib/widget/RadioButtonPreference.java @@ -0,0 +1,161 @@ +/* + * 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.settingslib.widget; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.core.content.res.TypedArrayUtils; +import androidx.preference.CheckBoxPreference; +import androidx.preference.PreferenceViewHolder; + +/** + * Check box preference with check box replaced by radio button. + * + * Functionally speaking, it's actually a CheckBoxPreference. We only modified + * the widget to RadioButton to make it "look like" a RadioButtonPreference. + * + * In other words, there's no "RadioButtonPreferenceGroup" in this + * implementation. When you check one RadioButtonPreference, if you want to + * uncheck all the other preferences, you should do that by code yourself. + */ +public class RadioButtonPreference extends CheckBoxPreference { + + /** + * Interface definition for a callback to be invoked when the preference is clicked. + */ + public interface OnClickListener { + /** + * Called when a preference has been clicked. + * + * @param emiter The clicked preference + */ + void onRadioButtonClicked(RadioButtonPreference emiter); + } + + private OnClickListener mListener = null; + private View mAppendix; + private int mAppendixVisibility = -1; + + + /** + * Perform inflation from XML and apply a class-specific base style. + * + * @param context The {@link Context} this is associated with, through which it can + * access the current theme, resources, {@link SharedPreferences}, etc. + * @param attrs The attributes of the XML tag that is inflating the preference + * @param defStyleAttr An attribute in the current theme that contains a reference to a style + * resource that supplies default values for the view. Can be 0 to not + * look for defaults. + */ + public RadioButtonPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setWidgetLayoutResource(R.layout.preference_widget_radiobutton); + setLayoutResource(R.layout.preference_radio); + setIconSpaceReserved(false); + } + + + /** + * Perform inflation from XML and apply a class-specific base style. + * + * @param context The {@link Context} this is associated with, through which it can + * access the current theme, resources, {@link SharedPreferences}, etc. + * @param attrs The attributes of the XML tag that is inflating the preference + */ + public RadioButtonPreference(Context context, AttributeSet attrs) { + this(context, attrs, TypedArrayUtils.getAttr(context, + androidx.preference.R.attr.preferenceStyle, + android.R.attr.preferenceStyle)); + } + + /** + * Constructor to create a preference. + * + * @param context The Context this is associated with. + */ + public RadioButtonPreference(Context context) { + this(context, null); + } + + /** + * Sets the callback to be invoked when this preference is clicked by the user. + * + * @param listener The callback to be invoked + */ + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + + /** + * Processes a click on the preference. + */ + @Override + public void onClick() { + if (mListener != null) { + mListener.onRadioButtonClicked(this); + } + } + + /** + * Binds the created View to the data for this preference. + * + * <p>This is a good place to grab references to custom Views in the layout and set + * properties on them. + * + * <p>Make sure to call through to the superclass's implementation. + * + * @param holder The ViewHolder that provides references to the views to fill in. These views + * will be recycled, so you should not hold a reference to them after this method + * returns. + */ + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + View summaryContainer = holder.findViewById(R.id.summary_container); + if (summaryContainer != null) { + summaryContainer.setVisibility( + TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE); + mAppendix = holder.findViewById(R.id.appendix); + if (mAppendix != null && mAppendixVisibility != -1) { + mAppendix.setVisibility(mAppendixVisibility); + } + } + + TextView title = (TextView) holder.findViewById(android.R.id.title); + if (title != null) { + title.setSingleLine(false); + title.setMaxLines(3); + } + } + + /** + * Set the visibility state of appendix view. + * + * @param visibility One of {@link View#VISIBLE}, {@link View#INVISIBLE}, or {@link View#GONE}. + */ + public void setAppendixVisibility(int visibility) { + if (mAppendix != null) { + mAppendix.setVisibility(visibility); + } + mAppendixVisibility = visibility; + } +} diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp new file mode 100644 index 000000000000..6d505bf8895d --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/Android.bp @@ -0,0 +1,8 @@ +android_library { + name: "SettingsLibSettingsTheme", + + resource_dirs: ["res"], + + sdk_version: "system_current", + min_sdk_version: "21", +} diff --git a/packages/SettingsLib/SettingsTheme/AndroidManifest.xml b/packages/SettingsLib/SettingsTheme/AndroidManifest.xml new file mode 100644 index 000000000000..fda7fde29404 --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.settingslib.widget"> + + <uses-sdk android:minSdkVersion="21" /> + +</manifest> diff --git a/packages/SettingsLib/AppPreference/res/values/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values/dimens.xml index e2a7a191f9de..94856552d6e2 100644 --- a/packages/SettingsLib/AppPreference/res/values/dimens.xml +++ b/packages/SettingsLib/SettingsTheme/res/values/dimens.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2018 The Android Open Source Project + 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. @@ -17,4 +17,4 @@ <resources> <dimen name="secondary_app_icon_size">32dp</dimen> -</resources>
\ No newline at end of file +</resources> diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/RadioButtonPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/RadioButtonPreferenceTest.java new file mode 100644 index 000000000000..d58e68a3b387 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/RadioButtonPreferenceTest.java @@ -0,0 +1,103 @@ +/* + * 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.settingslib.widget; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.app.Application; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.preference.PreferenceViewHolder; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class RadioButtonPreferenceTest { + + private Application mContext; + private RadioButtonPreference mPreference; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mPreference = new RadioButtonPreference(mContext); + } + + @Test + public void shouldHaveRadioPreferenceLayout() { + assertThat(mPreference.getLayoutResource()).isEqualTo(R.layout.preference_radio); + } + + @Test + public void iconSpaceReservedShouldBeFalse() { + assertThat(mPreference.isIconSpaceReserved()).isFalse(); + } + + @Test + public void summary_containerShouldBeVisible() { + mPreference.setSummary("some summary"); + View summaryContainer = new View(mContext); + View view = mock(View.class); + when(view.findViewById(R.id.summary_container)).thenReturn(summaryContainer); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + mPreference.onBindViewHolder(preferenceViewHolder); + assertEquals(View.VISIBLE, summaryContainer.getVisibility()); + } + + @Test + public void emptySummary_containerShouldBeGone() { + mPreference.setSummary(""); + View summaryContainer = new View(mContext); + View view = mock(View.class); + when(view.findViewById(R.id.summary_container)).thenReturn(summaryContainer); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + mPreference.onBindViewHolder(preferenceViewHolder); + assertEquals(View.GONE, summaryContainer.getVisibility()); + } + + @Test + public void nullSummary_containerShouldBeGone() { + mPreference.setSummary(null); + View summaryContainer = new View(mContext); + View view = mock(View.class); + when(view.findViewById(R.id.summary_container)).thenReturn(summaryContainer); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + mPreference.onBindViewHolder(preferenceViewHolder); + assertEquals(View.GONE, summaryContainer.getVisibility()); + } + + @Test + public void hideAppendix_shouldBeGone() { + mPreference.setAppendixVisibility(View.GONE); + View view = LayoutInflater.from(mContext).inflate(R.layout.preference_radio, null); + PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view); + mPreference.onBindViewHolder(holder); + assertThat(holder.findViewById(R.id.appendix).getVisibility()).isEqualTo(View.GONE); + } +} |