Allow appending static preferences to RadioButtonPickerFragment
This makes it so that static preferences can also be added after the candidates so they can show up on the bottom of the screen. This is done via a new xml tag for the preference screen that is usually mostly empty that RaiodButtonPickerFragments use Test: robotests Bug: 111450127 Change-Id: I0fe2f480f0ff59b9bf9269e94b33ab4b008b47b8
This commit is contained in:
@@ -72,6 +72,14 @@
|
||||
<attr name="allowDynamicSummaryInSlice" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="PreferenceScreen">
|
||||
<!-- Determines if static preferences defined in addStaticPreferences are added before or after the radio buttons -->
|
||||
<attr name="staticPreferenceLocation">
|
||||
<enum name="prepend" value="0" />
|
||||
<enum name="append" value="1" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- For DotsPageIndicator -->
|
||||
<declare-styleable name="DotsPageIndicator">
|
||||
<attr name="dotDiameter" format="dimension" />
|
||||
|
@@ -5406,6 +5406,12 @@
|
||||
<!-- Battery saver: Label for preference to turn on battery saver automatically when battery is low [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_auto_title">Turn on automatically</string>
|
||||
|
||||
<!-- Battery saver: Label for preference to indicate there is no battery saver schedule [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_auto_no_schedule">No schedule</string>
|
||||
|
||||
<!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_schedule_settings_title">Set a schedule</string>
|
||||
|
||||
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_seekbar_title">At <xliff:g id="percent">%1$s</xliff:g></string>
|
||||
|
||||
|
23
res/xml/battery_saver_schedule_settings.xml
Normal file
23
res/xml/battery_saver_schedule_settings.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/battery_saver_schedule_settings_title"
|
||||
settings:staticPreferenceLocation="append">
|
||||
</PreferenceScreen >
|
@@ -55,6 +55,8 @@ public class PreferenceXmlParserUtils {
|
||||
private static final List<String> SUPPORTED_PREF_TYPES = Arrays.asList(
|
||||
"Preference", "PreferenceCategory", "PreferenceScreen",
|
||||
"com.android.settings.widget.WorkOnlyCategory");
|
||||
public static final int PREPEND_VALUE = 0;
|
||||
public static final int APPEND_VALUE = 1;
|
||||
|
||||
/**
|
||||
* Flag definition to indicate which metadata should be extracted when
|
||||
@@ -84,6 +86,7 @@ public class PreferenceXmlParserUtils {
|
||||
int FLAG_NEED_KEYWORDS = 1 << 8;
|
||||
int FLAG_NEED_SEARCHABLE = 1 << 9;
|
||||
int FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = 1 << 10;
|
||||
int FLAG_NEED_PREF_APPEND = 1 << 11;
|
||||
}
|
||||
|
||||
public static final String METADATA_PREF_TYPE = "type";
|
||||
@@ -97,6 +100,7 @@ public class PreferenceXmlParserUtils {
|
||||
public static final String METADATA_SEARCHABLE = "searchable";
|
||||
public static final String METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE =
|
||||
"allow_dynamic_summary_in_slice";
|
||||
public static final String METADATA_APPEND = "staticPreferenceLocation";
|
||||
|
||||
private static final String ENTRIES_SEPARATOR = "|";
|
||||
|
||||
@@ -184,14 +188,13 @@ public class PreferenceXmlParserUtils {
|
||||
// Parse next until start tag is found
|
||||
}
|
||||
final int outerDepth = parser.getDepth();
|
||||
|
||||
final boolean hasPrefScreenFlag = hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN);
|
||||
do {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
final String nodeName = parser.getName();
|
||||
if (!hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN)
|
||||
&& TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
|
||||
if (!hasPrefScreenFlag && TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
|
||||
continue;
|
||||
}
|
||||
if (!SUPPORTED_PREF_TYPES.contains(nodeName) && !nodeName.endsWith("Preference")) {
|
||||
@@ -199,8 +202,14 @@ public class PreferenceXmlParserUtils {
|
||||
}
|
||||
final Bundle preferenceMetadata = new Bundle();
|
||||
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.Preference);
|
||||
TypedArray preferenceScreenAttributes = null;
|
||||
if (hasPrefScreenFlag) {
|
||||
preferenceScreenAttributes = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.PreferenceScreen);
|
||||
}
|
||||
|
||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
|
||||
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
|
||||
@@ -236,6 +245,10 @@ public class PreferenceXmlParserUtils {
|
||||
preferenceMetadata.putBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
|
||||
isDynamicSummaryAllowed(preferenceAttributes));
|
||||
}
|
||||
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_APPEND) && hasPrefScreenFlag) {
|
||||
preferenceMetadata.putBoolean(METADATA_APPEND,
|
||||
isAppended(preferenceScreenAttributes));
|
||||
}
|
||||
metadata.add(preferenceMetadata);
|
||||
|
||||
preferenceAttributes.recycle();
|
||||
@@ -325,7 +338,12 @@ public class PreferenceXmlParserUtils {
|
||||
false /* default */);
|
||||
}
|
||||
|
||||
private static String getKeywords(TypedArray styleAttributes) {
|
||||
return styleAttributes.getString(R.styleable.Preference_keywords);
|
||||
private static String getKeywords(TypedArray styledAttributes) {
|
||||
return styledAttributes.getString(R.styleable.Preference_keywords);
|
||||
}
|
||||
|
||||
private static boolean isAppended(TypedArray styledAttributes) {
|
||||
return styledAttributes.getInt(R.styleable.PreferenceScreen_staticPreferenceLocation,
|
||||
PREPEND_VALUE) == APPEND_VALUE;
|
||||
}
|
||||
}
|
||||
|
@@ -22,10 +22,12 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
@@ -34,16 +36,23 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.core.PreferenceXmlParserUtils;
|
||||
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
|
||||
import com.android.settingslib.widget.CandidateInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFragment implements
|
||||
RadioButtonPreference.OnClickListener {
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
@VisibleForTesting
|
||||
static final String EXTRA_FOR_WORK = "for_work";
|
||||
private static final String TAG = "RadioButtonPckrFrgmt";
|
||||
@VisibleForTesting
|
||||
boolean mAppendStaticPreferences = false;
|
||||
|
||||
private final Map<String, CandidateInfo> mCandidates = new ArrayMap<>();
|
||||
|
||||
@@ -69,6 +78,19 @@ public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFr
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||
try {
|
||||
// Check if the xml specifies if static preferences should go on the top or bottom
|
||||
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(getContext(),
|
||||
getPreferenceScreenResId(),
|
||||
MetadataFlag.FLAG_INCLUDE_PREF_SCREEN |
|
||||
MetadataFlag.FLAG_NEED_PREF_APPEND);
|
||||
mAppendStaticPreferences = metadata.get(0)
|
||||
.getBoolean(PreferenceXmlParserUtils.METADATA_APPEND);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error trying to open xml file", e);
|
||||
} catch (XmlPullParserException e) {
|
||||
Log.e(TAG, "Error parsing xml", e);
|
||||
}
|
||||
updateCandidates();
|
||||
}
|
||||
|
||||
@@ -142,7 +164,9 @@ public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFr
|
||||
final String systemDefaultKey = getSystemDefaultKey();
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removeAll();
|
||||
if (!mAppendStaticPreferences) {
|
||||
addStaticPreferences(screen);
|
||||
}
|
||||
|
||||
final int customLayoutResId = getRadioButtonPreferenceCustomLayoutResId();
|
||||
if (shouldShowItemNone()) {
|
||||
@@ -168,6 +192,9 @@ public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFr
|
||||
}
|
||||
}
|
||||
mayCheckOnlyRadioButton();
|
||||
if (mAppendStaticPreferences) {
|
||||
addStaticPreferences(screen);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/battery_saver_schedule_settings_title"
|
||||
settings:staticPreferenceLocation="append">
|
||||
</PreferenceScreen >
|
@@ -18,6 +18,7 @@ package com.android.settings.core;
|
||||
|
||||
import static com.android.settings.core.PreferenceXmlParserUtils
|
||||
.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
|
||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_APPEND;
|
||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
|
||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS;
|
||||
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
|
||||
@@ -315,6 +316,32 @@ public class PreferenceXmlParserUtilsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void extractMetadata_requestAppendProperty_shouldDefaultToFalse()
|
||||
throws Exception {
|
||||
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
|
||||
R.xml.display_settings,
|
||||
MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
|
||||
|
||||
for (Bundle bundle : metadata) {
|
||||
assertThat(bundle.getBoolean(METADATA_APPEND)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void extractMetadata_requestAppendProperty_shouldReturnCorrectValue()
|
||||
throws Exception {
|
||||
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
|
||||
R.xml.battery_saver_schedule_settings,
|
||||
MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
|
||||
|
||||
for (Bundle bundle : metadata) {
|
||||
assertThat(bundle.getBoolean(METADATA_APPEND)).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resId the ID for the XML preference
|
||||
* @return an XML resource parser that points to the start tag
|
||||
|
@@ -209,6 +209,7 @@ public class ColorModePreferenceFragmentTest {
|
||||
|
||||
@Test
|
||||
public void onCreatePreferences_useNewTitle_shouldAddColorModePreferences() {
|
||||
when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
|
||||
doNothing().when(mFragment).addPreferencesFromResource(anyInt());
|
||||
doNothing().when(mFragment).updateCandidates();
|
||||
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.widget;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -37,7 +38,9 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@@ -98,6 +101,26 @@ public class RadioButtonPickerFragmentTest {
|
||||
assertThat(mFragment.setDefaultKeyCalled).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticPreferencesPrepended_addedFirst() {
|
||||
mFragment.mAppendStaticPreferences = false;
|
||||
mFragment.updateCandidates();
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mFragment);
|
||||
inOrder.verify(mFragment).addStaticPreferences(any());
|
||||
inOrder.verify(mFragment).getRadioButtonPreferenceCustomLayoutResId();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticPreferencesAppended_addedLast() {
|
||||
mFragment.mAppendStaticPreferences = true;
|
||||
mFragment.updateCandidates();
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mFragment);
|
||||
inOrder.verify(mFragment).mayCheckOnlyRadioButton();
|
||||
inOrder.verify(mFragment).addStaticPreferences(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveNoCustomPreferenceLayout() {
|
||||
assertThat(mFragment.getRadioButtonPreferenceCustomLayoutResId()).isEqualTo(0);
|
||||
|
Reference in New Issue
Block a user