Merge "Controls UI - Motion for activities" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-21 13:43:30 +00:00
committed by Android (Google) Code Review
10 changed files with 324 additions and 62 deletions

View File

@@ -17,6 +17,7 @@
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/controls_management_root"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -1014,6 +1014,9 @@
<!-- Margins at the left and right of the power menu and home controls widgets. --> <!-- Margins at the left and right of the power menu and home controls widgets. -->
<dimen name="global_actions_side_margin">16dp</dimen> <dimen name="global_actions_side_margin">16dp</dimen>
<!-- Amount to shift the layout when exiting/entering for controls activities -->
<dimen name="global_actions_controls_y_translation">20dp</dimen>
<!-- The maximum offset in either direction that elements are moved horizontally to prevent <!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. --> burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen> <dimen name="burn_in_prevention_offset_x">8dp</dimen>

View File

@@ -663,8 +663,13 @@
<!-- Controls styles --> <!-- Controls styles -->
<style name="Theme.ControlsManagement" parent="@android:style/Theme.DeviceDefault.NoActionBar"> <style name="Theme.ControlsManagement" parent="@android:style/Theme.DeviceDefault.NoActionBar">
<item name="android:windowActivityTransitions">true</item>
<item name="android:windowContentTransitions">false</item>
<item name="android:windowIsTranslucent">false</item> <item name="android:windowIsTranslucent">false</item>
<item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item> <item name="android:windowBackground">@android:color/black</item>
<item name="android:colorBackground">@android:color/black</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:statusBarColor">@*android:color/transparent</item>
</style> </style>
<style name="TextAppearance.Control"> <style name="TextAppearance.Control">

