diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a5f48a24dda..8e62f7f59b4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3112,7 +3112,7 @@ diff --git a/src/com/android/settings/media/MediaOutputIndicatorSlice.java b/src/com/android/settings/media/MediaOutputIndicatorSlice.java index fe59d7531db..dec50bcb9d9 100644 --- a/src/com/android/settings/media/MediaOutputIndicatorSlice.java +++ b/src/com/android/settings/media/MediaOutputIndicatorSlice.java @@ -90,7 +90,7 @@ public class MediaOutputIndicatorSlice implements CustomSliceable { private Intent getMediaOutputSliceIntent() { final Intent intent = new Intent() .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; } diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java index 4e4fc0cd4f8..ae72427cbf7 100644 --- a/src/com/android/settings/panel/InternetConnectivityPanel.java +++ b/src/com/android/settings/panel/InternetConnectivityPanel.java @@ -63,7 +63,8 @@ public class InternetConnectivityPanel implements PanelContent { @Override public Intent getSeeMoreIntent() { - return new Intent(Settings.ACTION_WIRELESS_SETTINGS); + return new Intent(Settings.ACTION_WIRELESS_SETTINGS) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } @Override diff --git a/src/com/android/settings/panel/NfcPanel.java b/src/com/android/settings/panel/NfcPanel.java index 6a9c74dbb20..c1e15e84063 100644 --- a/src/com/android/settings/panel/NfcPanel.java +++ b/src/com/android/settings/panel/NfcPanel.java @@ -64,6 +64,7 @@ public class NfcPanel implements PanelContent { screenTitle, SettingsEnums.SETTINGS_CONNECTED_DEVICE_CATEGORY); intent.setClassName(mContext.getPackageName(), SubSettings.class.getName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; } diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java index 173461c7699..e9eeb8d2041 100644 --- a/src/com/android/settings/panel/PanelFragment.java +++ b/src/com/android/settings/panel/PanelFragment.java @@ -16,6 +16,8 @@ package com.android.settings.panel; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -29,7 +31,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; import android.widget.Button; import android.widget.TextView; @@ -59,9 +60,14 @@ public class PanelFragment extends Fragment { private static final String TAG = "PanelFragment"; /** - * Duration of the animation entering or exiting the screen, in milliseconds. + * Duration of the animation entering the screen, in milliseconds. */ - private static final int DURATION_ANIMATE_PANEL_MS = 250; + private static final int DURATION_ANIMATE_PANEL_EXPAND_MS = 250; + + /** + * Duration of the animation exiting the screen, in milliseconds. + */ + private static final int DURATION_ANIMATE_PANEL_COLLAPSE_MS = 200; /** * Duration of timeout waiting for Slice data to bind, in milliseconds. @@ -104,15 +110,53 @@ public class PanelFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - final FragmentActivity activity = getActivity(); - mLayoutView = inflater.inflate(R.layout.panel_layout, container, false); + createPanelContent(); + return mLayoutView; + } + + /** + * Animate the old panel out from the screen, then update the panel with new content once the + * animation is done. + *

+ * Takes the entire panel and animates out from behind the navigation bar. + *

+ * Call createPanelContent() once animation end. + */ + void updatePanelWithAnimation() { + final View panelContent = mLayoutView.findViewById(R.id.panel_container); + final AnimatorSet animatorSet = buildAnimatorSet(mLayoutView, + 0.0f /* startY */, panelContent.getHeight() /* endY */, + 1.0f /* startAlpha */, 0.0f /* endAlpha */, + DURATION_ANIMATE_PANEL_COLLAPSE_MS); + + final ValueAnimator animator = new ValueAnimator(); + animator.setFloatValues(0.0f, 1.0f); + animatorSet.play(animator); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + createPanelContent(); + } + }); + animatorSet.start(); + } + + private void createPanelContent() { + final FragmentActivity activity = getActivity(); + if (mLayoutView == null) { + activity.finish(); + } mPanelSlices = mLayoutView.findViewById(R.id.panel_parent_layout); mSeeMoreButton = mLayoutView.findViewById(R.id.see_more); mDoneButton = mLayoutView.findViewById(R.id.done); mTitleView = mLayoutView.findViewById(R.id.panel_title); + // Make the panel layout gone here, to avoid janky animation when updating from old panel. + // We will make it visible once the panel is ready to load. + mPanelSlices.setVisibility(View.GONE); + final Bundle arguments = getArguments(); final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT); @@ -152,8 +196,6 @@ public class PanelFragment extends Fragment { mPanel.getMetricsCategory(), callingPackageName, 0 /* value */); - - return mLayoutView; } private void loadAllSlices() { @@ -220,6 +262,7 @@ public class PanelFragment extends Fragment { mPanelSlices.setAdapter(mAdapter); mPanelSlices.getViewTreeObserver() .addOnGlobalLayoutListener(mOnGlobalLayoutListener); + mPanelSlices.setVisibility(View.VISIBLE); DividerItemDecoration itemDecoration = new DividerItemDecoration(getActivity()); itemDecoration @@ -237,8 +280,10 @@ public class PanelFragment extends Fragment { */ private void animateIn() { final View panelContent = mLayoutView.findViewById(R.id.panel_container); - final AnimatorSet animatorSet = buildAnimatorSet(mLayoutView, panelContent.getHeight(), - 0.0f, new DecelerateInterpolator()); + final AnimatorSet animatorSet = buildAnimatorSet(mLayoutView, + panelContent.getHeight() /* startY */, 0.0f /* endY */, + 0.0f /* startAlpha */, 1.0f /* endAlpha */, + DURATION_ANIMATE_PANEL_EXPAND_MS); final ValueAnimator animator = new ValueAnimator(); animator.setFloatValues(0.0f, 1.0f); animatorSet.play(animator); @@ -248,18 +293,21 @@ public class PanelFragment extends Fragment { } /** - * Build an {@link AnimatorSet} to bring the Panel, {@param parentView}in our out of the screen, - * based on the positional parameters {@param startY}, {@param endY} and at the rate set by the - * {@param interpolator}. + * Build an {@link AnimatorSet} to animate the Panel, {@param parentView} in or out of the + * screen, based on the positional parameters {@param startY}, {@param endY}, the parameters + * for alpha changes {@param startAlpha}, {@param endAlpha}, and the {@param duration} in + * milliseconds. */ @NonNull private static AnimatorSet buildAnimatorSet(@NonNull View parentView, float startY, float endY, - @NonNull Interpolator interpolator) { + float startAlpha, float endAlpha, int duration) { final View sheet = parentView.findViewById(R.id.panel_container); final AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.setDuration(DURATION_ANIMATE_PANEL_MS); - animatorSet.setInterpolator(interpolator); - animatorSet.playTogether(ObjectAnimator.ofFloat(sheet, View.TRANSLATION_Y, startY, endY)); + animatorSet.setDuration(duration); + animatorSet.setInterpolator(new DecelerateInterpolator()); + animatorSet.playTogether( + ObjectAnimator.ofFloat(sheet, View.TRANSLATION_Y, startY, endY), + ObjectAnimator.ofFloat(sheet, View.ALPHA, startAlpha,endAlpha)); return animatorSet; } diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java index eabd7151fc8..a2cb2771ed9 100644 --- a/src/com/android/settings/panel/SettingsPanelActivity.java +++ b/src/com/android/settings/panel/SettingsPanelActivity.java @@ -21,6 +21,7 @@ import static com.android.settingslib.media.MediaOutputSliceConstants.EXTRA_PACK import android.app.settings.SettingsEnums; import android.content.Intent; import android.os.Bundle; +import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; @@ -65,7 +66,17 @@ public class SettingsPanelActivity extends FragmentActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + showOrUpdatePanel(); + } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + showOrUpdatePanel(); + } + + private void showOrUpdatePanel() { final Intent callingIntent = getIntent(); if (callingIntent == null) { Log.e(TAG, "Null intent, closing Panel Activity"); @@ -76,24 +87,28 @@ public class SettingsPanelActivity extends FragmentActivity { // We will use it once media output switch panel support remote device. final String mediaPackageName = callingIntent.getStringExtra(EXTRA_PACKAGE_NAME); - setContentView(R.layout.settings_panel); - - // Move the window to the bottom of screen, and make it take up the entire screen width. - final Window window = getWindow(); - window.setGravity(Gravity.BOTTOM); - window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.WRAP_CONTENT); - mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, callingIntent.getAction()); mBundle.putString(KEY_CALLING_PACKAGE_NAME, getCallingPackage()); mBundle.putString(KEY_MEDIA_PACKAGE_NAME, mediaPackageName); - final PanelFragment panelFragment = new PanelFragment(); - panelFragment.setArguments(mBundle); - final FragmentManager fragmentManager = getSupportFragmentManager(); final Fragment fragment = fragmentManager.findFragmentById(R.id.main_content); - if (fragment == null) { + + // If fragment already exists, we will need to update panel with animation. + if (fragment != null && fragment instanceof PanelFragment) { + final PanelFragment panelFragment = (PanelFragment) fragment; + panelFragment.setArguments(mBundle); + ((PanelFragment) fragment).updatePanelWithAnimation(); + } else { + setContentView(R.layout.settings_panel); + + // Move the window to the bottom of screen, and make it take up the entire screen width. + final Window window = getWindow(); + window.setGravity(Gravity.BOTTOM); + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT); + final PanelFragment panelFragment = new PanelFragment(); + panelFragment.setArguments(mBundle); fragmentManager.beginTransaction().add(R.id.main_content, panelFragment).commit(); } } diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java index 2cbf7295141..1a166bae5c3 100644 --- a/src/com/android/settings/panel/VolumePanel.java +++ b/src/com/android/settings/panel/VolumePanel.java @@ -68,7 +68,7 @@ public class VolumePanel implements PanelContent { @Override public Intent getSeeMoreIntent() { - return new Intent(Settings.ACTION_SOUND_SETTINGS); + return new Intent(Settings.ACTION_SOUND_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } @Override diff --git a/src/com/android/settings/panel/WifiPanel.java b/src/com/android/settings/panel/WifiPanel.java index f9be081c70d..36ee1178d06 100644 --- a/src/com/android/settings/panel/WifiPanel.java +++ b/src/com/android/settings/panel/WifiPanel.java @@ -67,6 +67,7 @@ public class WifiPanel implements PanelContent { screenTitle, SettingsEnums.WIFI); intent.setClassName(mContext.getPackageName(), SubSettings.class.getName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; }