Revise homepage highlight mechanism
- Create TopLevelHighlightMixin to handle highlight actions and simplify TopLevelSettings - Fix the error highlight and the flicker after screen rotation - Postpone creating the fragment until it's needed to accelerate the initialization and to fix the search highlight function breakage after toggling light/dark mode - Register activity embedding rules only once for injection and wallpaper - Do not highlight Tips & support since it's full screen - Refactor ActivityEmbeddingRulesController Bug: 207316936 Test: manual, robotest build pass Change-Id: If322ec180b03ee123987c70779a25c6a570d9faf
This commit is contained in:
@@ -23,7 +23,6 @@ import android.content.Intent;
|
||||
import android.util.LayoutDirection;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.window.embedding.ActivityFilter;
|
||||
import androidx.window.embedding.ActivityRule;
|
||||
import androidx.window.embedding.SplitController;
|
||||
@@ -114,7 +113,7 @@ public class ActivityEmbeddingRulesController {
|
||||
|
||||
registerTwoPanePairRule(
|
||||
context,
|
||||
getComponentName(context, Settings.class),
|
||||
new ComponentName(context, Settings.class),
|
||||
secondaryComponent,
|
||||
secondaryIntentAction,
|
||||
finishPrimaryWithSecondary ? SplitRule.FINISH_ADJACENT : SplitRule.FINISH_NEVER,
|
||||
@@ -123,7 +122,7 @@ public class ActivityEmbeddingRulesController {
|
||||
|
||||
registerTwoPanePairRule(
|
||||
context,
|
||||
getComponentName(context, SettingsHomepageActivity.class),
|
||||
new ComponentName(context, SettingsHomepageActivity.class),
|
||||
secondaryComponent,
|
||||
secondaryIntentAction,
|
||||
finishPrimaryWithSecondary ? SplitRule.FINISH_ADJACENT : SplitRule.FINISH_NEVER,
|
||||
@@ -143,7 +142,7 @@ public class ActivityEmbeddingRulesController {
|
||||
|
||||
registerTwoPanePairRule(
|
||||
context,
|
||||
getComponentName(context, SliceDeepLinkHomepageActivity.class),
|
||||
new ComponentName(context, SliceDeepLinkHomepageActivity.class),
|
||||
secondaryComponent,
|
||||
secondaryIntentAction,
|
||||
finishPrimaryWithSecondary ? SplitRule.FINISH_ALWAYS : SplitRule.FINISH_NEVER,
|
||||
@@ -179,7 +178,7 @@ public class ActivityEmbeddingRulesController {
|
||||
|
||||
registerTwoPanePairRuleForSettingsHome(
|
||||
context,
|
||||
getComponentName(context, SubSettings.class),
|
||||
new ComponentName(context, SubSettings.class),
|
||||
null /* secondaryIntentAction */,
|
||||
clearTop);
|
||||
}
|
||||
@@ -191,8 +190,7 @@ public class ActivityEmbeddingRulesController {
|
||||
addActivityFilter(activityFilters, SliceDeepLinkHomepageActivity.class);
|
||||
addActivityFilter(activityFilters, Settings.class);
|
||||
|
||||
final Intent intent = new Intent();
|
||||
intent.setComponent(getComponentName(Settings.NetworkDashboardActivity.class));
|
||||
final Intent intent = new Intent(mContext, Settings.NetworkDashboardActivity.class);
|
||||
final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule(
|
||||
activityFilters,
|
||||
intent,
|
||||
@@ -215,23 +213,7 @@ public class ActivityEmbeddingRulesController {
|
||||
|
||||
private void addActivityFilter(Set<ActivityFilter> activityFilters,
|
||||
Class<? extends Activity> activityClass) {
|
||||
activityFilters.add(new ActivityFilter(getComponentName(activityClass),
|
||||
activityFilters.add(new ActivityFilter(new ComponentName(mContext, activityClass),
|
||||
null /* intentAction */));
|
||||
}
|
||||
|
||||
private void addActivityFilter(Set<ActivityFilter> activityFilters,
|
||||
ComponentName componentName) {
|
||||
activityFilters.add(new ActivityFilter(componentName, null /* intentAction */));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ComponentName getComponentName(Class<? extends Activity> activityClass) {
|
||||
return getComponentName(mContext, activityClass);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ComponentName getComponentName(Context context,
|
||||
Class<? extends Activity> activityClass) {
|
||||
return new ComponentName(context.getPackageName(), activityClass.getName());
|
||||
}
|
||||
}
|
||||
|
@@ -36,7 +36,6 @@ import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITL
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.IContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -63,6 +62,7 @@ import com.android.settings.Utils;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
|
||||
import com.android.settings.homepage.TopLevelHighlightMixin;
|
||||
import com.android.settings.homepage.TopLevelSettings;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.PrimarySwitchPreference;
|
||||
@@ -170,27 +170,23 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
if (action != null) {
|
||||
intent.setAction(action);
|
||||
}
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
OnCancelListener listener = null;
|
||||
if (fragment instanceof TopLevelSettings
|
||||
&& ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) {
|
||||
// Register the rule for injected apps.
|
||||
ActivityEmbeddingRulesController.registerTwoPanePairRuleForSettingsHome(
|
||||
mContext,
|
||||
new ComponentName(tile.getPackageName(), tile.getComponentName()),
|
||||
null /* secondaryIntentAction */,
|
||||
action,
|
||||
true /* clearTop */);
|
||||
|
||||
// Highlight preference ui.
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
TopLevelHighlightMixin highlightMixin = null;
|
||||
if (fragment instanceof TopLevelSettings
|
||||
&& ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) {
|
||||
// Highlight the preference whenever it's clicked
|
||||
final TopLevelSettings topLevelSettings = (TopLevelSettings) fragment;
|
||||
// Highlight the tile immediately whenever it's clicked
|
||||
topLevelSettings.setHighlightPreferenceKey(key);
|
||||
// If the tile allows users to select profile, the pop-op dialog may be
|
||||
// cancelled and then the previous highlight entry should be restored.
|
||||
listener = dialog -> topLevelSettings.restorePreviousHighlight();
|
||||
highlightMixin = topLevelSettings.getHighlightMixin();
|
||||
}
|
||||
launchIntentOrSelectProfile(activity, tile, intent, sourceMetricsCategory,
|
||||
listener);
|
||||
highlightMixin);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -223,7 +219,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
SettingsEnums.DASHBOARD_SUMMARY)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
launchIntentOrSelectProfile(activity, tile, intent, SettingsEnums.DASHBOARD_SUMMARY,
|
||||
/* listener= */ null);
|
||||
/* highlightMixin= */ null);
|
||||
}
|
||||
|
||||
private DynamicDataObserver createDynamicDataObserver(String method, Uri uri, Preference pref) {
|
||||
@@ -438,7 +434,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
}
|
||||
|
||||
private void launchIntentOrSelectProfile(FragmentActivity activity, Tile tile, Intent intent,
|
||||
int sourceMetricCategory, OnCancelListener listener) {
|
||||
int sourceMetricCategory, TopLevelHighlightMixin highlightMixin) {
|
||||
if (!isIntentResolvable(intent)) {
|
||||
Log.w(TAG, "Cannot resolve intent, skipping. " + intent);
|
||||
return;
|
||||
@@ -469,7 +465,9 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
}
|
||||
|
||||
ProfileSelectDialog.show(activity.getSupportFragmentManager(), tile,
|
||||
sourceMetricCategory, listener);
|
||||
sourceMetricCategory, /* onShowListener= */ highlightMixin,
|
||||
/* onDismissListener= */ highlightMixin,
|
||||
/* onCancelListener= */ highlightMixin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,8 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.DialogInterface.OnShowListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
@@ -45,23 +47,30 @@ public class ProfileSelectDialog extends DialogFragment implements OnClickListen
|
||||
|
||||
private int mSourceMetricCategory;
|
||||
private Tile mSelectedTile;
|
||||
private OnShowListener mOnShowListener;
|
||||
private OnCancelListener mOnCancelListener;
|
||||
private OnDismissListener mOnDismissListener;
|
||||
|
||||
/**
|
||||
* Display the profile select dialog, adding the fragment to the given FragmentManager.
|
||||
* @param manager The FragmentManager this fragment will be added to.
|
||||
* @param tile The tile for this fragment.
|
||||
* @param sourceMetricCategory The source metric category.
|
||||
* @param listener The listener listens to the dialog cancelling event.
|
||||
* @param onShowListener The listener listens to the dialog showing event.
|
||||
* @param onDismissListener The listener listens to the dialog dismissing event.
|
||||
* @param onCancelListener The listener listens to the dialog cancelling event.
|
||||
*/
|
||||
public static void show(FragmentManager manager, Tile tile, int sourceMetricCategory,
|
||||
OnCancelListener listener) {
|
||||
OnShowListener onShowListener, OnDismissListener onDismissListener,
|
||||
OnCancelListener onCancelListener) {
|
||||
final ProfileSelectDialog dialog = new ProfileSelectDialog();
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(ARG_SELECTED_TILE, tile);
|
||||
args.putInt(ARG_SOURCE_METRIC_CATEGORY, sourceMetricCategory);
|
||||
dialog.setArguments(args);
|
||||
dialog.mOnCancelListener = listener;
|
||||
dialog.mOnShowListener = onShowListener;
|
||||
dialog.mOnDismissListener = onDismissListener;
|
||||
dialog.mOnCancelListener = onCancelListener;
|
||||
dialog.show(manager, "select_profile");
|
||||
}
|
||||
|
||||
@@ -96,13 +105,31 @@ public class ProfileSelectDialog extends DialogFragment implements OnClickListen
|
||||
getActivity().startActivityAsUser(intent, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
// The fragment shows the dialog within onStart()
|
||||
if (mOnShowListener != null) {
|
||||
mOnShowListener.onShow(getDialog());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
if (mOnCancelListener != null) {
|
||||
mOnCancelListener.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
if (mOnDismissListener != null) {
|
||||
mOnDismissListener.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateUserHandlesIfNeeded(Context context, Tile tile) {
|
||||
final List<UserHandle> userHandles = tile.userHandle;
|
||||
if (tile.userHandle == null || tile.userHandle.size() <= 1) {
|
||||
|
@@ -63,6 +63,11 @@ public class TopLevelWallpaperPreferenceController extends BasePreferenceControl
|
||||
super.displayPreference(screen);
|
||||
Preference preference = screen.findPreference(getPreferenceKey());
|
||||
preference.setTitle(getTitle());
|
||||
ActivityEmbeddingRulesController.registerTwoPanePairRuleForSettingsHome(
|
||||
mContext,
|
||||
getComponentName(),
|
||||
null /* secondaryIntentAction */,
|
||||
true /* clearTop */);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@@ -103,11 +108,6 @@ public class TopLevelWallpaperPreferenceController extends BasePreferenceControl
|
||||
mContext)) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
ActivityEmbeddingRulesController.registerTwoPanePairRuleForSettingsHome(
|
||||
mContext,
|
||||
intent.getComponent(),
|
||||
null /* secondaryIntentAction */,
|
||||
true /* clearTop */);
|
||||
preference.getContext().startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
public static final String EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_DATA =
|
||||
"settings_large_screen_deep_link_intent_data";
|
||||
|
||||
private static final int DEFAULT_HIGHLIGHT_MENU_KEY = R.string.menu_key_network;
|
||||
static final int DEFAULT_HIGHLIGHT_MENU_KEY = R.string.menu_key_network;
|
||||
private static final long HOMEPAGE_LOADING_TIMEOUT_MS = 300;
|
||||
|
||||
private TopLevelSettings mMainFragment;
|
||||
@@ -94,6 +94,10 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
void onHomepageLoaded();
|
||||
}
|
||||
|
||||
private interface FragmentBuilder<T extends Fragment> {
|
||||
T build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to add a {@link HomepageLoadedListener}. If homepage is already loaded, the listener
|
||||
* will not be notified.
|
||||
@@ -168,13 +172,15 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
initAvatarView();
|
||||
showSuggestionFragment();
|
||||
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.CONTEXTUAL_HOME)) {
|
||||
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
|
||||
showFragment(() -> new ContextualCardsFragment(), R.id.contextual_cards_content);
|
||||
}
|
||||
}
|
||||
mMainFragment = new TopLevelSettings();
|
||||
mMainFragment.getArguments().putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY,
|
||||
mMainFragment = showFragment(() -> {
|
||||
final TopLevelSettings fragment = new TopLevelSettings();
|
||||
fragment.getArguments().putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY,
|
||||
getHighlightMenuKey());
|
||||
showFragment(mMainFragment, R.id.main_content);
|
||||
return fragment;
|
||||
}, R.id.main_content);
|
||||
|
||||
((FrameLayout) findViewById(R.id.main_content))
|
||||
.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
|
||||
@@ -260,9 +266,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void showSuggestionFragment() {
|
||||
final Class<? extends Fragment> fragment = FeatureFactory.getFactory(this)
|
||||
final Class<? extends Fragment> fragmentClass = FeatureFactory.getFactory(this)
|
||||
.getSuggestionFeatureProvider(this).getContextualSuggestionFragment();
|
||||
if (fragment == null) {
|
||||
if (fragmentClass == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -274,28 +280,33 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
// Schedule a timer to show the homepage and hide the suggestion on timeout.
|
||||
mHomepageView.postDelayed(() -> showHomepageWithSuggestion(false),
|
||||
HOMEPAGE_LOADING_TIMEOUT_MS);
|
||||
final FragmentBuilder<?> fragmentBuilder = () -> {
|
||||
try {
|
||||
showFragment(fragment.getConstructor().newInstance(), R.id.suggestion_content);
|
||||
if (mIsEmbeddingActivityEnabled) {
|
||||
showFragment(fragment.getConstructor().newInstance(),
|
||||
R.id.two_pane_suggestion_content);
|
||||
}
|
||||
return fragmentClass.getConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Cannot show fragment", e);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
showFragment(fragmentBuilder, R.id.suggestion_content);
|
||||
if (mIsEmbeddingActivityEnabled) {
|
||||
showFragment(fragmentBuilder, R.id.two_pane_suggestion_content);
|
||||
}
|
||||
}
|
||||
|
||||
private void showFragment(Fragment fragment, int id) {
|
||||
private <T extends Fragment> T showFragment(FragmentBuilder<T> fragmentBuilder, int id) {
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
final Fragment showFragment = fragmentManager.findFragmentById(id);
|
||||
T showFragment = (T) fragmentManager.findFragmentById(id);
|
||||
|
||||
if (showFragment == null) {
|
||||
fragmentTransaction.add(id, fragment);
|
||||
showFragment = fragmentBuilder.build();
|
||||
fragmentTransaction.add(id, showFragment);
|
||||
} else {
|
||||
fragmentTransaction.show(showFragment);
|
||||
}
|
||||
fragmentTransaction.commit();
|
||||
return showFragment;
|
||||
}
|
||||
|
||||
private void launchDeepLinkIntentToRight() {
|
||||
@@ -363,14 +374,14 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
targetIntent.getAction(),
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
true /* clearTop*/);
|
||||
true /* clearTop */);
|
||||
ActivityEmbeddingRulesController.registerTwoPanePairRule(this,
|
||||
new ComponentName(Settings.class.getPackageName(), Settings.class.getName()),
|
||||
new ComponentName(getApplicationContext(), Settings.class),
|
||||
targetComponentName,
|
||||
targetIntent.getAction(),
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
SplitRule.FINISH_ALWAYS,
|
||||
true /* clearTop*/);
|
||||
true /* clearTop */);
|
||||
startActivity(targetIntent);
|
||||
}
|
||||
|
||||
|
189
src/com/android/settings/homepage/TopLevelHighlightMixin.java
Normal file
189
src/com/android/settings/homepage/TopLevelHighlightMixin.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.settings.homepage;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.widget.HighlightableTopLevelPreferenceAdapter;
|
||||
|
||||
/** A highlight mixin for the top level settings fragment. */
|
||||
public class TopLevelHighlightMixin implements Parcelable, DialogInterface.OnShowListener,
|
||||
DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String TAG = "TopLevelHighlightMixin";
|
||||
|
||||
private String mCurrentKey;
|
||||
// Stores the previous key for the profile select dialog cancel event
|
||||
private String mPreviousKey;
|
||||
// Stores the key hidden for the search page presence
|
||||
private String mHiddenKey;
|
||||
private DialogInterface mDialog;
|
||||
private HighlightableTopLevelPreferenceAdapter mTopLevelAdapter;
|
||||
|
||||
public TopLevelHighlightMixin() {
|
||||
}
|
||||
|
||||
public TopLevelHighlightMixin(Parcel source) {
|
||||
mCurrentKey = source.readString();
|
||||
mPreviousKey = source.readString();
|
||||
mHiddenKey = source.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mCurrentKey);
|
||||
dest.writeString(mPreviousKey);
|
||||
dest.writeString(mHiddenKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<TopLevelHighlightMixin> CREATOR = new Creator<>() {
|
||||
@Override
|
||||
public TopLevelHighlightMixin createFromParcel(Parcel source) {
|
||||
return new TopLevelHighlightMixin(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TopLevelHighlightMixin[] newArray(int size) {
|
||||
return new TopLevelHighlightMixin[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onShow(DialogInterface dialog) {
|
||||
mDialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
mDialog = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
if (mTopLevelAdapter != null) {
|
||||
mCurrentKey = mPreviousKey;
|
||||
mPreviousKey = null;
|
||||
mTopLevelAdapter.highlightPreference(mCurrentKey, /* scrollNeeded= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
RecyclerView.Adapter onCreateAdapter(TopLevelSettings topLevelSettings,
|
||||
PreferenceScreen preferenceScreen) {
|
||||
if (TextUtils.isEmpty(mCurrentKey)) {
|
||||
mCurrentKey = getHighlightPrefKeyFromArguments(topLevelSettings.getArguments());
|
||||
}
|
||||
|
||||
Log.d(TAG, "onCreateAdapter, pref key: " + mCurrentKey);
|
||||
mTopLevelAdapter = new HighlightableTopLevelPreferenceAdapter(
|
||||
(SettingsHomepageActivity) topLevelSettings.getActivity(), preferenceScreen,
|
||||
topLevelSettings.getListView(), mCurrentKey);
|
||||
return mTopLevelAdapter;
|
||||
}
|
||||
|
||||
void reloadHighlightMenuKey(Bundle arguments) {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
}
|
||||
ensureDialogDismissed();
|
||||
|
||||
mCurrentKey = getHighlightPrefKeyFromArguments(arguments);
|
||||
Log.d(TAG, "reloadHighlightMenuKey, pref key: " + mCurrentKey);
|
||||
mTopLevelAdapter.highlightPreference(mCurrentKey, /* scrollNeeded= */ true);
|
||||
}
|
||||
|
||||
void setHighlightPreferenceKey(String prefKey) {
|
||||
if (mTopLevelAdapter != null) {
|
||||
ensureDialogDismissed();
|
||||
mPreviousKey = mCurrentKey;
|
||||
mCurrentKey = prefKey;
|
||||
mTopLevelAdapter.highlightPreference(prefKey, /* scrollNeeded= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
void highlightPreferenceIfNeeded(FragmentActivity activity) {
|
||||
if (mTopLevelAdapter != null) {
|
||||
mTopLevelAdapter.requestHighlight();
|
||||
}
|
||||
}
|
||||
|
||||
void setMenuHighlightShowed(boolean show) {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
}
|
||||
ensureDialogDismissed();
|
||||
|
||||
if (show) {
|
||||
mCurrentKey = mHiddenKey;
|
||||
mHiddenKey = null;
|
||||
} else {
|
||||
if (mHiddenKey == null) {
|
||||
mHiddenKey = mCurrentKey;
|
||||
}
|
||||
mCurrentKey = null;
|
||||
}
|
||||
mTopLevelAdapter.highlightPreference(mCurrentKey, /* scrollNeeded= */ show);
|
||||
}
|
||||
|
||||
void setHighlightMenuKey(String menuKey, boolean scrollNeeded) {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
}
|
||||
ensureDialogDismissed();
|
||||
|
||||
final String prefKey = HighlightableMenu.lookupPreferenceKey(menuKey);
|
||||
if (TextUtils.isEmpty(prefKey)) {
|
||||
Log.e(TAG, "Invalid highlight menu key: " + menuKey);
|
||||
} else {
|
||||
Log.d(TAG, "Menu key: " + menuKey);
|
||||
mCurrentKey = prefKey;
|
||||
mTopLevelAdapter.highlightPreference(prefKey, scrollNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getHighlightPrefKeyFromArguments(Bundle arguments) {
|
||||
final String menuKey = arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY);
|
||||
final String prefKey = HighlightableMenu.lookupPreferenceKey(menuKey);
|
||||
if (TextUtils.isEmpty(prefKey)) {
|
||||
Log.e(TAG, "Invalid highlight menu key: " + menuKey);
|
||||
} else {
|
||||
Log.d(TAG, "Menu key: " + menuKey);
|
||||
}
|
||||
return prefKey;
|
||||
}
|
||||
|
||||
private void ensureDialogDismissed() {
|
||||
if (mDialog != null) {
|
||||
onCancel(mDialog);
|
||||
mDialog.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,7 +25,6 @@ import android.content.res.Configuration;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
@@ -34,7 +33,6 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
@@ -42,7 +40,6 @@ import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.support.SupportPreferenceController;
|
||||
import com.android.settings.widget.HighlightableTopLevelPreferenceAdapter;
|
||||
import com.android.settings.widget.HomepagePreference;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
@@ -53,13 +50,10 @@ public class TopLevelSettings extends DashboardFragment implements
|
||||
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
|
||||
|
||||
private static final String TAG = "TopLevelSettings";
|
||||
private static final String SAVED_HIGHLIGHTED_PREF = "highlighted_pref";
|
||||
private static final String SAVED_CACHED_PREF = "cached_pref";
|
||||
private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin";
|
||||
private static final String PREF_KEY_SUPPORT = "top_level_support";
|
||||
|
||||
private HighlightableTopLevelPreferenceAdapter mTopLevelAdapter;
|
||||
|
||||
private String mHighlightedPreferenceKey;
|
||||
private String mCachedPreferenceKey;
|
||||
private TopLevelHighlightMixin mHighlightMixin;
|
||||
|
||||
public TopLevelSettings() {
|
||||
final Bundle args = new Bundle();
|
||||
@@ -127,17 +121,35 @@ public class TopLevelSettings extends DashboardFragment implements
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
if (icicle != null) {
|
||||
mHighlightedPreferenceKey = icicle.getString(SAVED_HIGHLIGHTED_PREF);
|
||||
mCachedPreferenceKey = icicle.getString(SAVED_CACHED_PREF);
|
||||
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (icicle != null) {
|
||||
mHighlightMixin = icicle.getParcelable(SAVED_HIGHLIGHT_MIXIN);
|
||||
}
|
||||
if (mHighlightMixin == null) {
|
||||
mHighlightMixin = new TopLevelHighlightMixin();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
// Set default highlight menu key for 1-pane homepage since it will show the placeholder
|
||||
// page once changing back to 2-pane.
|
||||
if (!ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) {
|
||||
setHighlightMenuKey(getString(SettingsHomepageActivity.DEFAULT_HIGHLIGHT_MENU_KEY),
|
||||
/* scrollNeeded= */ false);
|
||||
}
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(SAVED_HIGHLIGHTED_PREF, mHighlightedPreferenceKey);
|
||||
outState.putString(SAVED_CACHED_PREF, mCachedPreferenceKey);
|
||||
if (mHighlightMixin != null) {
|
||||
outState.putParcelable(SAVED_HIGHLIGHT_MIXIN, mHighlightMixin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,58 +182,35 @@ public class TopLevelSettings extends DashboardFragment implements
|
||||
|
||||
@Override
|
||||
public void highlightPreferenceIfNeeded() {
|
||||
if (mTopLevelAdapter != null) {
|
||||
mTopLevelAdapter.requestHighlight();
|
||||
if (mHighlightMixin != null) {
|
||||
mHighlightMixin.highlightPreferenceIfNeeded(getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a {@link TopLevelHighlightMixin} that performs highlighting */
|
||||
public TopLevelHighlightMixin getHighlightMixin() {
|
||||
return mHighlightMixin;
|
||||
}
|
||||
|
||||
/** Highlight a preference with specified preference key */
|
||||
public void setHighlightPreferenceKey(String prefKey) {
|
||||
if (mTopLevelAdapter != null) {
|
||||
mCachedPreferenceKey = null;
|
||||
mHighlightedPreferenceKey = prefKey;
|
||||
mTopLevelAdapter.highlightPreference(prefKey, /* scrollNeeded= */ false);
|
||||
// Skip Tips & support since it's full screen
|
||||
if (mHighlightMixin != null && !TextUtils.equals(prefKey, PREF_KEY_SUPPORT)) {
|
||||
mHighlightMixin.setHighlightPreferenceKey(prefKey);
|
||||
}
|
||||
}
|
||||
|
||||
/** Highlight the previous preference */
|
||||
public void restorePreviousHighlight() {
|
||||
if (mTopLevelAdapter != null) {
|
||||
mTopLevelAdapter.restorePreviousHighlight();
|
||||
}
|
||||
}
|
||||
|
||||
/** Show/hide the highlight on the menu entry */
|
||||
/** Show/hide the highlight on the menu entry for the search page presence */
|
||||
public void setMenuHighlightShowed(boolean show) {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
if (mHighlightMixin != null) {
|
||||
mHighlightMixin.setMenuHighlightShowed(show);
|
||||
}
|
||||
|
||||
if (show) {
|
||||
mHighlightedPreferenceKey = mCachedPreferenceKey;
|
||||
mCachedPreferenceKey = null;
|
||||
} else {
|
||||
if (mCachedPreferenceKey == null) {
|
||||
mCachedPreferenceKey = mHighlightedPreferenceKey;
|
||||
}
|
||||
mHighlightedPreferenceKey = null;
|
||||
}
|
||||
mTopLevelAdapter.highlightPreference(mHighlightedPreferenceKey, /* scrollNeeded= */ show);
|
||||
}
|
||||
|
||||
/** Highlight and scroll to a preference with specified menu key */
|
||||
public void setHighlightMenuKey(String menuKey) {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String prefKey = HighlightableMenu.lookupPreferenceKey(menuKey);
|
||||
if (TextUtils.isEmpty(prefKey)) {
|
||||
Log.e(TAG, "Invalid highlight menu key: " + menuKey);
|
||||
} else {
|
||||
Log.d(TAG, "Menu key: " + menuKey);
|
||||
mHighlightedPreferenceKey = prefKey;
|
||||
mTopLevelAdapter.highlightPreference(prefKey, /* scrollNeeded= */ true);
|
||||
public void setHighlightMenuKey(String menuKey, boolean scrollNeeded) {
|
||||
if (mHighlightMixin != null) {
|
||||
mHighlightMixin.setHighlightMenuKey(menuKey, scrollNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,16 +226,7 @@ public class TopLevelSettings extends DashboardFragment implements
|
||||
|| !(getActivity() instanceof SettingsHomepageActivity)) {
|
||||
return super.onCreateAdapter(preferenceScreen);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(mHighlightedPreferenceKey)) {
|
||||
mHighlightedPreferenceKey = getHighlightPrefKeyFromArguments();
|
||||
}
|
||||
|
||||
Log.d(TAG, "onCreateAdapter, pref key: " + mHighlightedPreferenceKey);
|
||||
mTopLevelAdapter = new HighlightableTopLevelPreferenceAdapter(
|
||||
(SettingsHomepageActivity) getActivity(), preferenceScreen, getListView(),
|
||||
mHighlightedPreferenceKey);
|
||||
return mTopLevelAdapter;
|
||||
return mHighlightMixin.onCreateAdapter(this, preferenceScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -255,25 +235,9 @@ public class TopLevelSettings extends DashboardFragment implements
|
||||
}
|
||||
|
||||
void reloadHighlightMenuKey() {
|
||||
if (mTopLevelAdapter == null) {
|
||||
return;
|
||||
if (mHighlightMixin != null) {
|
||||
mHighlightMixin.reloadHighlightMenuKey(getArguments());
|
||||
}
|
||||
|
||||
mHighlightedPreferenceKey = getHighlightPrefKeyFromArguments();
|
||||
Log.d(TAG, "reloadHighlightMenuKey, pref key: " + mHighlightedPreferenceKey);
|
||||
mTopLevelAdapter.highlightPreference(mHighlightedPreferenceKey, /* scrollNeeded= */ true);
|
||||
}
|
||||
|
||||
private String getHighlightPrefKeyFromArguments() {
|
||||
final Bundle arguments = getArguments();
|
||||
final String menuKey = arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY);
|
||||
final String prefKey = HighlightableMenu.lookupPreferenceKey(menuKey);
|
||||
if (TextUtils.isEmpty(prefKey)) {
|
||||
Log.e(TAG, "Invalid highlight menu key: " + menuKey);
|
||||
} else {
|
||||
Log.d(TAG, "Menu key: " + menuKey);
|
||||
}
|
||||
return prefKey;
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
|
@@ -109,7 +109,8 @@ public class SearchResultTrampoline extends Activity {
|
||||
final SettingsHomepageActivity homeActivity =
|
||||
((SettingsApplication) getApplicationContext()).getHomeActivity();
|
||||
if (homeActivity != null) {
|
||||
homeActivity.getMainFragment().setHighlightMenuKey(highlightMenuKey);
|
||||
homeActivity.getMainFragment().setHighlightMenuKey(highlightMenuKey,
|
||||
/* scrollNeeded= */ true);
|
||||
}
|
||||
} else {
|
||||
// Two-pane case
|
||||
|
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@@ -59,17 +60,18 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
private final int mNormalBackgroundRes;
|
||||
private final int mHighlightBackgroundRes;
|
||||
private String mHighlightKey;
|
||||
private String mPreviousHighlightKey;
|
||||
private int mHighlightPosition = RecyclerView.NO_POSITION;
|
||||
private int mScrollPosition = RecyclerView.NO_POSITION;
|
||||
private boolean mHighlightNeeded;
|
||||
private boolean mScrolled;
|
||||
private SparseArray<PreferenceViewHolder> mViewHolders;
|
||||
|
||||
public HighlightableTopLevelPreferenceAdapter(SettingsHomepageActivity homepageActivity,
|
||||
PreferenceGroup preferenceGroup, RecyclerView recyclerView, String key) {
|
||||
super(preferenceGroup);
|
||||
mRecyclerView = recyclerView;
|
||||
mHighlightKey = key;
|
||||
mViewHolders = new SparseArray<>();
|
||||
mContext = preferenceGroup.getContext();
|
||||
mHomepageActivity = homepageActivity;
|
||||
final TypedValue outValue = new TypedValue();
|
||||
@@ -92,6 +94,7 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
mViewHolders.put(position, holder);
|
||||
updateBackground(holder, position);
|
||||
}
|
||||
|
||||
@@ -120,9 +123,9 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
return;
|
||||
}
|
||||
|
||||
final int previousPosition = mHighlightPosition;
|
||||
if (TextUtils.isEmpty(mHighlightKey)) {
|
||||
// De-highlight previous preference.
|
||||
final int previousPosition = mHighlightPosition;
|
||||
mHighlightPosition = RecyclerView.NO_POSITION;
|
||||
mScrolled = true;
|
||||
if (previousPosition >= 0) {
|
||||
@@ -145,10 +148,14 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
|
||||
// Turn on/off highlight when screen split mode is changed.
|
||||
if (highlightNeeded != mHighlightNeeded) {
|
||||
Log.d(TAG, "Highlight change needed: " + highlightNeeded);
|
||||
Log.d(TAG, "Highlight needed change: " + highlightNeeded);
|
||||
mHighlightNeeded = highlightNeeded;
|
||||
mHighlightPosition = position;
|
||||
notifyItemChanged(position);
|
||||
if (!highlightNeeded) {
|
||||
// De-highlight to prevent a flicker
|
||||
removeHighlightAt(previousPosition);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,7 +163,6 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
return;
|
||||
}
|
||||
|
||||
final int previousPosition = mHighlightPosition;
|
||||
mHighlightPosition = position;
|
||||
Log.d(TAG, "Request highlight position " + position);
|
||||
Log.d(TAG, "Is highlight needed: " + highlightNeeded);
|
||||
@@ -178,20 +184,11 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
* preference is clicked.
|
||||
*/
|
||||
public void highlightPreference(String key, boolean scrollNeeded) {
|
||||
mPreviousHighlightKey = mHighlightKey;
|
||||
mHighlightKey = key;
|
||||
mScrolled = !scrollNeeded;
|
||||
requestHighlight();
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that restores the previous highlighted setting.
|
||||
*/
|
||||
public void restorePreviousHighlight() {
|
||||
mHighlightKey = mPreviousHighlightKey;
|
||||
requestHighlight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHomepageLoaded() {
|
||||
scroll();
|
||||
@@ -224,6 +221,17 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
}
|
||||
}
|
||||
|
||||
private void removeHighlightAt(int position) {
|
||||
if (position >= 0) {
|
||||
// De-highlight the existing preference view holder at an early stage
|
||||
final PreferenceViewHolder holder = mViewHolders.get(position);
|
||||
if (holder != null) {
|
||||
removeHighlightBackground(holder);
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
|
||||
private void addHighlightBackground(PreferenceViewHolder holder) {
|
||||
final View v = holder.itemView;
|
||||
v.setBackgroundResource(mHighlightBackgroundRes);
|
||||
|
Reference in New Issue
Block a user