From efa21e28c04602780074de3b5014267b5d16a7df Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 9 May 2022 16:38:22 +0200 Subject: [PATCH] more animations --- Habitica/res/drawable/circle_gray_700.xml | 4 + Habitica/res/layout/activity_armoire.xml | 125 +++++++++++------- Habitica/res/layout/can_hatch_item.xml | 41 ++++++ Habitica/res/layout/purchase_gem_view.xml | 4 + Habitica/res/values/attrs.xml | 10 +- .../android/habitica/helpers/Animations.kt | 86 ++++++++++++ .../habitica/ui/AvatarWithBarsViewModel.kt | 4 + .../habitica/ui/activities/ArmoireActivity.kt | 39 +++++- .../inventory/PetDetailRecyclerAdapter.kt | 125 ++++++++++++++++-- .../habitica/ui/viewHolders/PetViewHolder.kt | 11 -- .../habitica/ui/views/HabiticaProgressBar.kt | 26 ++-- .../android/habitica/ui/views/SparkView.kt | 104 +++++++++++++++ .../android/habitica/ui/views/ValueBar.kt | 17 ++- .../android/habitica/ui/views/ads/AdButton.kt | 4 +- .../habitica/ui/views/social/QuestMenuView.kt | 20 +-- 15 files changed, 513 insertions(+), 107 deletions(-) create mode 100644 Habitica/res/drawable/circle_gray_700.xml create mode 100644 Habitica/res/layout/can_hatch_item.xml create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/helpers/Animations.kt create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/SparkView.kt diff --git a/Habitica/res/drawable/circle_gray_700.xml b/Habitica/res/drawable/circle_gray_700.xml new file mode 100644 index 000000000..a6defe225 --- /dev/null +++ b/Habitica/res/drawable/circle_gray_700.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Habitica/res/layout/activity_armoire.xml b/Habitica/res/layout/activity_armoire.xml index 43eacc7bc..bbcaf28b5 100644 --- a/Habitica/res/layout/activity_armoire.xml +++ b/Habitica/res/layout/activity_armoire.xml @@ -13,52 +13,85 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:gravity="center_horizontal" - android:paddingTop="19dp"> - - - - - - - - + + - + android:orientation="vertical" + android:gravity="center_horizontal"> + + + + + + + + + + + diff --git a/Habitica/res/layout/can_hatch_item.xml b/Habitica/res/layout/can_hatch_item.xml new file mode 100644 index 000000000..602982584 --- /dev/null +++ b/Habitica/res/layout/can_hatch_item.xml @@ -0,0 +1,41 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/purchase_gem_view.xml b/Habitica/res/layout/purchase_gem_view.xml index b83800c33..8635a9a37 100644 --- a/Habitica/res/layout/purchase_gem_view.xml +++ b/Habitica/res/layout/purchase_gem_view.xml @@ -17,6 +17,10 @@ android:contentDescription="@string/gems" android:layout_marginTop="20dp"/> + + + @@ -101,7 +102,7 @@ - + @@ -160,4 +161,11 @@ + + + + + + + diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/Animations.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/Animations.kt new file mode 100644 index 000000000..b92c764c7 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/Animations.kt @@ -0,0 +1,86 @@ +package com.habitrpg.android.habitica.helpers + +import android.view.View +import android.view.ViewAnimationUtils +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.AlphaAnimation +import android.view.animation.Animation +import android.view.animation.Animation.INFINITE +import android.view.animation.Animation.RELATIVE_TO_SELF +import android.view.animation.Animation.REVERSE +import android.view.animation.AnimationSet +import android.view.animation.LinearInterpolator +import android.view.animation.RotateAnimation +import android.view.animation.TranslateAnimation +import androidx.core.animation.doOnEnd +import kotlin.random.Random + +object Animations { + private fun randomFloat(min: Float, max: Float): Float { + return min + Random.nextFloat() * (max - min) + } + + fun bobbingAnimation(amount: Float = 8f): Animation { + val anim = TranslateAnimation(0f, 0f, -amount, amount) + anim.duration = 2500 + anim.interpolator = AccelerateDecelerateInterpolator() + anim.repeatCount = INFINITE + anim.repeatMode = REVERSE + return anim + } + + fun negativeShakeAnimation(intensity: Float = 1f): Animation { + val anim = AnimationSet(true) + anim.interpolator = LinearInterpolator() + + val translate = TranslateAnimation(randomFloat(-2f * intensity, 0f), randomFloat(0f, 2f * intensity), randomFloat(-1f * intensity, 0f), randomFloat(0f, 1f * intensity)) + translate.duration = 70 + translate.repeatCount = 5 + translate.repeatMode = REVERSE + anim.addAnimation(translate) + + val rotate = RotateAnimation(randomFloat(-0.4f * intensity, 0f), randomFloat(0f, 0.4f * intensity), RELATIVE_TO_SELF, 0.5f, RELATIVE_TO_SELF, 0.5f) + rotate.duration = 70 + rotate.repeatCount = 5 + rotate.repeatMode = REVERSE + anim.addAnimation(rotate) + + return anim + } + + fun circularReveal(view: View, duration: Long = 300) { + val cx = view.width / 2 + val cy = view.height / 2 + val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() + val anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0f, finalRadius) + anim.duration = duration + view.visibility = View.VISIBLE + anim.start() + } + + fun circularHide(view: View) { + val cx = view.width / 2 + val cy = view.height / 2 + val initialRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() + val anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0f) + anim.doOnEnd { + view.visibility = View.INVISIBLE + } + anim.start() + } + + fun fadeInAnimation(duration: Long = 300): Animation { + val anim = AlphaAnimation(0f, 1f) + anim.interpolator = AccelerateDecelerateInterpolator() + anim.fillBefore = true + anim.fillAfter = true + anim.duration = duration + return anim + } + + fun fadeOutAnimation(): Animation { + val anim = AlphaAnimation(1f, 0f) + anim.interpolator = AccelerateDecelerateInterpolator() + return anim + } +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt index bf6a1a385..ac9b8dee7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt @@ -9,6 +9,7 @@ import androidx.core.os.bundleOf import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.databinding.AvatarWithBarsBinding +import com.habitrpg.android.habitica.helpers.Animations import com.habitrpg.android.habitica.helpers.HealthFormatter import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.models.Avatar @@ -96,6 +97,9 @@ class AvatarWithBarsViewModel( if (valueMax != 0) { cachedMaxHealth = valueMax } + if (binding.hpBar.currentValue > value) { + binding.hpBar.progressBar.startAnimation(Animations.negativeShakeAnimation()) + } binding.hpBar.set(HealthFormatter.format(value.toDouble()), cachedMaxHealth.toDouble()) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt index e00125826..cebcdc579 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ArmoireActivity.kt @@ -6,22 +6,26 @@ import android.view.Gravity import android.view.View import android.view.animation.AccelerateInterpolator import android.widget.FrameLayout +import android.widget.RelativeLayout import androidx.core.content.ContextCompat import androidx.lifecycle.lifecycleScope import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.databinding.ActivityArmoireBinding +import com.habitrpg.android.habitica.extensions.dpToPx import com.habitrpg.android.habitica.extensions.observeOnce import com.habitrpg.android.habitica.helpers.AdHandler import com.habitrpg.android.habitica.helpers.AdType +import com.habitrpg.android.habitica.helpers.Animations import com.habitrpg.android.habitica.helpers.AppConfigManager import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.ui.helpers.loadImage import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel import com.habitrpg.android.habitica.ui.views.ads.AdButton import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaBottomSheetDialog import com.plattysoft.leonids.ParticleSystem +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import javax.inject.Inject class ArmoireActivity: BaseActivity() { @@ -86,7 +90,7 @@ class ArmoireActivity: BaseActivity() { }, RxErrorHandler.handleEmptyError())) } handler.prepare { - if (it && binding.adButton.state == AdButton.State.EMPTY) { + if (it && binding.adButton.state == AdButton.State.LOADING) { binding.adButton.state = AdButton.State.READY } else if (!it) { binding.adButton.visibility = View.INVISIBLE @@ -141,6 +145,34 @@ class ArmoireActivity: BaseActivity() { }, 500 ) + + + binding.iconView.startAnimation(Animations.bobbingAnimation()) + binding.titleView.alpha = 0f + binding.subtitleView.alpha = 0f + + lifecycleScope.launch { + delay(100) + if (binding.iconWrapper.isAttachedToWindow) { + Animations.circularReveal(binding.iconWrapper, 400) + } + binding.leftSparkView.startAnimating() + binding.rightSparkView.startAnimating() + } + + binding.titleView.animate().apply { + alpha(1f) + duration = 400 + startDelay = 600 + start() + } + binding.subtitleView.animate().apply { + alpha(1f) + duration = 400 + startDelay = 900 + start() + } + hasAnimatedChanges = true } @@ -171,8 +203,9 @@ class ArmoireActivity: BaseActivity() { binding.iconView.loadImage("Pet_Food_$key") } else -> { - binding.subtitleView.text = getString(R.string.armoireExp, value) + binding.subtitleView.text = getString(R.string.armoireExp_new, value) binding.iconView.setImageResource(R.drawable.armoire_experience) + binding.iconView.layoutParams = RelativeLayout.LayoutParams(108.dpToPx(this), 122.dpToPx(this)) } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt index 690e26b64..018d96d6d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt @@ -1,6 +1,11 @@ package com.habitrpg.android.habitica.ui.adapter.inventory +import android.view.View import android.view.ViewGroup +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.databinding.CanHatchItemBinding +import com.habitrpg.android.habitica.extensions.inflate +import com.habitrpg.android.habitica.helpers.Animations import com.habitrpg.android.habitica.models.inventory.Animal import com.habitrpg.android.habitica.models.inventory.Egg import com.habitrpg.android.habitica.models.inventory.Food @@ -11,8 +16,10 @@ import com.habitrpg.android.habitica.models.inventory.StableSection import com.habitrpg.android.habitica.models.user.OwnedItem import com.habitrpg.android.habitica.models.user.OwnedMount import com.habitrpg.android.habitica.models.user.OwnedPet +import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.viewHolders.PetViewHolder import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder +import com.habitrpg.android.habitica.ui.views.dialogs.PetSuggestHatchDialog import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.subjects.PublishSubject @@ -66,6 +73,7 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder = when (viewType) { 1 -> SectionViewHolder(parent) + 2 -> CanHatchViewHolder(parent, animalIngredientsRetriever) else -> PetViewHolder(parent, equipEvents, feedEvents, animalIngredientsRetriever) } @@ -78,23 +86,50 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt (holder as? SectionViewHolder)?.bind(obj) } is Pet -> { - (holder as? PetViewHolder)?.bind( - obj, - ownedPets?.get(obj.key ?: "")?.trained ?: 0, - eggCount(obj), - potionCount(obj), - canRaiseToMount(obj), - ownsSaddles, - ownedItems?.get(obj.animal + "-eggs") != null, - ownedItems?.get(obj.color + "-hatchingPotions") != null, - ownedMounts?.containsKey(obj.key) == true, - currentPet - ) + val trained = ownedPets?.get(obj.key ?: "")?.trained ?: 0 + val eggCount = eggCount(obj) + val potionCount = potionCount(obj) + if (trained <= 0 && eggCount > 0 && potionCount > 0) { + (holder as? CanHatchViewHolder)?.bind( + obj, + eggCount, + potionCount, + ownedItems?.get(obj.animal + "-eggs") != null, + ownedItems?.get(obj.color + "-hatchingPotions") != null, + ownedMounts?.containsKey(obj.key) == true, + ) + } else { + (holder as? PetViewHolder)?.bind( + obj, + trained, + eggCount, + potionCount, + canRaiseToMount(obj), + ownsSaddles, + ownedItems?.get(obj.animal + "-eggs") != null, + ownedItems?.get(obj.color + "-hatchingPotions") != null, + ownedMounts?.containsKey(obj.key) == true, + currentPet + ) + } + } } } - override fun getItemViewType(position: Int): Int = if (itemList.size > position && itemList[position] is StableSection) 1 else 2 + override fun getItemViewType(position: Int): Int { + if (itemList.size <= position) return 3 + return if (itemList[position] is StableSection) { + 1 + } else { + val pet = itemList[position] as Pet + if (ownedPets?.get(pet.key ?: "")?.trained ?: 0 <= 0 && eggCount(pet) > 0 && potionCount(pet) > 0) { + 2 + } else { + 3 + } + } + } override fun getItemCount(): Int = itemList.size @@ -118,4 +153,68 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt ownsSaddles = if (ownedItems.containsKey("Saddle-food")) (ownedItems["Saddle-food"]?.numberOwned ?: 0) > 0 else false notifyDataSetChanged() } + + class CanHatchViewHolder( + parent: ViewGroup, + private val ingredientsReceiver: ((Animal, ((Pair) -> Unit)) -> Unit)? + ) : androidx.recyclerview.widget.RecyclerView.ViewHolder(parent.inflate(R.layout.can_hatch_item)), + View.OnClickListener { + private var binding = CanHatchItemBinding.bind(itemView) + + private var hasMount: Boolean = false + private var hasUnlockedPotion: Boolean = false + private var hasUnlockedEgg: Boolean = false + private var eggCount: Int = 0 + private var potionCount: Int = 0 + private var animal: Pet? = null + + init { + itemView.setOnClickListener(this) + } + + fun bind( + item: Pet, + eggCount: Int, + potionCount: Int, + hasUnlockedEgg: Boolean, + hasUnlockedPotion: Boolean, + hasMount: Boolean, + ) { + this.animal = item + this.eggCount = eggCount + this.potionCount = potionCount + this.hasUnlockedEgg = hasUnlockedEgg + this.hasUnlockedPotion = hasUnlockedPotion + this.hasMount = hasMount + + DataBindingUtils.loadImage(binding.eggView, "Pet_Egg_${item.animal}") + DataBindingUtils.loadImage( + binding.hatchingPotionView, + "Pet_HatchingPotion_${item.color}" + ) + + binding.eggView.startAnimation(Animations.bobbingAnimation(4f)) + binding.hatchingPotionView.startAnimation(Animations.bobbingAnimation(-4f)) + } + + override fun onClick(p0: View?) { + val context = itemView.context + val dialog = PetSuggestHatchDialog(context) + animal?.let { + ingredientsReceiver?.invoke(it) { ingredients -> + dialog.configure( + it, + ingredients.first, + ingredients.second, + eggCount, + potionCount, + hasUnlockedEgg, + hasUnlockedPotion, + hasMount + ) + dialog.show() + } + } + } + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/PetViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/PetViewHolder.kt index 40ac5124e..c5567aa55 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/PetViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/PetViewHolder.kt @@ -89,17 +89,6 @@ class PetViewHolder( } else { binding.trainedProgressBar.visibility = View.GONE binding.imageView.alpha = 0.2f - if (canHatch) { - binding.imageView.visibility = View.GONE - binding.itemWrapper.visibility = View.VISIBLE - binding.checkmarkView.visibility = View.VISIBLE - itemView.setBackgroundResource(R.drawable.layout_rounded_bg_window_tint_border) - DataBindingUtils.loadImage(binding.eggView, "Pet_Egg_${item.animal}") - DataBindingUtils.loadImage( - binding.hatchingPotionView, - "Pet_HatchingPotion_${item.color}" - ) - } } if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaProgressBar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaProgressBar.kt index ba7597093..fd496f576 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaProgressBar.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaProgressBar.kt @@ -45,8 +45,20 @@ class HabiticaProgressBar(context: Context, attrs: AttributeSet?) : FrameLayout( } } - private var currentValue: Double = 0.0 - private var maxValue: Double = 0.0 + var currentValue: Double = 0.0 + set(value) { + if (field != value) { + field = value + updateBar() + } + } + var maxValue: Double = 0.0 + set(value) { + if (field != value) { + field = value + updateBar() + } + } var pendingValue: Double = 0.0 set(value) { @@ -97,16 +109,6 @@ class HabiticaProgressBar(context: Context, attrs: AttributeSet?) : FrameLayout( updateBar() } - fun setCurrentValue(value: Double) { - currentValue = value - updateBar() - } - - fun setMaxValue(value: Double) { - maxValue = value - updateBar() - } - private fun setLayoutWeight(view: View, weight: Double) { view.clearAnimation() val layout = view.layoutParams as? LinearLayout.LayoutParams diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/SparkView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/SparkView.kt new file mode 100644 index 000000000..05f51bcfb --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/SparkView.kt @@ -0,0 +1,104 @@ +package com.habitrpg.android.habitica.ui.views + +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.Animation +import androidx.core.content.ContextCompat +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.extensions.dpToPx +import kotlin.math.min + +class SparkView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + private var spacing: Float = 0f + set(value) { + field = value + invalidate() + } + private var paint: Paint = Paint() + + var thickness = 3.dpToPx(context) + var length = 6.dpToPx(context) + var maxSpacing = 5.dpToPx(context) + var animationDuration = 2500L + var color: Int + get() { + return paint.color + } + set(value) { + paint.color = value + } + + init { + spacing = maxSpacing.toFloat() + context.theme?.obtainStyledAttributes(attrs, R.styleable.SparkView, 0, 0)?.let { + thickness = it.getDimensionPixelSize(R.styleable.SparkView_thickness, 3.dpToPx(context)) + length = it.getDimensionPixelSize(R.styleable.SparkView_length, 6.dpToPx(context)) + maxSpacing = it.getDimensionPixelSize(R.styleable.SparkView_maxSpacing, 5.dpToPx(context)) + animationDuration = it.getInt(R.styleable.SparkView_duration, 2500).toLong() + color = it.getInt(R.styleable.SparkView_color, ContextCompat.getColor(context, R.color.white)) + } + + paint.style = Paint.Style.FILL + } + + fun startAnimating() { + val anim = ObjectAnimator.ofFloat(thickness.toFloat(), maxSpacing.toFloat()) + anim.addUpdateListener { + spacing = it.animatedValue as Float + } + anim.interpolator = AccelerateDecelerateInterpolator() + anim.repeatCount = Animation.INFINITE + anim.repeatMode = ValueAnimator.REVERSE + anim.duration = animationDuration + anim.start() + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val widthSize = MeasureSpec.getSize(widthMeasureSpec) + val heightSize = MeasureSpec.getSize(heightMeasureSpec) + val desiredSize = (length * 2 + maxSpacing) + + val width = when (MeasureSpec.getMode(widthMeasureSpec)) { + MeasureSpec.EXACTLY -> widthSize + MeasureSpec.AT_MOST -> min(desiredSize, widthSize) + else -> desiredSize + } + + val height = when (MeasureSpec.getMode(heightMeasureSpec)) { + MeasureSpec.EXACTLY -> heightSize + MeasureSpec.AT_MOST -> min(desiredSize, heightSize) + else -> desiredSize + } + + setMeasuredDimension(width, height) + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + val thisCanvas = canvas ?: return + val centerHorizontal = width / 2f + val centerVertical = height / 2f + val offset = (maxSpacing - spacing)/2 + drawHorizontal(thisCanvas, offset, centerVertical) + drawHorizontal(thisCanvas, width - length.toFloat() - offset, centerVertical) + + drawVertical(thisCanvas, centerHorizontal, offset) + drawVertical(thisCanvas, centerVertical, height - length.toFloat() - offset) + } + + private fun drawVertical(canvas: Canvas, x: Float, y: Float) { + canvas.drawRoundRect(x-(thickness/2), y, x+(thickness/2), y+length, thickness/2f, thickness/2f, paint) + } + + private fun drawHorizontal(canvas: Canvas, x: Float, y: Float) { + canvas.drawRoundRect(x, y-(thickness/2), x+length, y+(thickness/2), thickness/2f, thickness/2f, paint) + } +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt index d970d12e6..fc652a3a9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt @@ -28,8 +28,19 @@ class ValueBar(context: Context, attrs: AttributeSet?) : FrameLayout(context, at private var binding: ValueBarBinding = ValueBarBinding.inflate(context.layoutInflater, this, true) private val formatter = NumberFormat.getInstance() - private var currentValue: Double = 0.0 - private var maxValue: Double = 0.0 + val progressBar: HabiticaProgressBar + get() = binding.progressBar + + var currentValue: Double + get() = binding.progressBar.currentValue + set(value) { + binding.progressBar.currentValue = value + } + var maxValue: Double + get() = binding.progressBar.maxValue + set(value) { + binding.progressBar.maxValue = value + } var barForegroundColor: Int get() = binding.progressBar.barForegroundColor @@ -169,7 +180,7 @@ class ValueBar(context: Context, attrs: AttributeSet?) : FrameLayout(context, at var animationDelay = 0L fun set(value: Double, valueMax: Double) { - if (currentValue != value || maxValue != valueMax) { + if (binding.progressBar.currentValue != value || maxValue != valueMax) { if (animationDuration == 0L || binding.valueTextView.text.isEmpty()) { currentValue = value } else { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ads/AdButton.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ads/AdButton.kt index 6f2ad0075..a67ef1973 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ads/AdButton.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ads/AdButton.kt @@ -25,7 +25,7 @@ class AdButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null ) : LinearLayout(context, attrs) { - var state: State = State.EMPTY + var state: State = State.LOADING set(value) { field = value updateViews() @@ -61,7 +61,7 @@ class AdButton @JvmOverloads constructor( binding.currencyView.setTextColor(ContextCompat.getColor(context, R.color.white)) binding.currencyView.value = 0.0 gravity = Gravity.CENTER - state = State.EMPTY + state = State.LOADING } private fun updateViews() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt index 803aa3918..4b7225af6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt @@ -36,30 +36,22 @@ class QuestMenuView : LinearLayout { binding.rageIconView.setImageBitmap(HabiticaIconsHelper.imageOfRage()) binding.pendingDamageIconView.setImageBitmap(HabiticaIconsHelper.imageOfDamage()) - - /*binding.closeButton.setOnClickListener { - hideBossArt() - val preferences = context.getSharedPreferences("collapsible_sections", 0) - preferences?.edit { - putBoolean("boss_art_collapsed", true) - } - }*/ } fun configure(quest: Quest) { - binding.healthBarView.setCurrentValue(quest.progress?.hp ?: 0.0) - binding.rageBarView.setCurrentValue(quest.progress?.rage ?: 0.0) + binding.healthBarView.currentValue = quest.progress?.hp ?: 0.0 + binding.rageBarView.currentValue = quest.progress?.rage ?: 0.0 } fun configure(questContent: QuestContent) { this.questContent = questContent - binding.healthBarView.setMaxValue(questContent.boss?.hp?.toDouble() ?: 0.0) + binding.healthBarView.maxValue = questContent.boss?.hp?.toDouble() ?: 0.0 binding.bossNameView.text = questContent.boss?.name binding.typeTextView.text = context.getString(R.string.boss_quest) if (questContent.boss?.hasRage == true) { binding.rageView.visibility = View.VISIBLE - binding.rageBarView.setMaxValue(questContent.boss?.rage?.value ?: 0.0) + binding.rageBarView.maxValue = questContent.boss?.rage?.value ?: 0.0 } else { binding.rageView.visibility = View.GONE } @@ -74,9 +66,7 @@ class QuestMenuView : LinearLayout { binding.topView.setBackgroundColor(questContent?.colors?.mediumColor ?: 0) binding.bossNameView.gravity = Gravity.START binding.bossNameView.layoutParams = LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1F) - // binding.bossArtView.visibility = View.GONE binding.typeTextView.setTextColor(questContent?.colors?.extraLightColor ?: 0) - // binding.closeButton.visibility = View.GONE } fun showBossArt() { @@ -84,8 +74,6 @@ class QuestMenuView : LinearLayout { binding.topView.setBackgroundColor(ContextCompat.getColor(context, R.color.transparent)) binding.bossNameView.gravity = Gravity.END binding.bossNameView.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - // binding.bossArtView.visibility = View.VISIBLE binding.typeTextView.setTextColor(ContextCompat.getColor(context, R.color.white)) - // binding.closeButton.visibility = View.VISIBLE } }