diff --git a/app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt b/app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt index 9b85ca37e..c375599d0 100644 --- a/app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt @@ -1,5 +1,8 @@ package com.topjohnwu.magisk.redesign.hide +import android.animation.Animator +import android.animation.AnimatorSet +import android.animation.ObjectAnimator import android.content.Context import android.graphics.Insets import android.os.Bundle @@ -7,10 +10,20 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View +import androidx.core.animation.addListener +import androidx.core.view.isInvisible +import androidx.core.view.isVisible +import androidx.core.view.marginBottom +import androidx.core.view.marginEnd +import androidx.interpolator.view.animation.FastOutSlowInInterpolator +import com.google.android.material.circularreveal.CircularRevealCompat +import com.google.android.material.circularreveal.CircularRevealWidget +import com.google.android.material.floatingactionbutton.FloatingActionButton import com.topjohnwu.magisk.R import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding import com.topjohnwu.magisk.redesign.compat.CompatFragment import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.math.hypot class HideFragment : CompatFragment() { @@ -27,6 +40,14 @@ class HideFragment : CompatFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + binding.hideFilterToggle.setOnClickListener { + MotionRevealHelper.withViews(binding.hideFilter, binding.hideFilterToggle, true) + } + binding.hideFilterInclude.hideFilterDone.setOnClickListener { + MotionRevealHelper.withViews(binding.hideFilter, binding.hideFilterToggle, false) + } + val lama = binding.hideContent.layoutManager ?: return lama.isAutoMeasureEnabled = false } @@ -44,4 +65,71 @@ class HideFragment : CompatFragment() { return super.onOptionsItemSelected(item) } -} \ No newline at end of file +} + +object MotionRevealHelper { + + fun withViews( + revealable: CV, + fab: FloatingActionButton, + expanded: Boolean + ) where CV : CircularRevealWidget, CV : View { + revealable.revealInfo = revealable.createRevealInfo(!expanded) + + val revealInfo = revealable.createRevealInfo(expanded) + val revealAnim = revealable.createRevealAnim(revealInfo) + val moveAnim = fab.createMoveAnim(revealInfo) + + AnimatorSet().also { + if (expanded) { + it.play(revealAnim).after(moveAnim) + } else { + it.play(moveAnim).after(revealAnim) + } + }.start() + } + + private fun CV.createRevealAnim( + revealInfo: CircularRevealWidget.RevealInfo + ): Animator where CV : CircularRevealWidget, CV : View = + CircularRevealCompat.createCircularReveal( + this, + revealInfo.centerX, + revealInfo.centerY, + revealInfo.radius + ).apply { + addListener(onStart = { + isVisible = true + }, onEnd = { + if (revealInfo.radius == 0f) { + isInvisible = true + } + }) + } + + private fun FloatingActionButton.createMoveAnim( + revealInfo: CircularRevealWidget.RevealInfo + ): Animator = AnimatorSet().also { + it.interpolator = FastOutSlowInInterpolator() + it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() }) + + val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f + val targetX = if (revealInfo.radius == 0f) 0f else -maxX + val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX) + + val maxY = revealInfo.centerY - marginBottom - measuredHeight / 2f + val targetY = if (revealInfo.radius == 0f) 0f else -maxY + val moveY = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, targetY) + + it.playTogether(moveX, moveY) + } + + private fun View.createRevealInfo(expanded: Boolean): CircularRevealWidget.RevealInfo { + val cX = measuredWidth / 2f + val cY = measuredHeight / 2f - paddingBottom + return CircularRevealWidget.RevealInfo(cX, cY, if (expanded) hypot(cX, cY) else 0f) + } + +} + + diff --git a/app/src/main/res/layout/fragment_hide_md2.xml b/app/src/main/res/layout/fragment_hide_md2.xml index 61493935d..cfab09d06 100644 --- a/app/src/main/res/layout/fragment_hide_md2.xml +++ b/app/src/main/res/layout/fragment_hide_md2.xml @@ -23,129 +23,48 @@ invisibleUnless="@{viewModel.loaded || !viewModel.items.empty}" itemBinding="@{viewModel.itemBinding}" items="@{viewModel.items}" - nestedScrollingEnabled="@{false}" android:layout_width="match_parent" - android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}" - android:paddingBottom="@{viewModel.insets.bottom}" android:layout_height="match_parent" android:clipToPadding="false" android:orientation="vertical" android:paddingStart="@dimen/l1" + android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}" android:paddingEnd="@dimen/l1" + android:paddingBottom="@{viewModel.insets.bottom}" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:listitem="@layout/item_hide_md2" tools:paddingTop="40dp" /> - + app:backgroundTint="?colorSurface" + app:srcCompat="@drawable/ic_filter" + app:tint="?colorPrimary" + tools:layout_marginBottom="64dp" /> - + + + android:layout_height="wrap_content" /> - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings_md2.xml b/app/src/main/res/values/strings_md2.xml index ec7a0792c..a37dd2ed1 100644 --- a/app/src/main/res/values/strings_md2.xml +++ b/app/src/main/res/values/strings_md2.xml @@ -87,5 +87,7 @@ Filter by name Scroll up + Filters + Search \ No newline at end of file