Animated stat values, truncate text if needed,

This commit is contained in:
Hafiz 2022-06-24 12:43:55 -04:00
parent bd7caff14f
commit aa1ec21668
4 changed files with 94 additions and 20 deletions

View file

@ -1,7 +1,8 @@
package com.habitrpg.wearos.habitica.ui.activities
import android.animation.ValueAnimator
import android.os.Bundle
import android.view.View
import android.view.View.*
import androidx.activity.viewModels
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ActivityStatsBinding
@ -9,8 +10,10 @@ import com.habitrpg.common.habitica.views.HabiticaIconsHelper
import com.habitrpg.wearos.habitica.models.user.Stats
import com.habitrpg.wearos.habitica.models.user.User
import com.habitrpg.wearos.habitica.ui.viewmodels.StatsViewModel
import com.habitrpg.wearos.habitica.ui.views.StatValue
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding, StatsViewModel>() {
override val viewModel: StatsViewModel by viewModels()
@ -18,14 +21,36 @@ class StatsActivity : BaseActivity<ActivityStatsBinding, StatsViewModel>() {
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityStatsBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
setStatViews()
setViews()
viewModel.user.observe(this) {
updateStats(it)
loadViews(it)
}
}
private fun setViews() {
binding.statsImageview.visibility = VISIBLE
loadingManager.startLoading()
setBarViews()
setStatViews()
}
private fun loadViews(user: User) {
binding.statsImageview.visibility = GONE
loadingManager.endLoading()
updateStats(user)
}
private fun setBarViews() {
binding.hpBar.visibility = INVISIBLE
binding.expBar.visibility = INVISIBLE
binding.mpBar.visibility = INVISIBLE
}
private fun setStatViews() {
binding.hpStatValue.visibility = INVISIBLE
binding.expStatValue.visibility = INVISIBLE
binding.mpStatValue.visibility = INVISIBLE
binding.hpStatValue.setStatValueResources(HabiticaIconsHelper.imageOfHeartLightBg(), R.color.hp_bar_color)
binding.expStatValue.setStatValueResources(HabiticaIconsHelper.imageOfExperience(), R.color.exp_bar_color)
binding.mpStatValue.setStatValueResources(HabiticaIconsHelper.imageOfMagic(), R.color.mpColor)
@ -38,6 +63,10 @@ class StatsActivity : BaseActivity<ActivityStatsBinding, StatsViewModel>() {
}
private fun updateBarViews(stats: Stats) {
binding.hpBar.visibility = VISIBLE
binding.expBar.visibility = VISIBLE
binding.mpBar.visibility = VISIBLE
binding.hpBar.setPercentageValues(stats.hp?.toFloat() ?: 0f, stats.maxHealth?.toFloat() ?: 0f)
binding.hpBar.animateProgress()
@ -45,7 +74,7 @@ class StatsActivity : BaseActivity<ActivityStatsBinding, StatsViewModel>() {
binding.expBar.animateProgress()
if ((stats.lvl ?: 0) < 10) {
binding.mpBar.visibility = View.GONE
binding.mpBar.visibility = GONE
} else {
binding.mpBar.setPercentageValues(stats.mp?.toFloat() ?: 0f, stats.maxMP?.toFloat() ?: 0f)
binding.mpBar.animateProgress()
@ -53,14 +82,19 @@ class StatsActivity : BaseActivity<ActivityStatsBinding, StatsViewModel>() {
}
private fun updateStatViews(stats: Stats) {
binding.hpStatValue.setStatValue(stats.maxHealth ?: 0, stats.hp?.toInt() ?: 0)
binding.expStatValue.setStatValue(stats.toNextLevel ?: 0, stats.exp?.toInt() ?: 0)
binding.hpStatValue.visibility = VISIBLE
binding.expStatValue.visibility = VISIBLE
binding.mpStatValue.visibility = VISIBLE
binding.hpStatValue.setStatValues(stats.maxHealth ?: 0, stats.hp?.toInt() ?: 0)
binding.expStatValue.setStatValues(stats.toNextLevel ?: 0, stats.exp?.toInt() ?: 0)
if ((stats.lvl ?: 0) < 10) {
binding.mpStatValue.visibility = View.GONE
binding.mpStatValue.visibility = GONE
} else {
binding.mpStatValue.setStatValue(stats.maxMP ?: 0, stats.mp?.toInt() ?: 0)
binding.mpStatValue.setStatValues(stats.maxMP ?: 0, stats.mp?.toInt() ?: 0)
}
}
}

View file

@ -1,5 +1,6 @@
package com.habitrpg.wearos.habitica.ui.views
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
@ -7,8 +8,15 @@ import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
import com.habitrpg.android.habitica.databinding.StatValueLayoutBinding
import com.habitrpg.common.habitica.extensions.layoutInflater
import kotlin.math.abs
import kotlin.math.ln
import kotlin.math.pow
class StatValue @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
class StatValue @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) :
ConstraintLayout(
context,
attrs,
@ -17,10 +25,12 @@ class StatValue @JvmOverloads constructor(context: Context, attrs: AttributeSet?
var binding = StatValueLayoutBinding.inflate(context.layoutInflater, this)
fun setStatValue(maxValue: Int, currentValue: Int) {
fun setStatValues(maxValue: Int, currentValue: Int) {
binding.currentValue.text = currentValue.toString()
binding.maxValue.text = "/$maxValue"
invalidate()
startUpdateCountAnimation(currentValue)
}
fun setStatValueResources(bitmap: Bitmap, bitmapColor: Int) {
@ -30,5 +40,27 @@ class StatValue @JvmOverloads constructor(context: Context, attrs: AttributeSet?
)
}
private fun startUpdateCountAnimation(statValue: Int) {
val animator = ValueAnimator.ofInt(0, statValue)
animator.duration = 1000
animator.addUpdateListener { animation ->
binding.currentValue.text =
(truncateFormat(animation.animatedValue.toString().toLong()))
}
animator.start()
}
private fun truncateFormat(statCount: Long): String {
//If we want to truncate and remove text after decimal (Example 1200 -> 1k)
if (statCount < 1000) return "" + statCount
return (statCount / 1000).toString() + "k";
//If we want to truncate including text after decimal (Example 1200 -> 1.2k)
// val exp = (ln(statCount.toDouble()) / ln(1000.0)).toInt()
// binding.currentValue.letterSpacing = -.07f
// return String.format("%.1f%c", statCount / 1000.0.pow(exp.toDouble()), "kMGTPE"[exp - 1])
}
}

View file

@ -4,6 +4,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/stats_imageview"
android:layout_width="35dp"
android:layout_height="35dp"
android:src="@drawable/icon_stats"
android:layout_centerInParent="true"/>
<com.habitrpg.wearos.habitica.ui.views.CircularProgressView
android:id="@+id/hp_bar"
android:layout_width="match_parent"
@ -37,17 +44,19 @@
<com.habitrpg.wearos.habitica.ui.views.StatValue
android:id="@+id/hp_stat_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"/>
<com.habitrpg.wearos.habitica.ui.views.StatValue
android:id="@+id/exp_stat_value"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_marginBottom="4dp"
android:layout_height="wrap_content" />
<com.habitrpg.wearos.habitica.ui.views.StatValue
android:id="@+id/mp_stat_value"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -4,8 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
tools:parentTag="com.habitrpg.wearos.habitica.ui.views.StatValue">
<View
@ -21,9 +19,10 @@
<ImageView
android:id="@+id/bitmap"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginBottom="2dp"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginBottom="5dp"
android:layout_marginEnd="6dp"
app:layout_constraintBottom_toBottomOf="@+id/current_value"
app:layout_constraintEnd_toStartOf="@+id/current_value"
app:layout_constraintTop_toTopOf="parent" />