Files
lawnchair/src/com/android/launcher3/settings/SettingsActivity.java
Brian Isganitis 890d8d5a91 Give each preference screen its own activity and toolbar title
This change is in preparation for each preference screen having its own collapsible toolbar with its specific title.

Test: Subsettings open with activity transition and title changes
Bug: 187732263
Change-Id: Iac44d688539195ddb6c2aca0a96d737ce7727071
2021-05-27 16:08:22 -04:00

304 lines
12 KiB
Java

/*
* Copyright (C) 2015 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.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
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;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback;
import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartScreenCallback;
import androidx.preference.PreferenceGroup.PreferencePositionCallback;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
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
*/
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";
private static final String NOTIFICATION_DOTS_PREFERENCE_KEY = "pref_icon_badging";
public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
public static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
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) {
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(),
getPreferenceFragment());
f.setArguments(args);
// Display the fragment as the main content.
fm.beginTransaction().replace(android.R.id.content, f).commit();
}
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 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 preferences in that case.
return false;
}
final FragmentManager fm = getSupportFragmentManager();
final Fragment f = fm.getFragmentFactory().instantiate(getClassLoader(), fragment);
if (f instanceof DialogFragment) {
f.setArguments(args);
((DialogFragment) f).show(fm, key);
} else {
startActivity(new Intent(this, SettingsActivity.class)
.putExtra(EXTRA_FRAGMENT, fragment)
.putExtra(EXTRA_FRAGMENT_ARGS, args));
}
return true;
}
@Override
public boolean onPreferenceStartFragment(
PreferenceFragmentCompat preferenceFragment, Preference pref) {
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 startPreference(getString(R.string.settings_fragment_name), args, pref.getKey());
}
/**
* This fragment shows the launcher preferences.
*/
public static class LauncherSettingsFragment extends PreferenceFragmentCompat {
private String mHighLightKey;
private boolean mPreferenceHighlighted = false;
private Preference mDeveloperOptionPref;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
final Bundle args = getArguments();
mHighLightKey = args == null ? null : args.getString(EXTRA_FRAGMENT_ARG_KEY);
if (rootKey == null && !TextUtils.isEmpty(mHighLightKey)) {
rootKey = getParentKeyForPref(mHighLightKey);
}
if (savedInstanceState != null) {
mPreferenceHighlighted = savedInstanceState.getBoolean(SAVE_HIGHLIGHTED_KEY);
}
getPreferenceManager().setSharedPreferencesName(LauncherFiles.SHARED_PREFERENCES_KEY);
setPreferencesFromResource(R.xml.launcher_preferences, rootKey);
PreferenceScreen screen = getPreferenceScreen();
for (int i = screen.getPreferenceCount() - 1; i >= 0; i--) {
Preference preference = screen.getPreference(i);
if (!initPreference(preference)) {
screen.removePreference(preference);
}
}
if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
getActivity().setTitle(getPreferenceScreen().getTitle());
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mPreferenceHighlighted);
}
protected String getParentKeyForPref(String key) {
return null;
}
/**
* Initializes a preference. This is called for every preference. Returning false here
* will remove that preference from the list.
*/
protected boolean initPreference(Preference preference) {
switch (preference.getKey()) {
case NOTIFICATION_DOTS_PREFERENCE_KEY:
return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
case ALLOW_ROTATION_PREFERENCE_KEY:
DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.get(
getContext()).getDeviceProfile(getContext());
if (deviceProfile.allowRotation) {
// Launcher supports rotation by default. No need to show this setting.
return false;
}
// Initialize the UI once
preference.setDefaultValue(false);
return true;
case FLAGS_PREFERENCE_KEY:
// Only show flag toggler UI if this build variant implements that.
return FeatureFlags.showFlagTogglerUi(getContext());
case DEVELOPER_OPTIONS_KEY:
mDeveloperOptionPref = preference;
return updateDeveloperOption();
}
return true;
}
/**
* Show if plugins are enabled or flag UI is enabled.
* @return True if we should show the preference option.
*/
private boolean updateDeveloperOption() {
boolean showPreference = FeatureFlags.showFlagTogglerUi(getContext())
|| PluginManagerWrapper.hasPlugins(getContext());
if (mDeveloperOptionPref != null) {
mDeveloperOptionPref.setEnabled(showPreference);
if (showPreference) {
getPreferenceScreen().addPreference(mDeveloperOptionPref);
} else {
getPreferenceScreen().removePreference(mDeveloperOptionPref);
}
}
return showPreference;
}
@Override
public void onResume() {
super.onResume();
updateDeveloperOption();
if (isAdded() && !mPreferenceHighlighted) {
PreferenceHighlighter highlighter = createHighlighter();
if (highlighter != null) {
getView().postDelayed(highlighter, DELAY_HIGHLIGHT_DURATION_MILLIS);
mPreferenceHighlighted = true;
} else {
requestAccessibilityFocus(getListView());
}
}
}
private PreferenceHighlighter createHighlighter() {
if (TextUtils.isEmpty(mHighLightKey)) {
return null;
}
PreferenceScreen screen = getPreferenceScreen();
if (screen == null) {
return null;
}
RecyclerView list = getListView();
PreferencePositionCallback callback = (PreferencePositionCallback) list.getAdapter();
int position = callback.getPreferenceAdapterPosition(mHighLightKey);
return position >= 0 ? new PreferenceHighlighter(
list, position, screen.findPreference(mHighLightKey))
: null;
}
private void requestAccessibilityFocus(@NonNull final RecyclerView rv) {
rv.post(() -> {
if (!rv.hasFocus() && rv.getChildCount() > 0) {
rv.getChildAt(0)
.performAccessibilityAction(ACTION_ACCESSIBILITY_FOCUS, null);
}
});
}
}
}