Merge "Give each preference screen its own activity and toolbar title" into sc-dev
This commit is contained in:
commit
8d6ca68786
|
@ -45,9 +45,14 @@ android_robolectric_test {
|
|||
java_resources: [":launcher3-robolectric-resources"],
|
||||
static_libs: [
|
||||
"truth-prebuilt",
|
||||
"androidx.test.espresso.contrib",
|
||||
"androidx.test.espresso.core",
|
||||
"androidx.test.espresso.intents",
|
||||
"androidx.test.ext.junit",
|
||||
"androidx.test.runner",
|
||||
"androidx.test.rules",
|
||||
"mockito-robolectric-prebuilt",
|
||||
"SystemUISharedLib",
|
||||
],
|
||||
robolectric_prebuilt_version: "4.5.1",
|
||||
instrumentation_for: "Launcher3",
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2021 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.launcher3.settings;
|
||||
|
||||
import static androidx.preference.PreferenceFragmentCompat.ARG_PREFERENCE_ROOT;
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem;
|
||||
import static androidx.test.espresso.intent.Intents.intended;
|
||||
import static androidx.test.espresso.intent.matcher.BundleMatchers.hasEntry;
|
||||
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT;
|
||||
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARGS;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.espresso.intent.Intents;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.systemui.shared.plugins.PluginPrefs;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SettingsActivityTest {
|
||||
|
||||
private Context mApplicationContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
Intents.init();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Intents.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettings_aboutTap_launchesActivity() {
|
||||
ActivityScenario.launch(SettingsActivity.class);
|
||||
onView(withId(R.id.recycler_view)).perform(
|
||||
actionOnItem(hasDescendant(withText("About")), click()));
|
||||
|
||||
intended(allOf(
|
||||
hasComponent(SettingsActivity.class.getName()),
|
||||
hasExtra(
|
||||
equalTo(EXTRA_FRAGMENT_ARGS),
|
||||
hasEntry(ARG_PREFERENCE_ROOT, "about_screen"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettings_developerOptionsTap_launchesActivityWithFragment() {
|
||||
PluginPrefs.setHasPlugins(mApplicationContext);
|
||||
ActivityScenario.launch(SettingsActivity.class);
|
||||
onView(withId(R.id.recycler_view)).perform(
|
||||
actionOnItem(hasDescendant(withText("Developer Options")), click()));
|
||||
|
||||
intended(allOf(
|
||||
hasComponent(SettingsActivity.class.getName()),
|
||||
hasExtra(EXTRA_FRAGMENT, DeveloperOptionsFragment.class.getName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettings_aboutScreenIntent() {
|
||||
Bundle fragmentArgs = new Bundle();
|
||||
fragmentArgs.putString(ARG_PREFERENCE_ROOT, "about_screen");
|
||||
|
||||
Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
|
||||
.putExtra(EXTRA_FRAGMENT_ARGS, fragmentArgs);
|
||||
ActivityScenario.launch(intent);
|
||||
|
||||
onView(withText("About")).check(matches(isDisplayed()));
|
||||
onView(withText("Version")).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettings_developerOptionsFragmentIntent() {
|
||||
Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
|
||||
.putExtra(EXTRA_FRAGMENT, DeveloperOptionsFragment.class.getName());
|
||||
ActivityScenario.launch(intent);
|
||||
|
||||
onView(withText("Developer Options")).check(matches(isDisplayed()));
|
||||
onView(withId(R.id.filter_box)).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettings_intentWithUnknownFragment() {
|
||||
String fragmentClass = PreferenceFragmentCompat.class.getName();
|
||||
Intent intent = new Intent(mApplicationContext, SettingsActivity.class)
|
||||
.putExtra(EXTRA_FRAGMENT, fragmentClass);
|
||||
|
||||
try {
|
||||
ActivityScenario.launch(intent);
|
||||
Assert.fail("Should have thrown an IllegalArgumentException.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage()).contains(fragmentClass);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,10 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
|
|||
initFlags();
|
||||
loadPluginPrefs();
|
||||
maybeAddSandboxCategory();
|
||||
|
||||
if (getActivity() != null) {
|
||||
getActivity().setTitle("Developer Options");
|
||||
}
|
||||
}
|
||||
|
||||
private void filterPreferences(String query, PreferenceGroup pg) {
|
||||
|
|
|
@ -20,11 +20,13 @@ import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTIO
|
|||
|
||||
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
@ -46,6 +48,9 @@ import com.android.launcher3.config.FeatureFlags;
|
|||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Settings activity for Launcher. Currently implements the following setting: Allow rotation
|
||||
*/
|
||||
|
@ -53,6 +58,10 @@ public class SettingsActivity extends FragmentActivity
|
|||
implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback,
|
||||
SharedPreferences.OnSharedPreferenceChangeListener{
|
||||
|
||||
/** List of fragments that can be hosted by this activity. */
|
||||
private static final List<String> VALID_PREFERENCE_FRAGMENTS = Collections.singletonList(
|
||||
DeveloperOptionsFragment.class.getName());
|
||||
|
||||
private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
|
||||
private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
|
||||
|
||||
|
@ -63,20 +72,30 @@ public class SettingsActivity extends FragmentActivity
|
|||
private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
|
||||
public static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String EXTRA_FRAGMENT = ":settings:fragment";
|
||||
@VisibleForTesting
|
||||
static final String EXTRA_FRAGMENT_ARGS = ":settings:fragment_args";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Bundle args = new Bundle();
|
||||
String prefKey = getIntent().getStringExtra(EXTRA_FRAGMENT_ARG_KEY);
|
||||
Intent intent = getIntent();
|
||||
Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
|
||||
if (args == null) {
|
||||
args = new Bundle();
|
||||
}
|
||||
|
||||
String prefKey = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY);
|
||||
if (!TextUtils.isEmpty(prefKey)) {
|
||||
args.putString(EXTRA_FRAGMENT_ARG_KEY, prefKey);
|
||||
}
|
||||
|
||||
final FragmentManager fm = getSupportFragmentManager();
|
||||
final Fragment f = fm.getFragmentFactory().instantiate(getClassLoader(),
|
||||
getString(R.string.settings_fragment_name));
|
||||
getPreferenceFragment());
|
||||
f.setArguments(args);
|
||||
// Display the fragment as the main content.
|
||||
fm.beginTransaction().replace(android.R.id.content, f).commit();
|
||||
|
@ -84,22 +103,45 @@ public class SettingsActivity extends FragmentActivity
|
|||
Utilities.getPrefs(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the preference fragment to instantiate in this activity.
|
||||
*
|
||||
* @return the preference fragment class
|
||||
* @throws IllegalArgumentException if the fragment is unknown to this activity
|
||||
*/
|
||||
private String getPreferenceFragment() {
|
||||
String preferenceFragment = getIntent().getStringExtra(EXTRA_FRAGMENT);
|
||||
String defaultFragment = getString(R.string.settings_fragment_name);
|
||||
|
||||
if (TextUtils.isEmpty(preferenceFragment)) {
|
||||
return defaultFragment;
|
||||
} else if (!preferenceFragment.equals(defaultFragment)
|
||||
&& !VALID_PREFERENCE_FRAGMENTS.contains(preferenceFragment)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid fragment for this activity: " + preferenceFragment);
|
||||
} else {
|
||||
return preferenceFragment;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { }
|
||||
|
||||
private boolean startFragment(String fragment, Bundle args, String key) {
|
||||
private boolean startPreference(String fragment, Bundle args, String key) {
|
||||
if (Utilities.ATLEAST_P && getSupportFragmentManager().isStateSaved()) {
|
||||
// Sometimes onClick can come after onPause because of being posted on the handler.
|
||||
// Skip starting new fragments in that case.
|
||||
// Skip starting new preferences in that case.
|
||||
return false;
|
||||
}
|
||||
final FragmentManager fm = getSupportFragmentManager();
|
||||
final Fragment f = fm.getFragmentFactory().instantiate(getClassLoader(), fragment);
|
||||
f.setArguments(args);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).show(getSupportFragmentManager(), key);
|
||||
f.setArguments(args);
|
||||
((DialogFragment) f).show(fm, key);
|
||||
} else {
|
||||
fm.beginTransaction().replace(android.R.id.content, f).addToBackStack(key).commit();
|
||||
startActivity(new Intent(this, SettingsActivity.class)
|
||||
.putExtra(EXTRA_FRAGMENT, fragment)
|
||||
.putExtra(EXTRA_FRAGMENT_ARGS, args));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -107,14 +149,14 @@ public class SettingsActivity extends FragmentActivity
|
|||
@Override
|
||||
public boolean onPreferenceStartFragment(
|
||||
PreferenceFragmentCompat preferenceFragment, Preference pref) {
|
||||
return startFragment(pref.getFragment(), pref.getExtras(), pref.getKey());
|
||||
return startPreference(pref.getFragment(), pref.getExtras(), pref.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.getKey());
|
||||
return startFragment(getString(R.string.settings_fragment_name), args, pref.getKey());
|
||||
return startPreference(getString(R.string.settings_fragment_name), args, pref.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,6 +190,10 @@ public class SettingsActivity extends FragmentActivity
|
|||
screen.removePreference(preference);
|
||||
}
|
||||
}
|
||||
|
||||
if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
|
||||
getActivity().setTitle(getPreferenceScreen().getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue