Improve layout transitions
This commit is contained in:
parent
ca813f3f70
commit
944132ba12
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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())
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user