View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2020 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.systemui.controls.management
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.IdRes
import android.content.Intent
import android.transition.Transition
import android.transition.TransitionValues
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.Window
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import com.android.systemui.Interpolators
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlsUiController
object ControlsAnimations {
private const val ALPHA_EXIT_DURATION = 167L
private const val ALPHA_ENTER_DELAY = ALPHA_EXIT_DURATION
private const val ALPHA_ENTER_DURATION = 350L - ALPHA_ENTER_DELAY
private const val Y_TRANSLATION_EXIT_DURATION = 183L
private const val Y_TRANSLATION_ENTER_DELAY = Y_TRANSLATION_EXIT_DURATION - ALPHA_ENTER_DELAY
private const val Y_TRANSLATION_ENTER_DURATION = 400L - Y_TRANSLATION_EXIT_DURATION
private var translationY: Float = -1f
/**
* Setup an activity to handle enter/exit animations. [view] should be the root of the content.
* Fade and translate together.
*/
fun observerForAnimations(view: ViewGroup, window: Window, intent: Intent): LifecycleObserver {
return object : LifecycleObserver {
var showAnimation = intent.getBooleanExtra(ControlsUiController.EXTRA_ANIMATE, false)
init {
// Must flag the parent group to move it all together, and set the initial
// transitionAlpha to 0.0f. This property is reserved for fade animations.
view.setTransitionGroup(true)
view.transitionAlpha = 0.0f
if (translationY == -1f) {
translationY = view.context.resources.getDimensionPixelSize(
R.dimen.global_actions_controls_y_translation).toFloat()
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun setup() {
with(window) {
allowEnterTransitionOverlap = true
enterTransition = enterWindowTransition(view.getId())
exitTransition = exitWindowTransition(view.getId())
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun enterAnimation() {
if (showAnimation) {
ControlsAnimations.enterAnimation(view).start()
showAnimation = false
}
}
}
}
fun enterAnimation(view: View): Animator {
Log.d(ControlsUiController.TAG, "Enter animation for $view")
view.transitionAlpha = 0.0f
view.alpha = 1.0f
view.translationY = translationY
val alphaAnimator = ObjectAnimator.ofFloat(view, "transitionAlpha", 0.0f, 1.0f).apply {
interpolator = Interpolators.DECELERATE_QUINT
startDelay = ALPHA_ENTER_DELAY
duration = ALPHA_ENTER_DURATION
}
val yAnimator = ObjectAnimator.ofFloat(view, "translationY", 0.0f).apply {
interpolator = Interpolators.DECELERATE_QUINT
startDelay = Y_TRANSLATION_ENTER_DURATION
duration = Y_TRANSLATION_ENTER_DURATION
}
return AnimatorSet().apply {
playTogether(alphaAnimator, yAnimator)
}
}
/**
* Properly handle animations originating from dialogs. Activity transitions require
* transitioning between two activities, so expose this method for dialogs to animate
* on exit.
*/
@JvmStatic
fun exitAnimation(view: View, onEnd: Runnable? = null): Animator {
Log.d(ControlsUiController.TAG, "Exit animation for $view")
val alphaAnimator = ObjectAnimator.ofFloat(view, "transitionAlpha", 0.0f).apply {
interpolator = Interpolators.ACCELERATE
duration = ALPHA_EXIT_DURATION
}
view.translationY = 0.0f
val yAnimator = ObjectAnimator.ofFloat(view, "translationY", -translationY).apply {
interpolator = Interpolators.ACCELERATE
duration = Y_TRANSLATION_EXIT_DURATION
}
return AnimatorSet().apply {
playTogether(alphaAnimator, yAnimator)
onEnd?.let {
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
it.run()
}
})
}
}
}
fun enterWindowTransition(@IdRes id: Int) =
WindowTransition({ view: View -> enterAnimation(view) }).apply {
addTarget(id)
}
fun exitWindowTransition(@IdRes id: Int) =
WindowTransition({ view: View -> exitAnimation(view) }).apply {
addTarget(id)
}
}
/**
* In order to animate, at least one property must be marked on each view that should move.
* Setting "item" is just a flag to indicate that it should move by the animator.
*/
class WindowTransition(
val animator: (view: View) -> Animator
) : Transition() {
override fun captureStartValues(tv: TransitionValues) {
tv.values["item"] = 0.0f
}
override fun captureEndValues(tv: TransitionValues) {
tv.values["item"] = 1.0f
}
override fun createAnimator(
sceneRoot: ViewGroup,
startValues: TransitionValues?,
endValues: TransitionValues?
): Animator? = animator(startValues!!.view)
}

View File

@@ -16,11 +16,12 @@
package com.android.systemui.controls.management package com.android.systemui.controls.management
import android.app.Activity import android.app.ActivityOptions
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.ViewStub import android.view.ViewStub
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
@@ -32,6 +33,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.controller.ControlsControllerImpl import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject import javax.inject.Inject
/** /**
@@ -40,7 +42,7 @@ import javax.inject.Inject
class ControlsEditingActivity @Inject constructor( class ControlsEditingActivity @Inject constructor(
private val controller: ControlsControllerImpl, private val controller: ControlsControllerImpl,
broadcastDispatcher: BroadcastDispatcher broadcastDispatcher: BroadcastDispatcher
) : Activity() { ) : LifecycleActivity() {
companion object { companion object {
private const val TAG = "ControlsEditingActivity" private const val TAG = "ControlsEditingActivity"
@@ -92,6 +94,15 @@ class ControlsEditingActivity @Inject constructor(
private fun bindViews() { private fun bindViews() {
setContentView(R.layout.controls_management) setContentView(R.layout.controls_management)
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
requireViewById<ViewGroup>(R.id.controls_management_root),
window,
intent
)
)
requireViewById<ViewStub>(R.id.stub).apply { requireViewById<ViewStub>(R.id.stub).apply {
layoutResource = R.layout.controls_management_editing layoutResource = R.layout.controls_management_editing
inflate() inflate()
@@ -113,8 +124,8 @@ class ControlsEditingActivity @Inject constructor(
putExtras(this@ControlsEditingActivity.intent) putExtras(this@ControlsEditingActivity.intent)
putExtra(ControlsFavoritingActivity.EXTRA_SINGLE_STRUCTURE, true) putExtra(ControlsFavoritingActivity.EXTRA_SINGLE_STRUCTURE, true)
} }
startActivity(intent) startActivity(intent, ActivityOptions
finish() .makeSceneTransitionAnimation(this@ControlsEditingActivity).toBundle())
} }
} }
@@ -151,26 +162,38 @@ class ControlsEditingActivity @Inject constructor(
val controls = controller.getFavoritesForStructure(component, structure) val controls = controller.getFavoritesForStructure(component, structure)
model = FavoritesModel(component, controls, favoritesModelCallback) model = FavoritesModel(component, controls, favoritesModelCallback)
val elevation = resources.getFloat(R.dimen.control_card_elevation) val elevation = resources.getFloat(R.dimen.control_card_elevation)
val adapter = ControlAdapter(elevation) val recyclerView = requireViewById<RecyclerView>(R.id.list)
val recycler = requireViewById<RecyclerView>(R.id.list) recyclerView.alpha = 0.0f
val adapter = ControlAdapter(elevation).apply {
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
var hasAnimated = false
override fun onChanged() {
if (!hasAnimated) {
hasAnimated = true
ControlsAnimations.enterAnimation(recyclerView).start()
}
}
})
}
val margin = resources val margin = resources
.getDimensionPixelSize(R.dimen.controls_card_margin) .getDimensionPixelSize(R.dimen.controls_card_margin)
val itemDecorator = MarginItemDecorator(margin, margin) val itemDecorator = MarginItemDecorator(margin, margin)
recycler.apply { recyclerView.apply {
this.adapter = adapter this.adapter = adapter
layoutManager = GridLayoutManager(recycler.context, 2).apply { layoutManager = GridLayoutManager(recyclerView.context, 2).apply {
spanSizeLookup = adapter.spanSizeLookup spanSizeLookup = adapter.spanSizeLookup
} }
addItemDecoration(itemDecorator) addItemDecoration(itemDecorator)
} }
adapter.changeModel(model) adapter.changeModel(model)
model.attachAdapter(adapter) model.attachAdapter(adapter)
ItemTouchHelper(model.itemTouchHelperCallback).attachToRecyclerView(recycler) ItemTouchHelper(model.itemTouchHelperCallback).attachToRecyclerView(recyclerView)
} }
override fun onDestroy() { override fun onDestroy() {
currentUserTracker.stopTracking() currentUserTracker.stopTracking()
super.onDestroy() super.onDestroy()
} }
} }

View File

@@ -16,7 +16,7 @@
package com.android.systemui.controls.management package com.android.systemui.controls.management
import android.app.Activity import android.app.ActivityOptions
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
@@ -41,6 +41,7 @@ import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.util.LifecycleActivity
import java.text.Collator import java.text.Collator
import java.util.concurrent.Executor import java.util.concurrent.Executor
import java.util.function.Consumer import java.util.function.Consumer
@@ -51,7 +52,7 @@ class ControlsFavoritingActivity @Inject constructor(
private val controller: ControlsControllerImpl, private val controller: ControlsControllerImpl,
private val listingController: ControlsListingController, private val listingController: ControlsListingController,
broadcastDispatcher: BroadcastDispatcher broadcastDispatcher: BroadcastDispatcher
) : Activity() { ) : LifecycleActivity() {
companion object { companion object {
private const val TAG = "ControlsFavoritingActivity" private const val TAG = "ControlsFavoritingActivity"
@@ -115,6 +116,7 @@ class ControlsFavoritingActivity @Inject constructor(
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val collator = Collator.getInstance(resources.configuration.locales[0]) val collator = Collator.getInstance(resources.configuration.locales[0])
comparator = compareBy(collator) { it.structureName } comparator = compareBy(collator) { it.structureName }
appName = intent.getCharSequenceExtra(EXTRA_APP) appName = intent.getCharSequenceExtra(EXTRA_APP)
@@ -174,12 +176,17 @@ class ControlsFavoritingActivity @Inject constructor(
pageIndicator.setLocation(0f) pageIndicator.setLocation(0f)
pageIndicator.visibility = pageIndicator.visibility =
if (listOfStructures.size > 1) View.VISIBLE else View.GONE if (listOfStructures.size > 1) View.VISIBLE else View.GONE
ControlsAnimations.enterAnimation(pageIndicator).start()
ControlsAnimations.enterAnimation(structurePager).start()
} }
}) })
} }
} }
private fun setUpPager() { private fun setUpPager() {
structurePager.alpha = 0.0f
pageIndicator.alpha = 0.0f
structurePager.apply { structurePager.apply {
adapter = StructureAdapter(emptyList()) adapter = StructureAdapter(emptyList())
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
@@ -203,6 +210,15 @@ class ControlsFavoritingActivity @Inject constructor(
private fun bindViews() { private fun bindViews() {
setContentView(R.layout.controls_management) setContentView(R.layout.controls_management)
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
requireViewById<ViewGroup>(R.id.controls_management_root),
window,
intent
)
)
requireViewById<ViewStub>(R.id.stub).apply { requireViewById<ViewStub>(R.id.stub).apply {
layoutResource = R.layout.controls_management_favorites layoutResource = R.layout.controls_management_favorites
inflate() inflate()
@@ -278,7 +294,8 @@ class ControlsFavoritingActivity @Inject constructor(
val i = Intent() val i = Intent()
i.setComponent( i.setComponent(
ComponentName(context, ControlsProviderSelectorActivity::class.java)) ComponentName(context, ControlsProviderSelectorActivity::class.java))
context.startActivity(i) startActivity(i, ActivityOptions
.makeSceneTransitionAnimation(this@ControlsFavoritingActivity).toBundle())
} }
} }

View File

@@ -16,15 +16,18 @@
package com.android.systemui.controls.management package com.android.systemui.controls.management
import android.app.ActivityOptions
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.ViewStub import android.view.ViewStub
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.ControlsController
@@ -66,12 +69,23 @@ class ControlsProviderSelectorActivity @Inject constructor(
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.controls_management) setContentView(R.layout.controls_management)
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
requireViewById<ViewGroup>(R.id.controls_management_root),
window,
intent
)
)
requireViewById<ViewStub>(R.id.stub).apply { requireViewById<ViewStub>(R.id.stub).apply {
layoutResource = R.layout.controls_management_apps layoutResource = R.layout.controls_management_apps
inflate() inflate()
} }
recyclerView = requireViewById(R.id.list) recyclerView = requireViewById(R.id.list)
recyclerView.alpha = 0.0f
recyclerView.layoutManager = LinearLayoutManager(applicationContext)
recyclerView.adapter = AppAdapter( recyclerView.adapter = AppAdapter(
backExecutor, backExecutor,
executor, executor,
@@ -80,11 +94,21 @@ class ControlsProviderSelectorActivity @Inject constructor(
LayoutInflater.from(this), LayoutInflater.from(this),
::launchFavoritingActivity, ::launchFavoritingActivity,
FavoritesRenderer(resources, controlsController::countFavoritesForComponent), FavoritesRenderer(resources, controlsController::countFavoritesForComponent),
resources) resources).apply {
recyclerView.layoutManager = LinearLayoutManager(applicationContext) registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
var hasAnimated = false
override fun onChanged() {
if (!hasAnimated) {
hasAnimated = true
ControlsAnimations.enterAnimation(recyclerView).start()
}
}
})
}
requireViewById<TextView>(R.id.title).text = requireViewById<TextView>(R.id.title).apply {
resources.getText(R.string.controls_providers_title) text = resources.getText(R.string.controls_providers_title)
}
requireViewById<Button>(R.id.done).setOnClickListener { requireViewById<Button>(R.id.done).setOnClickListener {
this@ControlsProviderSelectorActivity.finishAffinity() this@ControlsProviderSelectorActivity.finishAffinity()
@@ -98,7 +122,7 @@ class ControlsProviderSelectorActivity @Inject constructor(
* @param component a component name for a [ControlsProviderService] * @param component a component name for a [ControlsProviderService]
*/ */
fun launchFavoritingActivity(component: ComponentName?) { fun launchFavoritingActivity(component: ComponentName?) {
backExecutor.execute { executor.execute {
component?.let { component?.let {
val intent = Intent(applicationContext, ControlsFavoritingActivity::class.java) val intent = Intent(applicationContext, ControlsFavoritingActivity::class.java)
.apply { .apply {
@@ -107,7 +131,7 @@ class ControlsProviderSelectorActivity @Inject constructor(
putExtra(Intent.EXTRA_COMPONENT_NAME, it) putExtra(Intent.EXTRA_COMPONENT_NAME, it)
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
} }
startActivity(intent) startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
} }
} }
} }

View File

@@ -26,9 +26,10 @@ interface ControlsUiController {
companion object { companion object {
public const val TAG = "ControlsUiController" public const val TAG = "ControlsUiController"
public const val EXTRA_ANIMATE = "extra_animate"
} }
fun show(parent: ViewGroup) fun show(parent: ViewGroup, dismissGlobalActions: Runnable)
fun hide() fun hide()
fun onRefreshState(componentName: ComponentName, controls: List<Control>) fun onRefreshState(componentName: ComponentName, controls: List<Control>)
fun onActionResponse( fun onActionResponse(

View File

@@ -85,7 +85,7 @@ class ControlsUiControllerImpl @Inject constructor (
private const val PREF_STRUCTURE = "controls_structure" private const val PREF_STRUCTURE = "controls_structure"
private const val USE_PANELS = "systemui.controls_use_panel" private const val USE_PANELS = "systemui.controls_use_panel"
private const val FADE_IN_MILLIS = 225L private const val FADE_IN_MILLIS = 200L
private val EMPTY_COMPONENT = ComponentName("", "") private val EMPTY_COMPONENT = ComponentName("", "")
private val EMPTY_STRUCTURE = StructureInfo( private val EMPTY_STRUCTURE = StructureInfo(
@@ -104,6 +104,7 @@ class ControlsUiControllerImpl @Inject constructor (
private var popup: ListPopupWindow? = null private var popup: ListPopupWindow? = null
private var activeDialog: Dialog? = null private var activeDialog: Dialog? = null
private var hidden = true private var hidden = true
private lateinit var dismissGlobalActions: Runnable
override val available: Boolean override val available: Boolean
get() = controlsController.get().available get() = controlsController.get().available
@@ -134,9 +135,10 @@ class ControlsUiControllerImpl @Inject constructor (
} }
} }
override fun show(parent: ViewGroup) { override fun show(parent: ViewGroup, dismissGlobalActions: Runnable) {
Log.d(ControlsUiController.TAG, "show()") Log.d(ControlsUiController.TAG, "show()")
this.parent = parent this.parent = parent
this.dismissGlobalActions = dismissGlobalActions
hidden = false hidden = false
allStructures = controlsController.get().getFavorites() allStructures = controlsController.get().getFavorites()
@@ -169,7 +171,7 @@ class ControlsUiControllerImpl @Inject constructor (
fadeAnim.setDuration(FADE_IN_MILLIS) fadeAnim.setDuration(FADE_IN_MILLIS)
fadeAnim.addListener(object : AnimatorListenerAdapter() { fadeAnim.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) { override fun onAnimationEnd(animation: Animator) {
show(parent) show(parent, dismissGlobalActions)
val showAnim = ObjectAnimator.ofFloat(parent, "alpha", 0.0f, 1.0f) val showAnim = ObjectAnimator.ofFloat(parent, "alpha", 0.0f, 1.0f)
showAnim.setInterpolator(DecelerateInterpolator(1.0f)) showAnim.setInterpolator(DecelerateInterpolator(1.0f))
showAnim.setDuration(FADE_IN_MILLIS) showAnim.setDuration(FADE_IN_MILLIS)
@@ -256,9 +258,10 @@ class ControlsUiControllerImpl @Inject constructor (
} }
private fun startActivity(context: Context, intent: Intent) { private fun startActivity(context: Context, intent: Intent) {
val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) // Force animations when transitioning from a dialog to an activity
context.sendBroadcast(closeDialog) intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
context.startActivity(intent) context.startActivity(intent)
dismissGlobalActions.run()
} }
private fun showControlsView(items: List<SelectionItem>) { private fun showControlsView(items: List<SelectionItem>) {

View File

@@ -110,6 +110,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.controls.ControlsServiceInfo; import com.android.systemui.controls.ControlsServiceInfo;
import com.android.systemui.controls.controller.ControlsController; import com.android.systemui.controls.controller.ControlsController;
import com.android.systemui.controls.management.ControlsAnimations;
import com.android.systemui.controls.management.ControlsListingController; import com.android.systemui.controls.management.ControlsListingController;
import com.android.systemui.controls.ui.ControlsUiController; import com.android.systemui.controls.ui.ControlsUiController;
import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Background;
@@ -1815,7 +1816,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
case MESSAGE_DISMISS: case MESSAGE_DISMISS:
if (mDialog != null) { if (mDialog != null) {
if (SYSTEM_DIALOG_REASON_DREAM.equals(msg.obj)) { if (SYSTEM_DIALOG_REASON_DREAM.equals(msg.obj)) {
mDialog.dismissImmediately(); mDialog.completeDismiss();
} else { } else {
mDialog.dismiss(); mDialog.dismiss();
} }
@@ -2200,50 +2201,55 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return WindowInsets.CONSUMED; return WindowInsets.CONSUMED;
}); });
if (mControlsUiController != null) { if (mControlsUiController != null) {
mControlsUiController.show(mControlsView); mControlsUiController.show(mControlsView, this::dismissForControlsActivity);
} }
} }
@Override @Override
public void dismiss() { public void dismiss() {
dismissWithAnimation(() -> {
mGlobalActionsLayout.setTranslationX(0);
mGlobalActionsLayout.setTranslationY(0);
mGlobalActionsLayout.setAlpha(1);
mGlobalActionsLayout.animate()
.alpha(0)
.translationX(mGlobalActionsLayout.getAnimationOffsetX())
.translationY(mGlobalActionsLayout.getAnimationOffsetY())
.setDuration(550)
.withEndAction(this::completeDismiss)
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
float animatedValue = 1f - animation.getAnimatedFraction();
int alpha = (int) (animatedValue * mScrimAlpha * 255);
mBackgroundDrawable.setAlpha(alpha);
mDepthController.updateGlobalDialogVisibility(animatedValue,
mGlobalActionsLayout);
})
.start();
});
}
private void dismissForControlsActivity() {
dismissWithAnimation(() -> {
ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView();
ControlsAnimations.exitAnimation(root, this::completeDismiss).start();
});
}
void dismissWithAnimation(Runnable animation) {
if (!mShowing) { if (!mShowing) {
return; return;
} }
mShowing = false; mShowing = false;
if (mControlsUiController != null) mControlsUiController.hide(); animation.run();
mGlobalActionsLayout.setTranslationX(0);
mGlobalActionsLayout.setTranslationY(0);
mGlobalActionsLayout.setAlpha(1);
mGlobalActionsLayout.animate()
.alpha(0)
.translationX(mGlobalActionsLayout.getAnimationOffsetX())
.translationY(mGlobalActionsLayout.getAnimationOffsetY())
.setDuration(550)
.withEndAction(this::completeDismiss)
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
float animatedValue = 1f - animation.getAnimatedFraction();
int alpha = (int) (animatedValue * mScrimAlpha * 255);
mBackgroundDrawable.setAlpha(alpha);
mDepthController.updateGlobalDialogVisibility(animatedValue,
mGlobalActionsLayout);
})
.start();
dismissPanel();
dismissOverflow();
resetOrientation();
}
void dismissImmediately() {
mShowing = false;
if (mControlsUiController != null) mControlsUiController.hide();
dismissPanel();
dismissOverflow();
resetOrientation();
completeDismiss();
} }
private void completeDismiss() { private void completeDismiss() {
mShowing = false;
resetOrientation();
dismissPanel();
dismissOverflow();
if (mControlsUiController != null) mControlsUiController.hide();
mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi); mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
mDepthController.updateGlobalDialogVisibility(0, null /* view */); mDepthController.updateGlobalDialogVisibility(0, null /* view */);
super.dismiss(); super.dismiss();
@@ -2304,7 +2310,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
initializeLayout(); initializeLayout();
mGlobalActionsLayout.updateList(); mGlobalActionsLayout.updateList();
if (mControlsUiController != null) { if (mControlsUiController != null) {
mControlsUiController.show(mControlsView); mControlsUiController.show(mControlsView, this::dismissForControlsActivity);
} }
} }
@@ -2343,10 +2349,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
&& mControlsUiController.getAvailable() && mControlsUiController.getAvailable()
&& !mControlsServiceInfos.isEmpty(); && !mControlsServiceInfos.isEmpty();
} }
// TODO: Remove legacy layout XML and classes. // TODO: Remove legacy layout XML and classes.
protected boolean shouldUseControlsLayout() { protected boolean shouldUseControlsLayout() {
// always use new controls layout // always use new controls layout
return true; return true;
} }
} }