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()})