diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index 38af57260f..9fb5b7b061 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -433,3 +433,14 @@ flag { description: "Enables tracking active gesture logs in ProtoLog" bug: "293182501" } + + +flag { + name: "coordinate_workspace_scale" + namespace: "launcher" + description: "Ensure that the workspace and hotseat scale doesn't conflict and transitions smoothly between launching and closing apps" + bug: "366403487" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml index 28bd69a8cb..0848ddd48e 100644 --- a/quickstep/res/values-am/strings.xml +++ b/quickstep/res/values-am/strings.xml @@ -139,8 +139,7 @@ "ሁልጊዜ የተግባር አሞሌ ያሳዩ" "የአሰሳ ሁነታን ይለውጡ" "የተግባር አሞሌ አካፋይ" - - + "የተግባር አሞሌ ትርፍ ፍሰት" "ወደ ላይ/ግራ ይውሰዱ" "ወደ ታች/ቀኝ ይውሰዱ" "{count,plural, =1{ተጨማሪ መተግበሪያ}one{ተጨማሪ መተግበሪያ}other{ተጨማሪ መተግበሪያዎች}}" diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index f08cf835b5..aa16f3c353 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -139,8 +139,7 @@ "Uvek prikazuj traku zadataka" "Promeni režim navigacije" "Razdelnik trake zadataka" - - + "Preklopna traka zadataka" "Premesti gore levo" "Premesti dole desno" "{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}" diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml index fb5b55698d..4dcfe62c1c 100644 --- a/quickstep/res/values-be/strings.xml +++ b/quickstep/res/values-be/strings.xml @@ -139,8 +139,7 @@ "Заўсёды паказваць панэль задач" "Змяніць рэжым навігацыі" "Раздзяляльнік панэлі задач" - - + "Меню з пашырэннем панэлі задач" "Перамясціць уверх/улева" "Перамясціць уніз/управа" "{count,plural, =1{даступная праграма}one{даступная праграма}few{даступныя праграмы}many{даступных праграм}other{даступнай праграмы}}" diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index 6588dd060c..3357a6e7eb 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -139,8 +139,7 @@ "Uvijek prikaži traku zadataka" "Promijeni način navigacije" "Razdjelnik trake zadataka" - - + "Dodatni izbornik trake sa zadacima" "Premjesti gore lijevo" "Premjesti dolje desno" "{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 527bdc30d3..d8bbc55815 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -139,8 +139,7 @@ "Barra de tareas visible" "Cambiar el modo de navegación" "Divisor de Barra de Tareas" - - + "Barra de tareas ampliada" "Mover arriba/a la izquierda" "Mover abajo/a la derecha" "{count,plural, =1{aplicación más}other{aplicaciones más}}" diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index a2bf69159f..2514aa157f 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -139,8 +139,7 @@ "Uvijek prikaži traku zadataka" "Promijeni način navigacije" "Razdjelnik trake sa zadacima" - - + "Dodatni izbornik trake sa zadacima" "Premjesti gore/lijevo" "Premjesti dolje/desno" "{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}" diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index 274e1da362..3aec0ceb32 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -139,8 +139,7 @@ "Alltaf sýna forritastiku" "Breyta leiðsagnarstillingu" "Skipting forritastiku" - - + "Yfirflæði á forritastiku" "Færa efst/til vinstri" "Færa neðst/til hægri" "{count,plural, =1{forrit til viðbótar}one{forrit til viðbótar}other{forrit til viðbótar}}" diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml index 0cff4c1f53..28b7746b43 100644 --- a/quickstep/res/values-ja/strings.xml +++ b/quickstep/res/values-ja/strings.xml @@ -139,8 +139,7 @@ "常にタスクバーを表示する" "ナビゲーション モードを変更" "タスクバーの区切り" - - + "タスクバーのオーバフロー" "上 / 左に移動" "下 / 右に移動" "{count,plural, =1{個のその他のアプリ}other{個のその他のアプリ}}" diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml index efff980290..d84d53e576 100644 --- a/quickstep/res/values-ka/strings.xml +++ b/quickstep/res/values-ka/strings.xml @@ -139,8 +139,7 @@ "ამოცანათა ზოლის მუდამ ჩვენება" "შეცვალეთ ნავიგაციის რეჟიმი" "ამოცანათა ზოლის გამყოფი" - - + "ამოცანათა ზოლის გადავსება" "ზემოთ/მარცხნივ გადატანა" "ქვემოთ/მარჯვნივ გადატანა" "{count,plural, =1{სხვა აპი}other{სხვა აპი}}" diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 193b606307..4cdbfc4d94 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -139,8 +139,7 @@ "Тапсырма жолағын үнемі көрсету" "Навигация режимін өзгерту" "Тапсырмалар жолағын бөлгіш" - - + "\"Тапсырмалар жолағы\" қосымша мәзірі" "Жоғары/солға жылжыту" "Төмен/оңға жылжыту" "{count,plural, =1{қосымша қолданба}other{қосымша қолданба}}" diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index aadfd673cd..5cf1b92737 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -139,8 +139,7 @@ "បង្ហាញរបារកិច្ចការជានិច្ច" "ប្ដូរ​មុខងាររុករក" "បន្ទាត់​ខណ្ឌចែករបារកិច្ចការ" - - + "ម៉ឺនុយបន្ថែមរបារកិច្ចការ" "ផ្លាស់ទីទៅខាងលើ/ឆ្វេង" "ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ" "{count,plural, =1{កម្មវិធីច្រើនទៀត}other{កម្មវិធីច្រើនទៀត}}" diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index 8eba2a5215..faf5675762 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -139,8 +139,7 @@ "Такта ар дайым көрүнсүн" "Өтүү режимин өзгөртүү" "Тапшырмалар панелин бөлгүч" - - + "\"Тапшырмалар панели\" кошумча менюсу" "Жогорку/сол бурчка жылдыруу" "Төмөнкү/оң бурчка жылдыруу" "{count,plural, =1{колдонмо бар}other{колдонмо бар}}" diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml index 1c20015f7e..a95249b508 100644 --- a/quickstep/res/values-lt/strings.xml +++ b/quickstep/res/values-lt/strings.xml @@ -139,8 +139,7 @@ "Visada rodyti užduočių juostą" "Keisti naršymo režimą" "Užduočių juostos daliklis" - - + "Užduočių juostos perpildymas" "Perkelti aukštyn, kairėn" "Perkelti žemyn, dešinėn" "{count,plural, =1{papildoma programa}one{papildoma programa}few{papildomos programos}many{papildomos programos}other{papildomų programų}}" diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml index bb5c01480a..c15a241bdb 100644 --- a/quickstep/res/values-ml/strings.xml +++ b/quickstep/res/values-ml/strings.xml @@ -139,8 +139,7 @@ "ടാസ്‌ക്ബാർ എപ്പോഴും കാണിക്കൂ" "നാവിഗേഷൻ മോഡ് മാറ്റുക" "ടാസ്‌ക്ബാർ ഡിവൈഡർ" - - + "ടാസ്‌ക്ബാർ ഓവർഫ്ലോ" "മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക" "താഴേക്കോ വലത്തേക്കോ നീക്കുക" "{count,plural, =1{കൂടുതൽ ആപ്പ്}other{കൂടുതൽ ആപ്പുകൾ}}" diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml index 9bdc9734a5..a1f19a95a4 100644 --- a/quickstep/res/values-ms/strings.xml +++ b/quickstep/res/values-ms/strings.xml @@ -139,8 +139,7 @@ "Papar Bar Tugas selalu" "Tukar mod navigasi" "Pembahagi Bar Tugas" - - + "Limpahan Bar Tugas" "Alihkan ke atas/kiri" "Alihkan ke bawah/kanan" "{count,plural, =1{apl lagi}other{apl lagi}}" diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index 4c9747f351..a2d4d325b3 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -139,8 +139,7 @@ "टास्कबार सधैँ देखाउनुहोस्" "नेभिगेसन मोड बदल्नुहोस्" "टास्कबार डिभाइडर" - - + "टास्कबार ओभरफ्लो" "सिरान/बायाँतिर सार्नुहोस्" "फेद/दायाँतिर सार्नुहोस्" "{count,plural, =1{थप एप}other{थप एपहरू}}" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 5ad32afaf1..2167875719 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -139,8 +139,7 @@ "Ver sempre Barra de tarefas" "Alterar modo de navegação" "Divisor da Barra de tarefas" - - + "Menu adicional da Barra de tarefas" "Mover para a parte superior esquerda" "Mover para a part superior direita" "{count,plural, =1{outra app}other{outras apps}}" diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index 28b3414715..9309810cdf 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -139,8 +139,7 @@ "Sempre mostrar a Barra de tarefas" "Mudar o modo de navegação" "Separador da Barra de tarefas" - - + "Barra de tarefas flutuante" "Mover para cima/para a esquerda" "Mover para baixo/para a direita" "{count,plural, =1{outro app}one{outro app}other{outros apps}}" diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml index 20f579dbd5..76c4e1f646 100644 --- a/quickstep/res/values-ru/strings.xml +++ b/quickstep/res/values-ru/strings.xml @@ -139,8 +139,7 @@ "Всегда показывать панель задач" "Изменить режим навигации" "Разделитель панели задач" - - + "Дополнительное меню панели задач" "Переместить вверх или влево" "Переместить вниз или вправо" "{count,plural, =1{дополнительное приложение}one{дополнительное приложение}few{дополнительных приложения}many{дополнительных приложений}other{дополнительного приложения}}" diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml index dd9739c11d..0953b38bd1 100644 --- a/quickstep/res/values-si/strings.xml +++ b/quickstep/res/values-si/strings.xml @@ -139,8 +139,7 @@ "සෑම විටම කාර්ය තීරුව පෙන්වන්න" "සංචාලන ප්‍රකාරය වෙනස් කරන්න" "කාර්ය තීරු බෙදනය" - - + "කාර්ය තීරුව පිටාර යාම" "ඉහළ/වම වෙත ගෙන යන්න" "පහළ/දකුණ වෙත ගෙන යන්න" "{count,plural, =1{තව යෙදුම}one{තවත් යෙදුම්}other{තවත් යෙදුම්}}" diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index 9394a5a34c..94de1e0567 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -139,8 +139,7 @@ "Stalen prikaz oprav. vrstice" "Spreminjanje načina navigacije" "Razdelilnik opravilne vrstice" - - + "Oblaček opravilne vrstice z dodatnimi elementi" "Premakni na vrh/levo" "Premakni na dno/desno" "{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}two{dodatni aplikaciji}few{dodatne aplikacije}other{dodatnih aplikacij}}" diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index a7760b9735..d6e5d03cee 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -139,8 +139,7 @@ "Увек приказуј траку задатака" "Промени режим навигације" "Разделник траке задатака" - - + "Преклопна трака задатака" "Премести горе лево" "Премести доле десно" "{count,plural, =1{додатна апликација}one{додатна апликација}few{додатне апликације}other{додатних апликација}}" diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index d4c3a695c0..bba98c6fb6 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -139,8 +139,7 @@ "Visa alltid aktivitetsfältet" "Ändra navigeringsläge" "Avdelare för aktivitetsfältet" - - + "Fler alternativ för aktivitetsfältet" "Flytta högst upp/till vänster" "Flytta längst ned/till höger" "{count,plural, =1{app till}other{appar till}}" diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 86161b4900..91ef8463a9 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -139,8 +139,7 @@ "టాస్క్‌బార్‌ను నిరంతరం చూపండి" "నావిగేషన్ మోడ్‌ను మార్చండి" "టాస్క్‌బార్ డివైడర్" - - + "టాస్క్‌బార్ ఓవర్‌ఫ్లో" "ఎగువ/ఎడమ వైపునకు తరలించండి" "దిగువ/కుడి వైపునకు తరలించండి" "{count,plural, =1{మరో యాప్‌}other{మరిన్ని యాప్‌లు}}" diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 4b43bd2c4d..18337d3991 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -116,6 +116,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; +import com.android.app.animation.Animations; import com.android.internal.jank.Cuj; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory; @@ -574,23 +575,45 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener } else { List viewsToAnimate = new ArrayList<>(); Workspace workspace = mLauncher.getWorkspace(); - workspace.forEachVisiblePage( - view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets())); + if (Flags.coordinateWorkspaceScale()) { + viewsToAnimate.add(workspace); + } else { + workspace.forEachVisiblePage( + view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets())); + } + Hotseat hotseat = mLauncher.getHotseat(); // Do not scale hotseat as a whole when taskbar is present, and scale QSB only if it's // not inline. if (mDeviceProfile.isTaskbarPresent) { if (!mDeviceProfile.isQsbInline) { - viewsToAnimate.add(mLauncher.getHotseat().getQsb()); + viewsToAnimate.add(hotseat.getQsb()); } } else { - viewsToAnimate.add(mLauncher.getHotseat()); + viewsToAnimate.add(hotseat); } viewsToAnimate.forEach(view -> { view.setLayerType(View.LAYER_TYPE_HARDWARE, null); - ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scales) + float[] scale = scales; + if (Flags.coordinateWorkspaceScale()) { + // Start the animation from the current value, instead of assuming the views are + // in their resting state, so interrupted animations merge seamlessly. + // TODO(b/367591368): ideally these animations would be refactored to be + // controlled centrally so each instances doesn't need to care about this + // coordination. + scale = new float[]{view.getScaleX(), scales[1]}; + + // Cancel any ongoing animations. This is necessary to avoid a conflict between + // e.g. the unfinished animation triggered when closing an app back to Home and + // this animation caused by a launch. + Animations.Companion.cancelOngoingAnimation(view); + // Make sure to cache the current animation, so it can be properly interrupted. + Animations.Companion.setOngoingAnimation(view, launcherAnimator); + } + + ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scale) .setDuration(CONTENT_SCALE_DURATION); scaleAnim.setInterpolator(DECELERATE_1_5); launcherAnimator.play(scaleAnim); @@ -600,6 +623,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener viewsToAnimate.forEach(view -> { SCALE_PROPERTY.set(view, 1f); view.setLayerType(View.LAYER_TYPE_NONE, null); + + if (Flags.coordinateWorkspaceScale()) { + // Reset the cached animation. + Animations.Companion.setOngoingAnimation(view, null /* animation */); + } }); mLauncher.resumeExpensiveViewUpdates(); }; diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt index 2b77dec462..b8c1c7f1d7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt @@ -36,4 +36,7 @@ interface BubbleBarFlyoutPositioner { /** The size of the flyout when collapsed. */ val collapsedSize: Float + + /** The color of the flyout when collapsed. */ + val collapsedColor: Int } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt index 8884b646b7..6723f57dd5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt @@ -20,13 +20,18 @@ import android.content.Context import android.content.res.Configuration import android.graphics.Canvas import android.graphics.Color +import android.graphics.Outline import android.graphics.Paint import android.graphics.Path import android.graphics.PointF +import android.graphics.RectF import android.view.LayoutInflater +import android.view.View +import android.view.ViewOutlineProvider import android.widget.ImageView import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.animation.ArgbEvaluator import com.android.launcher3.R import com.android.launcher3.popup.RoundedArrowDrawable @@ -37,6 +42,8 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly private companion object { // the minimum progress of the expansion animation before the triangle is made visible. const val MIN_EXPANSION_PROGRESS_FOR_TRIANGLE = 0.1f + // the minimum progress of the expansion animation before the content starts fading in. + const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f } private val sender: TextView by @@ -85,8 +92,11 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_max_width) } + /** The bounds of the background rect. */ + private val backgroundRect = RectF() private val cornerRadius: Float private val triangle: Path = Path() + private val triangleOutline = Outline() private var backgroundColor = Color.BLACK /** Represents the progress of the expansion animation. 0 when collapsed. 1 when expanded. */ private var expansionProgress = 0f @@ -96,6 +106,20 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly private var collapsedSize = 0f /** The corner radius of the flyout when it's collapsed. */ private var collapsedCornerRadius = 0f + /** The color of the flyout when collapsed. */ + private var collapsedColor = 0 + + /** The corner radius of the background according to the progress of the animation. */ + private val currentCornerRadius + get() = collapsedCornerRadius + (cornerRadius - collapsedCornerRadius) * expansionProgress + + /** Translation X of the background. */ + private val backgroundRectTx + get() = translationToCollapsedPosition.x * (1 - expansionProgress) + + /** Translation Y of the background. */ + private val backgroundRectTy + get() = translationToCollapsedPosition.y * (1 - expansionProgress) /** * The paint used to draw the background, whose color changes as the flyout transitions to the @@ -111,7 +135,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly ta.recycle() setWillNotDraw(false) - clipChildren = false + clipChildren = true clipToPadding = false val padding = context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding) @@ -126,12 +150,24 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly triangleRadius.toFloat(), triangle, ) + triangleOutline.setPath(triangle) + + outlineProvider = + object : ViewOutlineProvider() { + override fun getOutline(view: View, outline: Outline) { + this@BubbleBarFlyoutView.getOutline(outline) + } + } + clipToOutline = true applyConfigurationColors(resources.configuration) } /** Sets the data for the flyout and starts playing the expand animation. */ fun showFromCollapsed(flyoutMessage: BubbleBarFlyoutMessage, expandAnimation: () -> Unit) { + avatar.alpha = 0f + sender.alpha = 0f + message.alpha = 0f setData(flyoutMessage) val txToCollapsedPosition = if (positioner.isOnLeft) { @@ -145,6 +181,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly collapsedSize = positioner.collapsedSize collapsedCornerRadius = collapsedSize / 2 + collapsedColor = positioner.collapsedColor // post the request to start the expand animation to the looper so the view can measure // itself @@ -189,42 +226,64 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly /** Updates the flyout view with the progress of the animation. */ fun updateExpansionProgress(fraction: Float) { expansionProgress = fraction + + updateTranslationForAnimation(message) + updateTranslationForAnimation(sender) + updateTranslationForAnimation(avatar) + + // start fading in the content only after we're past the threshold + val alpha = + ((expansionProgress - MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA) / + (1f - MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA)) + .coerceIn(0f, 1f) + sender.alpha = alpha + message.alpha = alpha + avatar.alpha = alpha + invalidate() } override fun onDraw(canvas: Canvas) { // interpolate the width, height, corner radius and translation based on the progress of the - // animation + // animation. + // the background is drawn from the bottom left corner to the top right corner if we're + // positioned on the left, and from the bottom right corner to the top left if we're + // positioned on the right. + // the current width of the background rect according to the progress of the animation val currentWidth = collapsedSize + (width - collapsedSize) * expansionProgress val rectBottom = height - triangleHeight + triangleOverlap val currentHeight = collapsedSize + (rectBottom - collapsedSize) * expansionProgress - val currentCornerRadius = - collapsedCornerRadius + (cornerRadius - collapsedCornerRadius) * expansionProgress - val tx = translationToCollapsedPosition.x * (1 - expansionProgress) - val ty = translationToCollapsedPosition.y * (1 - expansionProgress) - canvas.save() - canvas.translate(tx, ty) - // draw the background starting from the bottom left if we're positioned left, or the bottom - // right if we're positioned right. - canvas.drawRoundRect( + backgroundRect.set( if (positioner.isOnLeft) 0f else width.toFloat() - currentWidth, height.toFloat() - triangleHeight + triangleOverlap - currentHeight, if (positioner.isOnLeft) currentWidth else width.toFloat(), height.toFloat() - triangleHeight + triangleOverlap, + ) + + backgroundPaint.color = + ArgbEvaluator.getInstance().evaluate(expansionProgress, collapsedColor, backgroundColor) + + canvas.save() + canvas.translate(backgroundRectTx, backgroundRectTy) + // draw the background starting from the bottom left if we're positioned left, or the bottom + // right if we're positioned right. + canvas.drawRoundRect( + backgroundRect, currentCornerRadius, currentCornerRadius, backgroundPaint, ) if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) { - drawTriangle(canvas, currentCornerRadius) + drawTriangle(canvas) } canvas.restore() + invalidateOutline() super.onDraw(canvas) } - private fun drawTriangle(canvas: Canvas, currentCornerRadius: Float) { + private fun drawTriangle(canvas: Canvas) { canvas.save() val triangleX = if (positioner.isOnLeft) { @@ -237,9 +296,38 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly val triangleY = height - triangleHeight - 0.5f * triangleHeight * (1 - expansionProgress) canvas.translate(triangleX, triangleY) canvas.drawPath(triangle, backgroundPaint) + triangleOutline.setPath(triangle) + triangleOutline.offset(triangleX.toInt(), triangleY.toInt()) canvas.restore() } + private fun getOutline(outline: Outline) { + val path = Path() + path.addRoundRect( + backgroundRect, + currentCornerRadius, + currentCornerRadius, + Path.Direction.CW, + ) + if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) { + path.addPath(triangleOutline.mPath) + } + outline.setPath(path) + outline.offset(backgroundRectTx.toInt(), backgroundRectTy.toInt()) + } + + private fun updateTranslationForAnimation(view: View) { + val tx = + if (positioner.isOnLeft) { + translationToCollapsedPosition.x - view.left + } else { + width - view.left - translationToCollapsedPosition.x + } + val ty = height - view.top + translationToCollapsedPosition.y + view.translationX = tx * (1f - expansionProgress) + view.translationY = ty * (1f - expansionProgress) + } + private fun applyConfigurationColors(configuration: Configuration) { val nightModeFlags = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK val isNightModeOn = nightModeFlags == Configuration.UI_MODE_NIGHT_YES diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index bcad478eae..721c831a42 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -21,6 +21,7 @@ import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; +import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile; import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; @@ -31,6 +32,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TR import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; +import static com.android.quickstep.views.RecentsView.DESKTOP_CAROUSEL_DETACH_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; @@ -76,6 +78,10 @@ public abstract class BaseRecentsViewStateController RECENTS_GRID_PROGRESS.set(mRecentsView, state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f); TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, state.showTaskThumbnailSplash() ? 1f : 0f); + if (enableLargeDesktopWindowingTile()) { + DESKTOP_CAROUSEL_DETACH_PROGRESS.set(mRecentsView, + state.detachDesktopCarousel() ? 1f : 0f); + } } @Override @@ -142,6 +148,12 @@ public abstract class BaseRecentsViewStateController setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS, toState.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f, getOverviewInterpolator(fromState, toState)); + + if (enableLargeDesktopWindowingTile()) { + setter.setFloat(mRecentsView, DESKTOP_CAROUSEL_DETACH_PROGRESS, + toState.detachDesktopCarousel() ? 1f : 0f, + getOverviewInterpolator(fromState, toState)); + } } private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index 18d717f096..e87ac2fec6 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -89,6 +89,11 @@ public class BackgroundAppState extends OverviewState { return true; } + @Override + public boolean detachDesktopCarousel() { + return true; + } + @Override protected float getDepthUnchecked(Context context) { if (Launcher.getLauncher(context).areDesktopTasksVisible()) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java index b165cddfb2..c48ba4f11b 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -165,6 +165,11 @@ public class OverviewState extends LauncherState { return deviceProfile.isTablet; } + @Override + public boolean detachDesktopCarousel() { + return false; + } + @Override public boolean disallowTaskbarGlobalDrag() { // Disable global drag in overview diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 83794fbd6c..daac9fb013 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -18,6 +18,7 @@ package com.android.quickstep.fallback; import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; +import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; @@ -26,6 +27,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.fallback.RecentsState.OVERVIEW_SPLIT_SELECT; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; +import static com.android.quickstep.views.RecentsView.DESKTOP_CAROUSEL_DETACH_PROGRESS; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; @@ -116,6 +118,11 @@ public class FallbackRecentsStateController implements StateHandler { private static final int FLAG_LIVE_TILE = BaseState.getFlag(6); private static final int FLAG_RECENTS_VIEW_VISIBLE = BaseState.getFlag(7); private static final int FLAG_TASK_THUMBNAIL_SPLASH = BaseState.getFlag(8); + private static final int FLAG_DETACH_DESKTOP_CAROUSEL = BaseState.getFlag(9); public static final RecentsState DEFAULT = new RecentsState(0, FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID @@ -51,8 +52,8 @@ public class RecentsState implements BaseState { | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE); public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2, FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN - | FLAG_RECENTS_VIEW_VISIBLE - | FLAG_TASK_THUMBNAIL_SPLASH); + | FLAG_RECENTS_VIEW_VISIBLE | FLAG_TASK_THUMBNAIL_SPLASH + | FLAG_DETACH_DESKTOP_CAROUSEL); public static final RecentsState HOME = new RecentsState(3, 0); public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0); public static final RecentsState OVERVIEW_SPLIT_SELECT = new RecentsState(5, @@ -149,6 +150,11 @@ public class RecentsState implements BaseState { return hasFlag(FLAG_TASK_THUMBNAIL_SPLASH); } + @Override + public boolean detachDesktopCarousel() { + return hasFlag(FLAG_DETACH_DESKTOP_CAROUSEL); + } + /** * True if the state has overview panel visible. */ diff --git a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt index e70372fb79..aa0fd88573 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt +++ b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt @@ -83,22 +83,22 @@ class RecentsViewUtils { /** Returns the first [TaskView], with some tasks possibly hidden in the carousel. */ fun getFirstTaskViewInCarousel( - nonRunningTaskCategoryHidden: Boolean, + nonRunningTaskCarouselHidden: Boolean, taskViews: Iterable, runningTaskView: TaskView?, ): TaskView? = taskViews.firstOrNull { - it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) + it.isVisibleInCarousel(runningTaskView, nonRunningTaskCarouselHidden) } /** Returns the last [TaskView], with some tasks possibly hidden in the carousel. */ fun getLastTaskViewInCarousel( - nonRunningTaskCategoryHidden: Boolean, + nonRunningTaskCarouselHidden: Boolean, taskViews: Iterable, runningTaskView: TaskView?, ): TaskView? = taskViews.lastOrNull { - it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) + it.isVisibleInCarousel(runningTaskView, nonRunningTaskCarouselHidden) } /** Returns the current list of [TaskView] children. */ @@ -109,28 +109,33 @@ class RecentsViewUtils { fun applyAttachAlpha( taskViews: Iterable, runningTaskView: TaskView?, - runningTaskTileHidden: Boolean, - nonRunningTaskCategoryHidden: Boolean, + runningTaskAttachAlpha: Float, + nonRunningTaskCarouselHidden: Boolean, ) { taskViews.forEach { taskView -> - val isVisible = - if (taskView == runningTaskView) !runningTaskTileHidden - else taskView.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) - taskView.attachAlpha = if (isVisible) 1f else 0f + taskView.attachAlpha = + if (taskView == runningTaskView) { + runningTaskAttachAlpha + } else { + if (taskView.isVisibleInCarousel(runningTaskView, nonRunningTaskCarouselHidden)) + 1f + else 0f + } } } - private fun TaskView.isVisibleInCarousel( + fun TaskView.isVisibleInCarousel( runningTaskView: TaskView?, - nonRunningTaskCategoryHidden: Boolean, + nonRunningTaskCarouselHidden: Boolean, ): Boolean = - if (!nonRunningTaskCategoryHidden) true - else if (runningTaskView == null) true else getCategory() == runningTaskView.getCategory() + if (!nonRunningTaskCarouselHidden) true + else getCarouselType() == runningTaskView.getCarouselType() - private fun TaskView.getCategory(): TaskViewCategory = - if (this is DesktopTaskView) TaskViewCategory.DESKTOP else TaskViewCategory.FULL_SCREEN + /** Returns the carousel type of the TaskView, and default to fullscreen if it's null. */ + private fun TaskView?.getCarouselType(): TaskViewCarousel = + if (this is DesktopTaskView) TaskViewCarousel.DESKTOP else TaskViewCarousel.FULL_SCREEN - private enum class TaskViewCategory { + private enum class TaskViewCarousel { FULL_SCREEN, DESKTOP, } diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt index f547a7fba1..a94d023076 100644 --- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt +++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt @@ -23,8 +23,10 @@ import android.graphics.RectF import android.view.View import android.view.animation.PathInterpolator import androidx.core.graphics.transform +import com.android.app.animation.Animations import com.android.app.animation.Interpolators import com.android.app.animation.Interpolators.LINEAR +import com.android.launcher3.Flags import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY @@ -44,9 +46,9 @@ import com.android.quickstep.views.RecentsView * the screen outwards radially. This is used in conjunction with the swipe up to home animation. */ class ScalingWorkspaceRevealAnim( - launcher: QuickstepLauncher, + private val launcher: QuickstepLauncher, siblingAnimation: RectFSpringAnim?, - windowTargetRect: RectF? + windowTargetRect: RectF?, ) { companion object { private const val FADE_DURATION_MS = 200L @@ -86,25 +88,40 @@ class ScalingWorkspaceRevealAnim( launcher.workspace.stateTransitionAnimation.setScrim( PropertySetter.NO_ANIM_PROPERTY_SETTER, LauncherState.BACKGROUND_APP, - setupConfig + setupConfig, ) val workspace = launcher.workspace val hotseat = launcher.hotseat + var fromSize = + if (Flags.coordinateWorkspaceScale()) { + // Interrupt the current animation, if any. + Animations.cancelOngoingAnimation(workspace) + Animations.cancelOngoingAnimation(hotseat) + + if (workspace.scaleX != MAX_SIZE) { + workspace.scaleX + } else { + MIN_SIZE + } + } else { + MIN_SIZE + } + // Scale the Workspace and Hotseat around the same pivot. workspace.setPivotToScaleWithSelf(hotseat) animation.addFloat( workspace, WORKSPACE_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE], - MIN_SIZE, + fromSize, MAX_SIZE, SCALE_INTERPOLATOR, ) animation.addFloat( hotseat, HOTSEAT_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE], - MIN_SIZE, + fromSize, MAX_SIZE, SCALE_INTERPOLATOR, ) @@ -116,13 +133,13 @@ class ScalingWorkspaceRevealAnim( animation.setViewAlpha( workspace, MAX_ALPHA, - Interpolators.clampToProgress(LINEAR, 0f, fadeClamp) + Interpolators.clampToProgress(LINEAR, 0f, fadeClamp), ) hotseat.alpha = MIN_ALPHA animation.setViewAlpha( hotseat, MAX_ALPHA, - Interpolators.clampToProgress(LINEAR, 0f, fadeClamp) + Interpolators.clampToProgress(LINEAR, 0f, fadeClamp), ) val transitionConfig = StateAnimationConfig() @@ -137,7 +154,7 @@ class ScalingWorkspaceRevealAnim( launcher.workspace.stateTransitionAnimation.setScrim( animation, LauncherState.NORMAL, - transitionConfig + transitionConfig, ) // To avoid awkward jumps in icon position, we want the sibling animation to always be @@ -164,7 +181,7 @@ class ScalingWorkspaceRevealAnim( 1 / workspace.scaleX, 1 / workspace.scaleY, transformed.centerX(), - transformed.centerY() + transformed.centerY(), ) } ) @@ -183,6 +200,12 @@ class ScalingWorkspaceRevealAnim( Runnable { workspace.setLayerType(View.LAYER_TYPE_NONE, null) hotseat.setLayerType(View.LAYER_TYPE_NONE, null) + + if (Flags.coordinateWorkspaceScale()) { + // Reset the cached animations. + Animations.setOngoingAnimation(workspace, animation = null) + Animations.setOngoingAnimation(hotseat, animation = null) + } } ) ) @@ -193,6 +216,14 @@ class ScalingWorkspaceRevealAnim( } fun start() { - getAnimators().start() + val animators = getAnimators() + if (Flags.coordinateWorkspaceScale()) { + // Make sure to cache the current animation, so it can be properly interrupted. + // TODO(b/367591368): ideally these animations would be refactored to be controlled + // centrally so each instances doesn't need to care about this coordination. + Animations.setOngoingAnimation(launcher.workspace, animators) + Animations.setOngoingAnimation(launcher.hotseat, animators) + } + animators.start() } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index a94f047764..a075c58a00 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -324,20 +324,13 @@ public abstract class RecentsView< new FloatProperty("runningTaskAttachAlpha") { @Override public void setValue(RecentsView recentsView, float v) { - TaskView runningTask = recentsView.getRunningTaskView(); - if (runningTask == null) { - return; - } - runningTask.setAttachAlpha(v); + recentsView.mRunningTaskAttachAlpha = v; + recentsView.applyAttachAlpha(); } @Override public Float get(RecentsView recentsView) { - TaskView runningTask = recentsView.getRunningTaskView(); - if (runningTask == null) { - return null; - } - return runningTask.getAttachAlpha(); + return recentsView.mRunningTaskAttachAlpha; } }; @@ -463,6 +456,21 @@ public abstract class RecentsView< } }; + public static final FloatProperty DESKTOP_CAROUSEL_DETACH_PROGRESS = + new FloatProperty<>("desktopCarouselDetachProgress") { + @Override + public void setValue(RecentsView view, float offset) { + view.mDesktopCarouselDetachProgress = offset; + view.applyAttachAlpha(); + view.updatePageOffsets(); + } + + @Override + public Float get(RecentsView view) { + return view.mDesktopCarouselDetachProgress; + } + }; + /** * Alpha of the task thumbnail splash, where being in BackgroundAppState has a value of 1, and * being in any other state has a value of 0. @@ -574,6 +582,7 @@ public abstract class RecentsView< private int mClampedScrollOffsetBound; private float mAdjacentPageHorizontalOffset = 0; + private float mDesktopCarouselDetachProgress = 0; protected float mTaskViewsSecondaryTranslation = 0; protected float mTaskViewsPrimarySplitTranslation = 0; protected float mTaskViewsSecondarySplitTranslation = 0; @@ -680,13 +689,13 @@ public abstract class RecentsView< protected int mRunningTaskViewId = -1; private int mTaskViewIdCount; protected boolean mRunningTaskTileHidden; - private boolean mNonRunningTaskCategoryHidden; @Nullable private Task[] mTmpRunningTasks; protected int mFocusedTaskViewId = INVALID_TASK_ID; private boolean mTaskIconScaledDown = false; private boolean mRunningTaskShowScreenshot = false; + private float mRunningTaskAttachAlpha; private boolean mOverviewStateEnabled; private boolean mHandleTaskStackChanges; @@ -2733,9 +2742,6 @@ public abstract class RecentsView< setEnableFreeScroll(false); setEnableDrawingLiveTile(false); setRunningTaskHidden(true); - if (enableLargeDesktopWindowingTile()) { - setNonRunningTaskCategoryHidden(true); - } setTaskIconScaledDown(true); } @@ -2859,6 +2865,14 @@ public abstract class RecentsView< animatorSet.play( ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, splashAlpha)); } + if (enableLargeDesktopWindowingTile()) { + if (animatorSet != null) { + animatorSet.play( + ObjectAnimator.ofFloat(this, DESKTOP_CAROUSEL_DETACH_PROGRESS, 0f)); + } else { + DESKTOP_CAROUSEL_DETACH_PROGRESS.set(this, 0f); + } + } } /** @@ -2874,9 +2888,6 @@ public abstract class RecentsView< setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS); Log.d(TAG, "onGestureAnimationEnd - mEnableDrawingLiveTile: " + mEnableDrawingLiveTile); setRunningTaskHidden(false); - if (enableLargeDesktopWindowingTile()) { - setNonRunningTaskCategoryHidden(false); - } animateUpTaskIconScale(); animateActionsViewIn(); @@ -3028,6 +3039,9 @@ public abstract class RecentsView< */ public void setRunningTaskHidden(boolean isHidden) { mRunningTaskTileHidden = isHidden; + // mRunningTaskAttachAlpha can be changed by RUNNING_TASK_ATTACH_ALPHA animation without + // changing mRunningTaskTileHidden. + mRunningTaskAttachAlpha = isHidden ? 0f : 1f; TaskView runningTask = getRunningTaskView(); if (runningTask == null) { return; @@ -3039,18 +3053,11 @@ public abstract class RecentsView< } } - /** - * Hides the tasks that has a different category (Fullscreen/Desktop) from the running task. - */ - public void setNonRunningTaskCategoryHidden(boolean isHidden) { - mNonRunningTaskCategoryHidden = isHidden; - updateMinAndMaxScrollX(); - applyAttachAlpha(); - } - private void applyAttachAlpha() { - mUtils.applyAttachAlpha(getTaskViews(), getRunningTaskView(), mRunningTaskTileHidden, - mNonRunningTaskCategoryHidden); + // Only hide non running task carousel when it's fully off screen, otherwise it needs to + // be visible to move to on screen. + mUtils.applyAttachAlpha(getTaskViews(), getRunningTaskView(), mRunningTaskAttachAlpha, + /*nonRunningTaskCarouselHidden=*/mDesktopCarouselDetachProgress == 1f); } private void setRunningTaskViewShowScreenshot(boolean showScreenshot) { @@ -3800,7 +3807,7 @@ public abstract class RecentsView< translateTaskWhenDismissed( child, Math.abs(i - dismissedIndex), - mIsRtl ? -scrollDiff : scrollDiff, + scrollDiff, anim, splitTimings); needsCurveUpdates = true; @@ -4693,6 +4700,10 @@ public abstract class RecentsView< ? (runningTask == null ? INVALID_PAGE : indexOfChild(runningTask)) : mOffsetMidpointIndexOverride; int modalMidpoint = getCurrentPage(); + TaskView carouselHiddenMidpointTask = runningTask != null ? runningTask + : mUtils.getFirstTaskViewInCarousel(/*nonRunningTaskCarouselHidden=*/true, + getTaskViews(), null); + int carouselHiddenMidpoint = indexOfChild(carouselHiddenMidpointTask); boolean shouldCalculateOffsetForAllTasks = showAsGrid && (enableGridOnlyOverview() || enableLargeDesktopWindowingTile()) && mTaskModalness > 0; @@ -4712,6 +4723,7 @@ public abstract class RecentsView< float modalLeftOffsetSize = 0; float modalRightOffsetSize = 0; float gridOffsetSize = 0; + float carouselHiddenOffsetSize = 0; if (showAsGrid) { // In grid, we only focus the task on the side. The reference index used for offset @@ -4729,7 +4741,10 @@ public abstract class RecentsView< : 0; } + int primarySize = getPagedOrientationHandler().getPrimaryValue(getWidth(), getHeight()); + float maxOverscroll = primarySize * OverScroll.OVERSCROLL_DAMP_FACTOR; for (int i = 0; i < count; i++) { + View child = getChildAt(i); float translation = i == midpoint ? midpointOffsetSize : i < midpoint @@ -4739,16 +4754,31 @@ public abstract class RecentsView< gridOffsetSize = getHorizontalOffsetSize(i, modalMidpoint, modalOffset); gridOffsetSize = Math.abs(gridOffsetSize) * (i <= modalMidpoint ? 1 : -1); } + if (enableLargeDesktopWindowingTile()) { + if (child instanceof TaskView + && !mUtils.isVisibleInCarousel((TaskView) child, + runningTask, /*nonRunningTaskCarouselHidden=*/true)) { + // Increment carouselHiddenOffsetSize by maxOverscroll so it won't be on screen + // even when user overscroll. + carouselHiddenOffsetSize = (Math.abs(getMaxHorizontalOffsetSize(i, + carouselHiddenMidpoint)) + maxOverscroll) + * mDesktopCarouselDetachProgress; + carouselHiddenOffsetSize = carouselHiddenOffsetSize * ( + i <= carouselHiddenMidpoint ? 1 : -1); + } else { + carouselHiddenOffsetSize = 0; + } + } float modalTranslation = i == modalMidpoint ? modalMidpointOffsetSize : showAsGrid ? gridOffsetSize : i < modalMidpoint ? modalLeftOffsetSize : modalRightOffsetSize; - View child = getChildAt(i); boolean skipTranslationOffset = enableDesktopTaskAlphaAnimation() && i == getRunningTaskIndex() && child instanceof DesktopTaskView; - float totalTranslationX = (skipTranslationOffset ? 0f : translation) + modalTranslation; + float totalTranslationX = (skipTranslationOffset ? 0f : translation) + modalTranslation + + carouselHiddenOffsetSize; FloatProperty translationPropertyX = child instanceof TaskView ? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty() : getPagedOrientationHandler().getPrimaryViewTranslate(); @@ -4805,6 +4835,14 @@ public abstract class RecentsView< return 0; } + return getMaxHorizontalOffsetSize(childIndex, midpointIndex) * offsetProgress; + } + + /** + * Computes the distance to offset the given child such that it is completely offscreen when + * translating away from the given midpoint. + */ + private float getMaxHorizontalOffsetSize(int childIndex, int midpointIndex) { // First, get the position of the task relative to the midpoint. If there is no midpoint // then we just use the normal (centered) task position. RectF taskPosition = mTempRectF; @@ -4864,7 +4902,7 @@ public abstract class RecentsView< } distanceToOffscreen -= mLastComputedTaskEndPushOutDistance; } - return distanceToOffscreen * offsetProgress; + return distanceToOffscreen; } /** @@ -5817,7 +5855,7 @@ public abstract class RecentsView< private int getFirstViewIndex() { final TaskView firstView; if (mShowAsGridLastOnLayout) { - // For grid Overivew, it always start if a large tile (focused task or desktop task) if + // For grid Overview, it always start if a large tile (focused task or desktop task) if // they exist, otherwise it start with the first task. TaskView firstLargeTaskView = mUtils.getFirstLargeTaskView(getTaskViews()); if (firstLargeTaskView != null) { @@ -5826,7 +5864,8 @@ public abstract class RecentsView< firstView = getTaskViewAt(0); } } else { - firstView = mUtils.getFirstTaskViewInCarousel(mNonRunningTaskCategoryHidden, + firstView = mUtils.getFirstTaskViewInCarousel( + /*nonRunningTaskCarouselHidden=*/mDesktopCarouselDetachProgress > 0, getTaskViews(), getRunningTaskView()); } return indexOfChild(firstView); @@ -5847,7 +5886,8 @@ public abstract class RecentsView< lastView = mUtils.getLastLargeTaskView(getTaskViews()); } } else { - lastView = mUtils.getLastTaskViewInCarousel(mNonRunningTaskCategoryHidden, + lastView = mUtils.getLastTaskViewInCarousel( + /*nonRunningTaskCarouselHidden=*/mDesktopCarouselDetachProgress > 0, getTaskViews(), getRunningTaskView()); } return indexOfChild(lastView); diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt index 82a76250c2..b5a418b04d 100644 --- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt +++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt @@ -98,7 +98,7 @@ class BubbleBarViewScreenshotTest(emulationSpec: DeviceEmulationSpec) { // if we're still expanding, wait with taking a screenshot val shouldWait: (ComponentActivity, View) -> Boolean = { _, _ -> bubbleBarView.isExpanding } // increase the frame limit to allow the animation to end before taking the screenshot - screenshotRule.frameLimit = 50 + screenshotRule.frameLimit = 500 screenshotRule.screenshotTest( "bubbleBarView_expanded_threeBubbles", checkView = shouldWait, diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt index 467a9cb968..50e2dcf7b4 100644 --- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt +++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt @@ -170,10 +170,100 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) { } } - private class FakeBubbleBarFlyoutPositioner(override val isOnLeft: Boolean) : - BubbleBarFlyoutPositioner { + @Test + fun bubbleBarFlyoutView_collapsed_onLeft() { + screenshotRule.screenshotTest("bubbleBarFlyoutView_collapsed_onLeft") { activity -> + activity.actionBar?.hide() + val flyout = + BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true)) + flyout.showFromCollapsed( + BubbleBarFlyoutMessage( + senderAvatar = ColorDrawable(Color.RED), + senderName = "sender", + message = "collapsed on left", + isGroupChat = true, + ) + ) {} + flyout.updateExpansionProgress(0f) + flyout + } + } + + @Test + fun bubbleBarFlyoutView_collapsed_onRight() { + screenshotRule.screenshotTest("bubbleBarFlyoutView_collapsed_onRight") { activity -> + activity.actionBar?.hide() + val flyout = + BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = false)) + flyout.showFromCollapsed( + BubbleBarFlyoutMessage( + senderAvatar = ColorDrawable(Color.RED), + senderName = "sender", + message = "collapsed on right", + isGroupChat = true, + ) + ) {} + flyout.updateExpansionProgress(0f) + flyout + } + } + + @Test + fun bubbleBarFlyoutView_90p_onLeft() { + screenshotRule.screenshotTest("bubbleBarFlyoutView_90p_onLeft") { activity -> + activity.actionBar?.hide() + val flyout = + BubbleBarFlyoutView( + context, + FakeBubbleBarFlyoutPositioner( + isOnLeft = true, + distanceToCollapsedPosition = PointF(100f, 100f), + ), + ) + flyout.showFromCollapsed( + BubbleBarFlyoutMessage( + senderAvatar = ColorDrawable(Color.RED), + senderName = "sender", + message = "collapsed 90% on left", + isGroupChat = true, + ) + ) {} + flyout.updateExpansionProgress(0.9f) + flyout + } + } + + @Test + fun bubbleBarFlyoutView_80p_onRight() { + screenshotRule.screenshotTest("bubbleBarFlyoutView_80p_onRight") { activity -> + activity.actionBar?.hide() + val flyout = + BubbleBarFlyoutView( + context, + FakeBubbleBarFlyoutPositioner( + isOnLeft = false, + distanceToCollapsedPosition = PointF(200f, 100f), + ), + ) + flyout.showFromCollapsed( + BubbleBarFlyoutMessage( + senderAvatar = ColorDrawable(Color.RED), + senderName = "sender", + message = "collapsed 80% on right", + isGroupChat = true, + ) + ) {} + flyout.updateExpansionProgress(0.8f) + flyout + } + } + + private class FakeBubbleBarFlyoutPositioner( + override val isOnLeft: Boolean, + override val distanceToCollapsedPosition: PointF = PointF(0f, 0f), + ) : BubbleBarFlyoutPositioner { override val targetTy = 0f - override val distanceToCollapsedPosition = PointF(0f, 0f) override val collapsedSize = 30f + override val collapsedColor = Color.BLUE } } diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt index fb12ac9a59..0f02444b30 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt @@ -17,6 +17,7 @@ package com.android.launcher3.taskbar.bubbles.flyout import android.content.Context +import android.graphics.Color import android.graphics.PointF import android.view.Gravity import android.widget.FrameLayout @@ -53,6 +54,7 @@ class BubbleBarFlyoutControllerTest { override val targetTy = 50f override val distanceToCollapsedPosition = PointF(100f, 200f) override val collapsedSize = 30f + override val collapsedColor = Color.BLUE } flyoutController = BubbleBarFlyoutController(flyoutContainer, positioner) } diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index be91c0b738..53dc4bae3d 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -31,8 +31,7 @@ "የተከፈለ ማያ ገፅ" "የመተግበሪያ መረጃ ለ%1$s" "የ%1$s የአጠቃቀም ቅንብሮች" - - + "አዲስ መስኮት" "የመተግበሪያ ጥምረትን ያስቀምጡ" "%1$s | %2$s" "ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 35ba18357d..002c800a04 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -31,8 +31,7 @@ "Podeljeni ekran" "Informacije o aplikaciji za: %1$s" "Podešavanja potrošnje za %1$s" - - + "Novi prozor" "Sačuvaj par aplikacija" "%1$s | %2$s" "Ovaj par aplikacija nije podržan na ovom uređaju" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 1a2bcc13f7..0984f3216f 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -31,8 +31,7 @@ "Падзелены экран" "Інфармацыя пра праграму для: %1$s" "%1$s: налады выкарыстання" - - + "Новае акно" "Захаваць спалучэнне праграм" "%1$s | %2$s" "Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index e4bbd30f52..2b168f60d1 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -31,8 +31,7 @@ "Podijeljeni ekran" "Informacije o aplikaciji %1$s" "Postavke korištenja za: %1$s" - - + "Novi prozor" "Sačuvaj par aplikacija" "%1$s | %2$s" "Par aplikacija nije podržan na uređaju" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 169afe52c2..ddcee65306 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -31,8 +31,7 @@ "Pantalla dividida" "Información de la aplicación %1$s" "Ajustes de uso para %1$s" - - + "Ventana nueva" "Guardar apps emparejadas" "%1$s | %2$s" "El dispositivo no admite esta aplicación emparejada" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index d8417703f2..c0a6fe3f65 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -132,7 +132,7 @@ "برای نمایش «نقطه‌های اعلان»، اعلان‌های برنامه را برای %1$s روشن کنید" "تغییر تنظیمات" "نمایش نقطه‌های اعلان" - "گزینه‌های برنامه‌نویس" + "گزینه‌های توسعه‌دهندگان" "افزودن نماد برنامه‌ها به صفحه اصلی" "برای برنامه‌های جدید" "نامشخص" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 3d5380a66b..a9fd14e2f3 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -31,8 +31,7 @@ "Podijeljeni zaslon" "Informacije o aplikaciji %1$s" "Postavke upotrebe za %1$s" - - + "Novi prozor" "Spremi par aplikacija" "%1$s | %2$s" "Taj par aplikacija nije podržan na ovom uređaju" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 7a87b2665d..001431797f 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -31,8 +31,7 @@ "Skipta skjá" "Upplýsingar um forrit fyrir %1$s" "Notkunarstillingar fyrir %1$s" - - + "Nýr gluggi" "Vista forritapar" "%1$s | %2$s" "Þetta forritapar er ekki stutt í þessu tæki" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index cea0a08a27..fc89041cdd 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -31,8 +31,7 @@ "分割画面" "%1$s のアプリ情報" "%1$s の使用設定" - - + "新しいウィンドウ" "アプリのペア設定を保存" "%1$s | %2$s" "このデバイスは、このアプリのペア設定に対応していません" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 2211a7d11e..f099bcde78 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -31,8 +31,7 @@ "ეკრანის გაყოფა" "%1$s-ის აპის ინფო" "გამოყენების პარამეტრები %1$s-ისთვის" - - + "ახალი ფანჯარა" "აპთა წყვილის შენახვა" "%1$s | %2$s" "ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index ca26ea4515..ebaacc9e65 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -31,8 +31,7 @@ "Экранды бөлу" "%1$s қолданбасы туралы ақпарат" "%1$s пайдалану параметрлері" - - + "Жаңа терезе" "Қолданбаларды жұптау әрекетін сақтау" "%1$s | %2$s" "Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды." diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index dc4fd80d24..b05eeb05cc 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -31,8 +31,7 @@ "មុខងារ​បំបែកអេក្រង់" "ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s" "ការកំណត់ការប្រើប្រាស់សម្រាប់ %1$s" - - + "វិនដូ​ថ្មី" "រក្សាទុកគូកម្មវិធី" "%1$s | %2$s" "មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index b32618154e..753d2dd26b 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -31,8 +31,7 @@ "Экранды бөлүү" "%1$s колдонмосу жөнүндө маалымат" "%1$s колдонмосун пайдалануу параметрлери" - - + "Жаңы терезе" "Колдонмолорду сактап коюу" "%1$s | %2$s" "Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index a613cb1cbf..6879862fd4 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -31,8 +31,7 @@ "Išskaidyto ekrano režimas" "Programos „%1$s“ informacija" "„%1$s“ naudojimo nustatymai" - - + "Naujas langas" "Išsaugoti programų porą" "%1$s | %2$s" "Ši programų pora šiame įrenginyje nepalaikoma" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 2eb1b2b947..b9e68e05de 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -31,8 +31,7 @@ "സ്‌ക്രീൻ വിഭജന മോഡ്" "%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ" "%1$s എന്നതിനുള്ള ഉപയോഗ ക്രമീകരണം" - - + "പുതിയ വിന്‍ഡോ" "ആപ്പ് ജോടി സംരക്ഷിക്കുക" "%1$s | %2$s" "ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index b548e67810..5ddf8a2075 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -31,8 +31,7 @@ "Skrin pisah" "Maklumat apl untuk %1$s" "Tetapan penggunaan sebanyak %1$s" - - + "Tetingkap Baharu" "Simpan gandingan apl" "%1$s | %2$s" "Gandingan apl ini tidak disokong pada peranti ini" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 93c4339af5..4fae68beb8 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -31,8 +31,7 @@ "स्प्लिट स्क्रिन" "%1$s का हकमा एपसम्बन्धी जानकारी" "%1$s को प्रयोगसम्बन्धी सेटिङ" - - + "नयाँ विन्डो" "एपको पेयर सेभ गर्नुहोस्" "%1$s | %2$s" "यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index c86c58d22c..d2b214e225 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -31,8 +31,7 @@ "Ecrã dividido" "Informações da app para %1$s" "Definições de utilização para %1$s" - - + "Nova janela" "Guardar par de apps" "%1$s | %2$s" "Este par de apps não é suportado neste dispositivo" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index f10b93af94..f864b3e7c7 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -31,8 +31,7 @@ "Tela dividida" "Informações do app %1$s" "Configurações de uso de %1$s" - - + "Nova janela" "Salvar par de apps" "%1$s | %2$s" "Este Par de apps não está disponível no dispositivo" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index aea3d2b985..126e3ad893 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -31,8 +31,7 @@ "Разделить экран" "Сведения о приложении \"%1$s\"" "Настройки использования приложения \"%1$s\"" - - + "Новое окно" "Сохранить приложения" "%1$s | %2$s" "Одновременно использовать эти два приложения на устройстве нельзя." diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index a3b9a710f8..328f2f5b33 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -31,8 +31,7 @@ "බෙදුම් තිරය" "%1$s සඳහා යෙදුම් තතු" "%1$s සඳහා භාවිත සැකසීම්" - - + "නව කවුළුව" "යෙදුම් යුගල සුරකින්න" "%1$s | %2$s" "මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 51b0c7ba1f..37a02e4256 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -31,8 +31,7 @@ "Razdeljen zaslon" "Podatki o aplikaciji za: %1$s" "Nastavitve uporabe za »%1$s«" - - + "Novo okno" "Shrani par aplikacij" "%1$s | %2$s" "Ta par aplikacij ni podprt v tej napravi" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index c93519f7aa..afaeb61e0e 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -31,8 +31,7 @@ "Подељени екран" "Информације о апликацији за: %1$s" "Подешавања потрошње за %1$s" - - + "Нови прозор" "Сачувај пар апликација" "%1$s | %2$s" "Овај пар апликација није подржан на овом уређају" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index c92d6f0fa2..547f60ef9a 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -31,8 +31,7 @@ "Delad skärm" "Appinformation för %1$s" "Användningsinställningar för %1$s" - - + "Nytt fönster" "Spara app-par" "%1$s | %2$s" "De här apparna som ska användas tillsammans stöds inte på den här enheten" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 5348a222ab..75dc7f0b60 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -31,8 +31,7 @@ "స్ప్లిట్ స్క్రీన్" "%1$s కోసం యాప్ సమాచారం" "%1$sకు సంబంధించిన వినియోగ సెట్టింగ్‌లు" - - + "కొత్త విండో" "యాప్ పెయిర్‌ను సేవ్ చేయండి" "%1$s | %2$s" "ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు" diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java index b81729a712..f6b610c9bf 100644 --- a/src/com/android/launcher3/statemanager/BaseState.java +++ b/src/com/android/launcher3/statemanager/BaseState.java @@ -71,6 +71,13 @@ public interface BaseState { return false; } + /** + * For this state, whether fullscreen and desktop quickswitch carousel are detached. + */ + default boolean detachDesktopCarousel() { + return true; + } + /** * For this state, whether member variables and other forms of data state should be preserved * or wiped when the state is reapplied. (See {@link StateManager#reapplyState()})