From 57c081229bfd86b6d9e60bfe0dc6c26b0099603f Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:58:29 +0200 Subject: [PATCH] Rewrite popup animations, fix crash --- .../ui/launcher/search/apps/AppItem.kt | 77 +++++------- .../launcher/search/calendar/CalendarItem.kt | 58 ++++----- .../launcher/search/contacts/ContactItem.kt | 72 +++++------ .../ui/launcher/search/files/FileItem.kt | 112 ++++++++++-------- .../launcher/search/shortcut/ShortcutItem.kt | 107 ++++++++++------- .../ui/launcher/search/website/WebsiteItem.kt | 72 +++++------ .../search/wikipedia/WikipediaItem.kt | 65 +++++----- 7 files changed, 279 insertions(+), 284 deletions(-) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt index cfbb4156..7aa99452 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt @@ -2,15 +2,11 @@ package de.mm20.launcher2.ui.launcher.search.apps import android.app.PendingIntent import android.content.Intent -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.SizeTransform +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize -import androidx.compose.animation.core.snap import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.animation.with +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -20,9 +16,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.requiredSize -import androidx.compose.foundation.layout.requiredWidth import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape @@ -52,6 +46,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Rect @@ -62,6 +57,7 @@ import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.roundToIntRect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import coil.compose.AsyncImage @@ -74,7 +70,6 @@ import de.mm20.launcher2.ui.component.ShapedLauncherIcon import de.mm20.launcher2.ui.component.SubmenuToolbarAction import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -85,7 +80,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState import de.mm20.launcher2.ui.modifier.scale import kotlinx.coroutines.launch import kotlin.math.pow -import kotlin.math.roundToInt @Composable fun AppItem( @@ -438,41 +432,30 @@ fun AppItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - slideInHorizontally( - tween(300), - initialOffsetX = { -it + origin.width.roundToInt() }) with - slideOutHorizontally( - tween(300), - targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - AppItem( - modifier = Modifier - .fillMaxWidth() - .scale( - 1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress), - transformOrigin = TransformOrigin(1f, 0f) - ) - .offset( - x = 16.dp * (1 - animationProgress).pow(10), - y = -16.dp * (1 - animationProgress), - ), - app = app, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + ) { + AppItem( + modifier = Modifier + .fillMaxWidth() + .scale( + 1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress), + transformOrigin = TransformOrigin(1f, 0f) + ) + .offset( + x = 16.dp * (1 - animationProgress).pow(10), + y = -16.dp * (1 - animationProgress), + ), + app = app, + onBack = onDismiss + ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/calendar/CalendarItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/calendar/CalendarItem.kt index 20fcb16a..11b18f34 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/calendar/CalendarItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/calendar/CalendarItem.kt @@ -2,24 +2,17 @@ package de.mm20.launcher2.ui.launcher.search.calendar import android.content.Context import android.text.format.DateUtils -import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.SizeTransform import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.snap import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.with +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredHeight -import androidx.compose.foundation.layout.requiredWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowBack import androidx.compose.material.icons.rounded.Edit @@ -51,6 +44,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.roundToIntRect import androidx.lifecycle.lifecycleScope import de.mm20.launcher2.search.data.CalendarEvent import de.mm20.launcher2.ui.R @@ -58,7 +52,6 @@ import de.mm20.launcher2.ui.animation.animateTextStyleAsState import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -313,32 +306,25 @@ fun CalendarItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - fadeIn(snap()) with - fadeOut(snap(400)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - CalendarItem( - modifier = Modifier - .fillMaxWidth() - .background(Color(calendar.color).copy(alpha = 1f - animationProgress)), - calendar = calendar, - showDetails = true, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.Center, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.Center, + ) { origin.roundToIntRect().size }, + ) { + CalendarItem( + modifier = Modifier + .fillMaxWidth() + .background(Color(calendar.color).copy(alpha = 1f - animationProgress)), + calendar = calendar, + showDetails = true, + onBack = onDismiss + ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt index f84b7e46..c3fc142c 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt @@ -2,24 +2,17 @@ package de.mm20.launcher2.ui.launcher.search.contacts import android.content.Intent import android.net.Uri -import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.SizeTransform import androidx.compose.animation.core.animateDp -import androidx.compose.animation.core.snap import androidx.compose.animation.core.tween import androidx.compose.animation.core.updateTransition -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.with -import androidx.compose.foundation.layout.Box +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredHeight -import androidx.compose.foundation.layout.requiredWidth import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons @@ -51,6 +44,7 @@ import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.roundToIntRect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import de.mm20.launcher2.ktx.tryStartActivity @@ -64,7 +58,6 @@ import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction import de.mm20.launcher2.ui.icons.Telegram import de.mm20.launcher2.ui.icons.WhatsApp -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -386,38 +379,31 @@ fun ContactItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - fadeIn(snap()) with - fadeOut(snap(400)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - ContactItem( - modifier = Modifier - .fillMaxWidth() - .scale( - 1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress), - transformOrigin = TransformOrigin(0f, 0f) - ) - .offset( - x = -16.dp * (1 - animationProgress), - y = -16.dp * (1 - animationProgress) - ), - contact = contact, - showDetails = true, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.TopStart, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.TopStart, + ) { origin.roundToIntRect().size }, + ) { + ContactItem( + modifier = Modifier + .fillMaxWidth() + .scale( + 1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress), + transformOrigin = TransformOrigin(0f, 0f) + ) + .offset( + x = -16.dp * (1 - animationProgress), + y = -16.dp * (1 - animationProgress) + ), + contact = contact, + showDetails = true, + onBack = onDismiss + ) } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt index 3c96f08d..2dd1e6ad 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt @@ -1,15 +1,39 @@ package de.mm20.launcher2.ui.launcher.search.files -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateDp -import androidx.compose.animation.core.snap import androidx.compose.animation.core.tween import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.layout.* +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.* -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.rounded.Delete +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.rounded.OpenInNew +import androidx.compose.material.icons.rounded.Share +import androidx.compose.material.icons.rounded.Star +import androidx.compose.material.icons.rounded.StarOutline +import androidx.compose.material.icons.rounded.Visibility +import androidx.compose.material.icons.rounded.VisibilityOff +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarResult +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Rect @@ -19,9 +43,9 @@ import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.roundToIntRect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.search.data.File import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.animation.animateTextStyleAsState @@ -29,7 +53,6 @@ import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.ShapedLauncherIcon import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -40,7 +63,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState import de.mm20.launcher2.ui.modifier.scale import kotlinx.coroutines.launch import java.text.DecimalFormat -import kotlin.math.roundToInt @Composable fun FileItem( @@ -265,11 +287,14 @@ fun FileItem( onBack() lifecycleOwner.lifecycleScope.launch { val result = snackbarHostState.showSnackbar( - message = context.getString(R.string.msg_item_hidden, file.label), + message = context.getString( + R.string.msg_item_hidden, + file.label + ), actionLabel = context.getString(R.string.action_undo), duration = SnackbarDuration.Short, - ) - if(result == SnackbarResult.ActionPerformed) { + ) + if (result == SnackbarResult.ActionPerformed) { viewModel.unhide() } } @@ -302,43 +327,32 @@ fun FileItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - slideInHorizontally( - tween(300), - initialOffsetX = { -it + origin.width.roundToInt() }) with - slideOutHorizontally( - tween(300), - targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - FileItem( - modifier = Modifier - .fillMaxWidth() - .scale( - 1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress), - transformOrigin = TransformOrigin(1f, 0f) - ) - .offset( - x = 16.dp * (1 - animationProgress), - y = -16.dp * (1 - animationProgress) - ), - file = file, - showDetails = true, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + ) { + FileItem( + modifier = Modifier + .fillMaxWidth() + .scale( + 1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress), + transformOrigin = TransformOrigin(1f, 0f) + ) + .offset( + x = 16.dp * (1 - animationProgress), + y = -16.dp * (1 - animationProgress) + ), + file = file, + showDetails = true, + onBack = onDismiss + ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt index 290069a5..80df9898 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt @@ -4,13 +4,41 @@ package de.mm20.launcher2.ui.launcher.search.shortcut import android.content.Intent import android.net.Uri import android.provider.Settings -import androidx.compose.animation.* -import androidx.compose.animation.core.* -import androidx.compose.foundation.layout.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateDp +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.* -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.rounded.Delete +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.rounded.Info +import androidx.compose.material.icons.rounded.Star +import androidx.compose.material.icons.rounded.StarOutline +import androidx.compose.material.icons.rounded.Visibility +import androidx.compose.material.icons.rounded.VisibilityOff +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarResult +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.TransformOrigin @@ -19,9 +47,9 @@ import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.roundToIntRect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.ktx.tryStartActivity import de.mm20.launcher2.search.data.AppShortcut import de.mm20.launcher2.search.data.LauncherShortcut @@ -32,7 +60,6 @@ import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.ShapedLauncherIcon import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -43,7 +70,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState import de.mm20.launcher2.ui.modifier.scale import kotlinx.coroutines.launch import kotlin.math.pow -import kotlin.math.roundToInt @Composable fun AppShortcutItem( @@ -263,43 +289,32 @@ fun ShortcutItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - slideInHorizontally( - tween(300), - initialOffsetX = { -it + origin.width.roundToInt() }) with - slideOutHorizontally( - tween(300), - targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - AppShortcutItem( - modifier = Modifier - .fillMaxWidth() - .scale( - 1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress), - transformOrigin = TransformOrigin(1f, 0f) - ) - .offset( - x = 16.dp * (1 - animationProgress).pow(10), - y = -16.dp * (1 - animationProgress), - ), - shortcut = shortcut, - showDetails = true, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.TopEnd, + ) { origin.roundToIntRect().size }, + ) { + AppShortcutItem( + modifier = Modifier + .fillMaxWidth() + .scale( + 1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress), + transformOrigin = TransformOrigin(1f, 0f) + ) + .offset( + x = 16.dp * (1 - animationProgress).pow(10), + y = -16.dp * (1 - animationProgress), + ), + shortcut = shortcut, + showDetails = true, + onBack = onDismiss + ) } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/website/WebsiteItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/website/WebsiteItem.kt index b826d61c..eb301fca 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/website/WebsiteItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/website/WebsiteItem.kt @@ -1,29 +1,41 @@ package de.mm20.launcher2.ui.launcher.search.website -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.* +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.rounded.Share +import androidx.compose.material.icons.rounded.Star +import androidx.compose.material.icons.rounded.StarOutline import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.compose.ui.unit.roundToIntRect import coil.compose.AsyncImage import de.mm20.launcher2.search.data.Website +import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.R -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -59,7 +71,8 @@ fun WebsiteItem( .background(MaterialTheme.colorScheme.secondaryContainer), model = website.image, contentScale = ContentScale.Crop, - contentDescription = null) + contentDescription = null + ) } Column( modifier = Modifier.padding(16.dp), @@ -111,7 +124,7 @@ fun WebsiteItem( toolbarActions.add( DefaultToolbarAction( label = stringResource(R.string.menu_share), - icon= Icons.Rounded.Share, + icon = Icons.Rounded.Share, action = { website.share(context) } @@ -146,29 +159,22 @@ fun WebsiteItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - fadeIn(tween(200)) with - fadeOut(tween(200, 200)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - WebsiteItem( - modifier = Modifier - .fillMaxWidth(), - website = website, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.Center, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.Center, + ) { origin.roundToIntRect().size }, + ) { + WebsiteItem( + modifier = Modifier + .fillMaxWidth(), + website = website, + onBack = onDismiss + ) } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/wikipedia/WikipediaItem.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/wikipedia/WikipediaItem.kt index 58f24488..4ae64470 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/wikipedia/WikipediaItem.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/wikipedia/WikipediaItem.kt @@ -1,29 +1,41 @@ package de.mm20.launcher2.ui.launcher.search.wikipedia -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween +import androidx.compose.animation.expandIn +import androidx.compose.animation.shrinkOut import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.* +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.rounded.Share +import androidx.compose.material.icons.rounded.Star +import androidx.compose.material.icons.rounded.StarOutline import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.compose.ui.unit.roundToIntRect import coil.compose.AsyncImage import de.mm20.launcher2.search.data.Wikipedia import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.Toolbar import de.mm20.launcher2.ui.component.ToolbarAction -import de.mm20.launcher2.ui.ktx.toDp import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.listItemViewModel @@ -154,29 +166,22 @@ fun WikipediaItemGridPopup( origin: Rect, onDismiss: () -> Unit ) { - AnimatedContent( - targetState = show, - transitionSpec = { - fadeIn(tween(200)) with - fadeOut(tween(200, 200)) using - SizeTransform { _, _ -> - tween(300) - } - } - ) { targetState -> - if (targetState) { - WikipediaItem( - modifier = Modifier - .fillMaxWidth(), - wikipedia = wikipedia, - onBack = onDismiss - ) - } else { - Box( - modifier = Modifier - .requiredWidth(origin.width.toDp()) - .requiredHeight(origin.height.toDp()) - ) - } + AnimatedVisibility( + show, + enter = expandIn( + animationSpec = tween(300), + expandFrom = Alignment.Center, + ) { origin.roundToIntRect().size }, + exit = shrinkOut( + animationSpec = tween(300), + shrinkTowards = Alignment.Center, + ) { origin.roundToIntRect().size }, + ) { + WikipediaItem( + modifier = Modifier + .fillMaxWidth(), + wikipedia = wikipedia, + onBack = onDismiss + ) } } \ No newline at end of file