Add fun emoji animations when selecting boost level.

This commit is contained in:
Alex Hart
2021-10-28 17:41:00 -03:00
committed by Greyson Parrelli
parent 5bb48caafd
commit 614d6ce04b
10 changed files with 117 additions and 4 deletions
@@ -52,7 +52,7 @@ data class Boost(
val selectedBoost: Boost?,
val currency: Currency,
override val isEnabled: Boolean,
val onBoostClick: (Boost) -> Unit,
val onBoostClick: (View, Boost) -> Unit,
val isCustomAmountFocused: Boolean,
val onCustomAmountChanged: (String) -> Unit,
val onCustomAmountFocusChanged: (Boolean) -> Unit,
@@ -95,7 +95,7 @@ data class Boost(
FiatMoneyUtil.formatOptions().trimZerosAfterDecimal()
)
button.setOnClickListener {
model.onBoostClick(boost)
model.onBoostClick(it, boost)
custom.clearFocus()
}
}
@@ -1,11 +1,13 @@
package org.thoughtcrime.securesms.components.settings.app.subscription.boost
import android.text.SpannableStringBuilder
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import com.airbnb.lottie.LottieAnimationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.signal.core.util.DimensionUnit
import org.signal.core.util.logging.Log
@@ -23,6 +25,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.models.Cu
import org.thoughtcrime.securesms.components.settings.app.subscription.models.GooglePayButton
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.Projection
import org.thoughtcrime.securesms.util.SpanUtil
/**
@@ -35,6 +38,13 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
private val viewModel: BoostViewModel by viewModels(ownerProducer = { requireActivity() })
private val lifecycleDisposable = LifecycleDisposable()
private lateinit var boost1AnimationView: LottieAnimationView
private lateinit var boost2AnimationView: LottieAnimationView
private lateinit var boost3AnimationView: LottieAnimationView
private lateinit var boost4AnimationView: LottieAnimationView
private lateinit var boost5AnimationView: LottieAnimationView
private lateinit var boost6AnimationView: LottieAnimationView
private lateinit var processingDonationPaymentDialog: AlertDialog
private val sayThanks: CharSequence by lazy {
@@ -58,6 +68,13 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
.setCancelable(false)
.create()
boost1AnimationView = requireView().findViewById(R.id.boost1_animation)
boost2AnimationView = requireView().findViewById(R.id.boost2_animation)
boost3AnimationView = requireView().findViewById(R.id.boost3_animation)
boost4AnimationView = requireView().findViewById(R.id.boost4_animation)
boost5AnimationView = requireView().findViewById(R.id.boost5_animation)
boost6AnimationView = requireView().findViewById(R.id.boost6_animation)
viewModel.state.observe(viewLifecycleOwner) { state ->
adapter.submitList(getConfiguration(state).toMappingModelList())
}
@@ -119,8 +136,9 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
currency = state.customAmount.currency,
isCustomAmountFocused = state.isCustomAmountFocused,
isEnabled = state.stage == BoostState.Stage.READY,
onBoostClick = {
viewModel.setSelectedBoost(it)
onBoostClick = { view, boost ->
startAnimationAboveSelectedBoost(view)
viewModel.setSelectedBoost(boost)
},
onCustomAmountChanged = {
viewModel.setCustomAmount(it)
@@ -196,6 +214,35 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
}
}
private fun startAnimationAboveSelectedBoost(view: View) {
val animationView = getAnimationContainer(view)
val viewProjection = Projection.relativeToViewRoot(view, null)
val animationProjection = Projection.relativeToViewRoot(animationView, null)
val viewHorizontalCenter = viewProjection.x + viewProjection.width / 2f
val animationHorizontalCenter = animationProjection.x + animationProjection.width / 2f
val animationBottom = animationProjection.y + animationProjection.height
animationView.translationY = -(animationBottom - viewProjection.y) + (viewProjection.height / 2f)
animationView.translationX = viewHorizontalCenter - animationHorizontalCenter
animationView.playAnimation()
viewProjection.release()
animationProjection.release()
}
private fun getAnimationContainer(view: View): LottieAnimationView {
return when (view.id) {
R.id.boost_1 -> boost1AnimationView
R.id.boost_2 -> boost2AnimationView
R.id.boost_3 -> boost3AnimationView
R.id.boost_4 -> boost4AnimationView
R.id.boost_5 -> boost5AnimationView
R.id.boost_6 -> boost6AnimationView
else -> throw AssertionError()
}
}
companion object {
private val TAG = Log.tag(BoostFragment::class.java)
}
@@ -98,6 +98,18 @@ public final class Projection {
}
}
@Override public String toString() {
return "Projection{" +
"x=" + x +
", y=" + y +
", width=" + width +
", height=" + height +
", corners=" + corners +
", path=" + path +
", rect=" + rect +
'}';
}
public @NonNull Projection translateX(float xTranslation) {
return set(x + xTranslation, y, width, height, corners);
}
@@ -26,4 +26,52 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/handle" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost1_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_smile"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost2_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_clap"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost3_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_heart_eyes"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost4_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_fire"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost5_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_shock"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/boost6_animation"
android:layout_width="60dp"
android:layout_height="360dp"
app:lottie_rawRes="@raw/boost_rockets"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long