1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-22 19:02:16 +00:00

fix: Water animation down is not working (#22)

This commit is contained in:
Florian Bouillon 2023-01-07 22:36:18 +01:00
parent 643861bf1e
commit 1f4ecc06ad
Signed by: Florian Bouillon
GPG Key ID: BEEAF3722D0EBF64
4 changed files with 136 additions and 51 deletions

View File

@ -21,6 +21,7 @@ import com.dzeio.openhealth.utils.GraphUtils
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import kotlin.math.max
import kotlin.math.min
@AndroidEntryPoint
class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewModel::class.java) {
@ -43,6 +44,10 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
)
}
/**
* Water Intake
*/
binding.fragmentHomeWaterAdd.setOnClickListener {
val water = viewModel.water.value
if (water == null || !water.isToday()) {
@ -75,14 +80,17 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
}
}
// handle button to go to weight home
binding.listWeight.setOnClickListener {
findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavListWeight())
}
// handle button to go to water intake home
binding.gotoWaterHome.setOnClickListener {
findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavWaterHome())
}
// Make a line Chart using the graph library
GraphUtils.lineChartSetup(
binding.weightGraph,
MaterialColors.getColor(
@ -95,6 +103,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
)
)
// Update the water intake Graph when the water intake changes
viewModel.water.observe(viewLifecycleOwner) {
if (it != null) {
updateWater(it.value)
@ -103,29 +112,41 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
}
}
// Update the steps Graph when the steps count changes
viewModel.steps.observe(viewLifecycleOwner) {
binding.stepsCurrent.text = it.toString()
}
// Update the steps Graph when the goal changes
viewModel.stepsGoal.observe(viewLifecycleOwner) {
if (it == null) {
binding.stepsTotal.text = ""
return@observe
}
binding.stepsTotal.text = it.toString()
}
// update the graph when the weight changes
viewModel.weights.observe(viewLifecycleOwner) {
if (it != null) {
updateGraph(it)
}
}
// update the graph when the goal weight change
viewModel.goalWeight.observe(viewLifecycleOwner) {
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
}
// update the graph when the weight unit change
viewModel.massUnit.observe(viewLifecycleOwner) {
if (viewModel.weights.value != null) updateGraph(viewModel.weights.value!!)
}
}
/**
* Function that update the graph for the weight
*/
private fun updateGraph(list: List<Weight>) {
WeightChart.setup(
binding.weightGraph,
@ -134,40 +155,37 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
viewModel.massUnit.value!!,
viewModel.goalWeight.value
)
// legend.apply {
// isEnabled = true
// form = Legend.LegendForm.LINE
//
// if (goal != null) {
// val legendEntry = LegendEntry().apply {
// label = "Weight Goal"
// formColor = Color.RED
// }
// setCustom(arrayOf(legendEntry))
// }
// }
}
/**
* the waterintake old value to keep for value update
*/
private var oldValue = 0f
/**
* function that update the water count in the home page
*/
private fun updateWater(newValue: Int) {
// get the current Unit
val waterUnit =
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
// Update the count
binding.fragmentHomeWaterCurrent.text =
String.format(
resources.getString(waterUnit.unit),
(newValue * waterUnit.modifier).toInt()
)
// TODO: move it elsewhere
binding.fragmentHomeWaterTotal.text =
String.format(
resources.getString(waterUnit.unit),
viewModel.dailyWaterIntake
)
// get the with/height of the ImageView
var width = 1500
var height = 750
@ -177,6 +195,7 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
}
// Prepare the update animation
val animator = ValueAnimator.ofInt(
this.oldValue.toInt(),
newValue
@ -186,7 +205,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
this.oldValue = (it.animatedValue as Int).toFloat()
val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake.toFloat()
// Log.d("Test2", "${this.oldValue}")
val graph = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(graph)
@ -209,9 +227,10 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
3f
)
// Draw the big Arc
DrawUtils.drawArc(
canvas,
max(value, 1f),
min(max(value, 0.01f), 100f),
rect,
MaterialColors.getColor(
requireView(),
@ -219,9 +238,15 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
),
6f
)
// save the canvas
canvas.save()
// send it
binding.background.setImageBitmap(graph)
}
// start the animation
animator.start()
}
}

View File

