ui: animate fab scale rather than translation
Suggested-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
03e95d2dd3
commit
48e0e427eb
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.wireguard.android.fragment
|
package com.wireguard.android.fragment
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -18,6 +17,8 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.animation.Animation
|
||||||
|
import android.view.animation.AnimationUtils
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
@ -306,7 +307,6 @@ class TunnelListFragment : BaseFragment() {
|
|||||||
private inner class ActionModeListener : ActionMode.Callback {
|
private inner class ActionModeListener : ActionMode.Callback {
|
||||||
val checkedItems: MutableCollection<Int> = HashSet()
|
val checkedItems: MutableCollection<Int> = HashSet()
|
||||||
private var resources: Resources? = null
|
private var resources: Resources? = null
|
||||||
private var initialFabTranslation = 0f
|
|
||||||
|
|
||||||
fun getCheckedItems(): ArrayList<Int> {
|
fun getCheckedItems(): ArrayList<Int> {
|
||||||
return ArrayList(checkedItems)
|
return ArrayList(checkedItems)
|
||||||
@ -316,7 +316,11 @@ class TunnelListFragment : BaseFragment() {
|
|||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.menu_action_delete -> {
|
R.id.menu_action_delete -> {
|
||||||
val copyCheckedItems = HashSet(checkedItems)
|
val copyCheckedItems = HashSet(checkedItems)
|
||||||
binding?.createFab?.translationY = initialFabTranslation
|
binding?.createFab?.apply {
|
||||||
|
visibility = View.VISIBLE
|
||||||
|
scaleX = 1f
|
||||||
|
scaleY = 1f
|
||||||
|
}
|
||||||
Application.getTunnelManager().tunnels.thenAccept { tunnels ->
|
Application.getTunnelManager().tunnels.thenAccept { tunnels ->
|
||||||
val tunnelsToDelete = ArrayList<ObservableTunnel>()
|
val tunnelsToDelete = ArrayList<ObservableTunnel>()
|
||||||
for (position in copyCheckedItems) tunnelsToDelete.add(tunnels[position])
|
for (position in copyCheckedItems) tunnelsToDelete.add(tunnels[position])
|
||||||
@ -346,13 +350,7 @@ class TunnelListFragment : BaseFragment() {
|
|||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
resources = activity!!.resources
|
resources = activity!!.resources
|
||||||
}
|
}
|
||||||
binding?.createFab?.let {
|
animateFab(binding?.createFab, false)
|
||||||
initialFabTranslation = it.translationY
|
|
||||||
ObjectAnimator.ofFloat(it, View.TRANSLATION_Y, 400f).apply {
|
|
||||||
duration = 400
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mode.menuInflater.inflate(R.menu.tunnel_list_action_mode, menu)
|
mode.menuInflater.inflate(R.menu.tunnel_list_action_mode, menu)
|
||||||
binding?.tunnelList?.adapter?.notifyDataSetChanged()
|
binding?.tunnelList?.adapter?.notifyDataSetChanged()
|
||||||
return true
|
return true
|
||||||
@ -361,15 +359,7 @@ class TunnelListFragment : BaseFragment() {
|
|||||||
override fun onDestroyActionMode(mode: ActionMode) {
|
override fun onDestroyActionMode(mode: ActionMode) {
|
||||||
actionMode = null
|
actionMode = null
|
||||||
resources = null
|
resources = null
|
||||||
binding?.createFab?.let {
|
animateFab(binding?.createFab, true)
|
||||||
if (it.translationY != initialFabTranslation) {
|
|
||||||
ObjectAnimator.ofFloat(it, View.TRANSLATION_Y, initialFabTranslation).apply {
|
|
||||||
duration = 400
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkedItems.clear()
|
checkedItems.clear()
|
||||||
binding!!.tunnelList.adapter!!.notifyDataSetChanged()
|
binding!!.tunnelList.adapter!!.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
@ -410,6 +400,26 @@ class TunnelListFragment : BaseFragment() {
|
|||||||
mode.title = resources!!.getQuantityString(R.plurals.delete_title, count, count)
|
mode.title = resources!!.getQuantityString(R.plurals.delete_title, count, count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun animateFab(view: View?, show: Boolean) {
|
||||||
|
view ?: return
|
||||||
|
val animation = AnimationUtils.loadAnimation(
|
||||||
|
context, if (show) R.anim.scale_up else R.anim.scale_down
|
||||||
|
)
|
||||||
|
animation.setAnimationListener(object : Animation.AnimationListener {
|
||||||
|
override fun onAnimationRepeat(animation: Animation?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationEnd(animation: Animation?) {
|
||||||
|
if (!show) view.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationStart(animation: Animation?) {
|
||||||
|
if (show) view.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
view.startAnimation(animation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
12
ui/src/main/res/anim/scale_down.xml
Normal file
12
ui/src/main/res/anim/scale_down.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<scale
|
||||||
|
android:duration="400"
|
||||||
|
android:fromXScale="1.0"
|
||||||
|
android:fromYScale="1.0"
|
||||||
|
android:interpolator="@android:anim/linear_interpolator"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%"
|
||||||
|
android:toXScale="0"
|
||||||
|
android:toYScale="0" />
|
||||||
|
</set>
|
12
ui/src/main/res/anim/scale_up.xml
Normal file
12
ui/src/main/res/anim/scale_up.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<scale
|
||||||
|
android:duration="400"
|
||||||
|
android:fromXScale="0"
|
||||||
|
android:fromYScale="0"
|
||||||
|
android:interpolator="@android:anim/linear_interpolator"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%"
|
||||||
|
android:toXScale="1.0"
|
||||||
|
android:toYScale="1.0" />
|
||||||
|
</set>
|
Loading…
Reference in New Issue
Block a user