Improve layout transitions

This commit is contained in:
MM20 2022-02-17 23:38:49 +01:00
parent ca813f3f70
commit 944132ba12
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
9 changed files with 14 additions and 38 deletions

View File

@ -1,12 +1,10 @@
package de.mm20.launcher2.ui.launcher package de.mm20.launcher2.ui.launcher
import android.animation.AnimatorSet import android.animation.AnimatorSet
import android.animation.LayoutTransition
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
@ -20,13 +18,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.doOnEnd import androidx.core.animation.doOnEnd
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.setPadding import androidx.core.view.setPadding
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.ktx.isBrightColor
import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.transition.OneShotLayoutTransition import de.mm20.launcher2.transition.OneShotLayoutTransition
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewLauncherScaffoldBinding import de.mm20.launcher2.ui.databinding.ViewLauncherScaffoldBinding
@ -152,9 +147,9 @@ class LauncherScaffoldView @JvmOverloads constructor(
} }
widgetsViewModel.isEditMode.observe(context) { widgetsViewModel.isEditMode.observe(context) {
OneShotLayoutTransition.run(binding.scrollContainer)
if (it) { if (it) {
binding.scrollView.setOnTouchListener(null) binding.scrollView.setOnTouchListener(null)
OneShotLayoutTransition.run(binding.scrollContainer)
binding.searchBar.visibility = View.INVISIBLE binding.searchBar.visibility = View.INVISIBLE
binding.editWidgetToolbar binding.editWidgetToolbar
.animate() .animate()
@ -170,7 +165,6 @@ class LauncherScaffoldView @JvmOverloads constructor(
context.window.statusBarColor = colorSurface.data context.window.statusBarColor = colorSurface.data
viewModel.setStatusBarColor(colorSurface.data) viewModel.setStatusBarColor(colorSurface.data)
} else { } else {
binding.widgetContainer.layoutTransition = ChangingLayoutTransition()
binding.scrollView.setOnTouchListener(scrollViewOnTouchListener) binding.scrollView.setOnTouchListener(scrollViewOnTouchListener)
binding.searchBar.visibility = View.VISIBLE binding.searchBar.visibility = View.VISIBLE
@ -233,6 +227,7 @@ class LauncherScaffoldView @JvmOverloads constructor(
set.duration = 300 set.duration = 300
set.doOnEnd { set.doOnEnd {
binding.searchContainer.visibility = View.GONE binding.searchContainer.visibility = View.GONE
binding.widgetContainer.animate().alpha(1f).setDuration(500).start()
binding.widgetContainer.visibility = View.VISIBLE binding.widgetContainer.visibility = View.VISIBLE
} }
set.playTogether( set.playTogether(
@ -255,7 +250,9 @@ class LauncherScaffoldView @JvmOverloads constructor(
} }
private fun showSearch() { private fun showSearch() {
OneShotLayoutTransition.run(binding.widgetContainer)
binding.searchContainer.visibility = View.VISIBLE binding.searchContainer.visibility = View.VISIBLE
binding.widgetContainer.animate().alpha(0f).setDuration(500).start()
binding.widgetContainer.visibility = View.GONE binding.widgetContainer.visibility = View.GONE
val set = AnimatorSet() val set = AnimatorSet()
set.duration = 300 set.duration = 300

View File

@ -1,5 +1,6 @@
package de.mm20.launcher2.ui.launcher.search.common.list package de.mm20.launcher2.ui.launcher.search.common.list
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding

View File

@ -55,8 +55,6 @@ class WidgetsView @JvmOverloads constructor(
init { init {
context as AppCompatActivity context as AppCompatActivity
layoutTransition = ChangingLayoutTransition()
binding.widgetList.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
pickWidgetLauncher = context.registerForActivityResult( pickWidgetLauncher = context.registerForActivityResult(
ActivityResultContracts.StartActivityForResult() ActivityResultContracts.StartActivityForResult()
@ -78,6 +76,7 @@ class WidgetsView @JvmOverloads constructor(
viewModel.isEditMode.observe(context) { viewModel.isEditMode.observe(context) {
if (it) { if (it) {
OneShotLayoutTransition.run(binding.widgetList)
binding.clockWidget.visibility = View.GONE binding.clockWidget.visibility = View.GONE
for (v in binding.widgetList.iterator()) { for (v in binding.widgetList.iterator()) {
@ -89,8 +88,6 @@ class WidgetsView @JvmOverloads constructor(
} }
} }
} }
OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(this)
binding.fabEditWidget.apply { binding.fabEditWidget.apply {
setIconResource(R.drawable.ic_add) setIconResource(R.drawable.ic_add)
setText(R.string.widget_add_widget) setText(R.string.widget_add_widget)
@ -99,13 +96,14 @@ class WidgetsView @JvmOverloads constructor(
} }
} }
} else { } else {
if (::widgets.isInitialized) viewModel.saveWidgets(widgets) if (::widgets.isInitialized) {
binding.widgetList.layoutTransition = ChangingLayoutTransition() viewModel.saveWidgets(widgets)
OneShotLayoutTransition.run(binding.widgetList)
}
binding.clockWidget.visibility = View.VISIBLE binding.clockWidget.visibility = View.VISIBLE
for (v in binding.widgetList.iterator()) { for (v in binding.widgetList.iterator()) {
if (v is WidgetView) { if (v is WidgetView) {
v.editMode = false v.editMode = false
v.layoutTransition = ChangingLayoutTransition()
} }
} }
binding.fabEditWidget.apply { binding.fabEditWidget.apply {
@ -155,7 +153,6 @@ class WidgetsView @JvmOverloads constructor(
params.topMargin = (8 * dp).roundToInt() params.topMargin = (8 * dp).roundToInt()
for (w in widgets) { for (w in widgets) {
val view = WidgetView(context) val view = WidgetView(context)
view.layoutTransition = ChangingLayoutTransition()
view.layoutParams = params view.layoutParams = params
if (view.setWidget(w, widgetHost)) { if (view.setWidget(w, widgetHost)) {
binding.widgetList.addDragView(view, view.getDragHandle()) binding.widgetList.addDragView(view, view.getDragHandle())

View File

@ -97,6 +97,7 @@ fun CalendarWidget() {
modifier = Modifier modifier = Modifier
.padding(horizontal = 12.dp) .padding(horizontal = 12.dp)
.padding(bottom = 12.dp) .padding(bottom = 12.dp)
.animateContentSize()
) { ) {
if (hasPermission == false) { if (hasPermission == false) {
MissingPermissionBanner( MissingPermissionBanner(

View File

@ -1,6 +1,5 @@
package de.mm20.launcher2.ui.legacy.component package de.mm20.launcher2.ui.legacy.component
import android.animation.LayoutTransition
import android.appwidget.AppWidgetHost import android.appwidget.AppWidgetHost
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
@ -9,7 +8,6 @@ import android.view.View
import androidx.appcompat.widget.TooltipCompat import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.get import androidx.core.view.get
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.transition.OneShotLayoutTransition import de.mm20.launcher2.transition.OneShotLayoutTransition
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewWidgetBinding import de.mm20.launcher2.ui.databinding.ViewWidgetBinding
@ -29,24 +27,19 @@ class WidgetView : LauncherCardView {
var editMode = false var editMode = false
set(value) { set(value) {
OneShotLayoutTransition.run(this)
if (value) { if (value) {
binding.widgetControlPanel.visibility = View.VISIBLE binding.widgetControlPanel.visibility = View.VISIBLE
val widget = binding.widgetWrapper[2] val widget = binding.widgetWrapper[2]
widget.visibility = View.GONE widget.visibility = View.GONE
binding.widgetName.visibility = View.VISIBLE binding.widgetName.visibility = View.VISIBLE
visibility = View.VISIBLE visibility = View.VISIBLE
layoutTransition = OneShotLayoutTransition(this)
widgetView?.layoutTransition = null
binding.widgetWrapper.layoutTransition = null
} else { } else {
resizeMode = false resizeMode = false
binding.widgetControlPanel.visibility = View.GONE binding.widgetControlPanel.visibility = View.GONE
val widget = binding.widgetWrapper[2] as LauncherWidget val widget = binding.widgetWrapper[2] as LauncherWidget
widget.visibility = View.VISIBLE widget.visibility = View.VISIBLE
binding.widgetName.visibility = View.GONE binding.widgetName.visibility = View.GONE
layoutTransition = ChangingLayoutTransition()
widgetView?.layoutTransition = ChangingLayoutTransition()
binding.widgetWrapper.layoutTransition = ChangingLayoutTransition()
} }
field = value field = value
} }
@ -55,6 +48,8 @@ class WidgetView : LauncherCardView {
set(value) { set(value) {
if (value == field) return if (value == field) return
onResizeModeChange?.invoke(value) onResizeModeChange?.invoke(value)
OneShotLayoutTransition.run(this)
OneShotLayoutTransition.run(binding.widgetWrapper)
if (value) { if (value) {
binding.widgetResizeDragHandle.visibility = View.VISIBLE binding.widgetResizeDragHandle.visibility = View.VISIBLE
val widget = binding.widgetWrapper[2] val widget = binding.widgetWrapper[2]
@ -69,7 +64,6 @@ class WidgetView : LauncherCardView {
} }
} }
layoutTransition = OneShotLayoutTransition(this)
field = value field = value
} }
@ -86,9 +80,6 @@ class WidgetView : LauncherCardView {
binding.widgetActionRemove.setOnClickListener { binding.widgetActionRemove.setOnClickListener {
onRemove?.invoke() onRemove?.invoke()
} }
layoutTransition = LayoutTransition().apply {
enableTransitionType(LayoutTransition.CHANGING)
}
TooltipCompat.setTooltipText(binding.widgetActionResize, context.getString(R.string.widget_action_adjust_height)) TooltipCompat.setTooltipText(binding.widgetActionResize, context.getString(R.string.widget_action_adjust_height))
TooltipCompat.setTooltipText(binding.widgetActionRemove, context.getString(R.string.widget_action_remove)) TooltipCompat.setTooltipText(binding.widgetActionRemove, context.getString(R.string.widget_action_remove))
@ -118,9 +109,6 @@ class WidgetView : LauncherCardView {
binding.widgetName.text = widgetView?.name binding.widgetName.text = widgetView?.name
binding.widgetActionResize.visibility = View.VISIBLE binding.widgetActionResize.visibility = View.VISIBLE
} }
widgetView?.layoutTransition = LayoutTransition().apply {
enableTransitionType(LayoutTransition.CHANGING)
}
this.widget = widget this.widget = widget
return true return true
} }

View File

@ -11,11 +11,6 @@ abstract class LauncherWidget : FrameLayout {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
init {
layoutTransition = LayoutTransition().apply {
enableTransitionType(LayoutTransition.CHANGING)
}
}
abstract val canResize: Boolean abstract val canResize: Boolean
abstract val name: String abstract val name: String

View File

@ -21,7 +21,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">
<de.mm20.launcher2.ui.launcher.search.SearchView <de.mm20.launcher2.ui.launcher.search.SearchView

View File

@ -7,7 +7,6 @@
android:id="@+id/widgetWrapper" android:id="@+id/widgetWrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">
<FrameLayout <FrameLayout

View File

@ -14,7 +14,6 @@
android:id="@+id/widgetList" android:id="@+id/widgetList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:orientation="vertical"> android:orientation="vertical">