@ -1,6 +1,5 @@
package com.dzeio.openhealth.ui.home
import android.content.SharedPreferences
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
@ -11,7 +10,6 @@ import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.water.WaterRepository
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.UnitFactory
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
@ -24,51 +22,73 @@ class HomeViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
private val waterRepository: WaterRepository,
stepRepository: StepRepository,
settings: SharedPreferences,
config: Configuration
) : BaseViewModel() {
private val _steps = MutableLiveData(0)
/**
* Steps taken today by the user
*/
val steps: LiveData<Int> = _steps
private val _stepsGoal: MutableLiveData<Int?> = MutableLiveData()
val stepsGoal: LiveData<Int?> = _stepsGoal
/**
* Number of steps the use should do today
*/
val stepsGoal: LiveData<Int?> = config.getInt(Settings.STEPS_GOAL).toLiveData()
private val _water = MutableLiveData<Water?>(null)
/**
* Quantity of water the user drank today
*/
val water: LiveData<Water?> = _water
private val _weights = MutableLiveData<List<Weight>?>(null)
/**
* The list of weight of the user
*/
val weights: LiveData<List<Weight>?> = _weights
/**
* The size of a cup for the quick water intake add
*/
var waterCupSize = config.getInt("water_cup_size").toLiveData()
var waterUnit =
UnitFactory.volume(settings.getString("water_unit", "milliliter") ?: "Milliliter")
/**
* The unit used to display the water intake of the user
*/
var waterUnit = Units.Volume.find(config.getString("water_unit").value ?: "ml")
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
/**
* The Mass unit used by the user
*/
val massUnit: LiveData<Units.Mass> = _massUnit
/**
* the User weight goal
*/
val goalWeight = config.getFloat(Settings.WEIGHT_GOAL).toLiveData()
val dailyWaterIntake: Int =
((settings.getString("water_intake", "1200")?.toFloatOrNull() ?: 1200f) * waterUnit.modifier)
.toInt()
val dailyWaterIntake: Float = (config.getFloat("water_intake").value ?: 1200f) * waterUnit.modifier
init {
// Fetch today's water intake
viewModelScope.launch {
waterRepository.todayWater().collectLatest {
_water.postValue(it)
}
}
// Fetch the user weights
viewModelScope.launch {
_steps.postValue(stepRepository.todaySteps())
}
this._stepsGoal.postValue(
config.getInt(Settings.STEPS_GOAL).value
)
// fetch the user weights
viewModelScope.launch {
weightRepository.getWeights().collectLatest {
_weights.postValue(it)
@ -86,24 +106,6 @@ class HomeViewModel @Inject internal constructor(
}
}
/**
* @deprecated
*/
fun fetchWeights() = weightRepository.getWeights()
/**
* @deprecated
*/
fun lastWeight() = weightRepository.lastWeight()
fun fetchWeight(id: Long) = weightRepository.getWeight(id)
suspend fun deleteWeight(weight: Weight) = weightRepository.deleteWeight(weight)
suspend fun addWeight(weight: Weight) = weightRepository.addWeight(weight)
fun fetchTodayWater() = waterRepository.todayWater()
fun updateWater(water: Water) {
viewModelScope.launch {
waterRepository.addWater(water)

View File

@ -20,12 +20,10 @@ import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.timepicker.MaterialTimePicker
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
import java.util.*
@AndroidEntryPoint
class EditWeightDialog :
BaseFullscreenDialog<HomeViewModel, DialogEditWeightBinding>(HomeViewModel::class.java) {
BaseFullscreenDialog<EditWeightDialogViewModel, DialogEditWeightBinding>(HomeViewModel::class.java) {
override val bindingInflater: (LayoutInflater) -> DialogEditWeightBinding =
DialogEditWeightBinding::inflate
@ -146,4 +144,4 @@ class EditWeightDialog :
}
}
}
}

View File

@ -0,0 +1,60 @@
package com.dzeio.openhealth.ui.weight
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.Settings
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class EditWeightDialogViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
config: Configuration
) : BaseViewModel() {
private val _water = MutableLiveData<Water?>(null)
/**
* Quantity of water the user drank today
*/
val water: LiveData<Water?> = _water
private val _weights = MutableLiveData<List<Weight>?>(null)
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
init {
// fetch the user weights
viewModelScope.launch {
weightRepository.getWeights().collectLatest {
_weights.postValue(it)
}
}
config.getString(Settings.MASS_UNIT).apply {
addObserver {
if (it == null) return@addObserver
_massUnit.postValue(Units.Mass.find(it))
}
if (value != null) {
_massUnit.postValue(Units.Mass.find(value!!))
}
}
}
fun fetchWeight(id: Long) = weightRepository.getWeight(id)
suspend fun deleteWeight(weight: Weight) = weightRepository.deleteWeight(weight)
suspend fun addWeight(weight: Weight) = weightRepository.addWeight(weight)
}