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

View File

@@ -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()
}
}

View File

@@ -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)
}

View File

@@ -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);
}

View File

@@ -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