实现了热量值计算

This commit is contained in:
zxj
2025-08-04 18:02:45 +08:00
parent 5ae72cdf04
commit c6badf2ca7
14 changed files with 431 additions and 32 deletions
@@ -54,6 +54,7 @@ class MainActivity : AppCompatActivity() {
private var checkedItem: FoodInfo? = null private var checkedItem: FoodInfo? = null
private var imageAnalysis: ImageAnalysis? = null private var imageAnalysis: ImageAnalysis? = null
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
private var canIdentify: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -156,14 +157,15 @@ class MainActivity : AppCompatActivity() {
} }
} }
viewModel.getIdentifiedFoodList() viewModel.getIdentifiedFoodList()
// SensorScaleUtils.startScale { weight -> SensorScaleUtils.startScale { weight ->
// Timber.d("weight = $weight") // Timber.d("weight = $weight")
// if (weight > 0.0) { if (weight > 0.0) {
// if (canIndentify) { if (canIdentify) {
// viewModel.getIdentifiedFoodList() canIdentify = false
// } viewModel.getIdentifiedFoodList()
// } }
// } }
}
} }
private fun createAdapter(): GenericItemAdapter<FoodInfo, ItemFoodInfoBinding> { private fun createAdapter(): GenericItemAdapter<FoodInfo, ItemFoodInfoBinding> {
@@ -55,6 +55,8 @@ val Float.sp: Float
Resources.getSystem().displayMetrics Resources.getSystem().displayMetrics
) )
fun Double.format2String(): String = "%.1f".format(this)
// 添加扩展函数 // 添加扩展函数
fun ImageProxy.toSafeBitmap(): Bitmap { fun ImageProxy.toSafeBitmap(): Bitmap {
val yBuffer = planes[0].buffer // Y val yBuffer = planes[0].buffer // Y
@@ -0,0 +1,42 @@
package com.sw.dualscreen.model.response
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
data class DinnerTypeInfo(
@SerializedName("dinnerType")
val dinnerType: DinnerType? = DinnerType()
) : Parcelable {
@Parcelize
data class DinnerType(
@SerializedName("createBy")
val createBy: String? = "",
@SerializedName("createTime")
val createTime: String? = "",
@SerializedName("delFlag")
val delFlag: Int? = 0,
@SerializedName("dinnerType")
val dinnerType: String? = "",
@SerializedName("endTime")
val endTime: String? = "",
@SerializedName("id")
val id: Int? = 0,
@SerializedName("isSync")
val isSync: Int? = 0,
@SerializedName("isSyncCopy")
val isSyncCopy: Int? = 0,
@SerializedName("restId")
val restId: String? = "",
@SerializedName("startTime")
val startTime: String? = "",
@SerializedName("sysOrgCode")
val sysOrgCode: String? = "",
@SerializedName("updateBy")
val updateBy: String? = "",
@SerializedName("updateTime")
val updateTime: String? = ""
) : Parcelable
}
@@ -2,6 +2,7 @@ package com.sw.dualscreen.model.response
import android.os.Parcelable import android.os.Parcelable
import android.text.TextUtils
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@@ -206,7 +207,28 @@ data class FoodInfo(
val vegetable: String? = "", val vegetable: String? = "",
@SerializedName("vegetableRecommend") @SerializedName("vegetableRecommend")
val vegetableRecommend: String? = "" val vegetableRecommend: String? = ""
) : Parcelable ) : Parcelable {
fun fruitsValue(): Double =
if (TextUtils.isEmpty(fruits))
0.0
else fruits!!.toDouble()
fun grainValue(): Double =
if (TextUtils.isEmpty(grain))
0.0
else grain!!.toDouble()
fun vegetableValue(): Double =
if (TextUtils.isEmpty(vegetable))
0.0
else vegetable!!.toDouble()
fun meatValue(): Double =
if (TextUtils.isEmpty(meat))
0.0
else meat!!.toDouble()
}
@Parcelize @Parcelize
data class StFoodInfoSetting( data class StFoodInfoSetting(
@@ -2,6 +2,7 @@ package com.sw.dualscreen.model.response
import android.os.Parcelable import android.os.Parcelable
import android.text.TextUtils
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@@ -9,69 +10,172 @@ import kotlinx.parcelize.Parcelize
* 就餐数据 * 就餐数据
*/ */
@Parcelize @Parcelize
data class NutritionData( data class UserNutritionData(
/**
* 总胆固醇
*/
@SerializedName("cho") @SerializedName("cho")
val cho: String? = "", val cho: String? = "",
/**
* 饮食纤维
*/
@SerializedName("dietFiber") @SerializedName("dietFiber")
val dietFiber: String? = "", val dietFiber: String? = "",
/**
* 能量
*/
@SerializedName("energy") @SerializedName("energy")
val energy: String? = "", val energy: String? = "",
/**
* 脂肪
*/
@SerializedName("fat") @SerializedName("fat")
val fat: String? = "", val fat: String? = "",
/**
* 食物类型和实际摄入量清单
*/
@SerializedName("foodTypeAndRealIntakeVoList") @SerializedName("foodTypeAndRealIntakeVoList")
val foodTypeAndRealIntakeVoList: List<String?>? = listOf(), val foodTypeAndRealIntakeVoList: List<String?>? = listOf(),
@SerializedName("foodWeight") @SerializedName("foodWeight")
val foodWeight: String? = "", val foodWeight: String? = "",
@SerializedName("message") @SerializedName("message")
val message: String? = "", val message: String? = "",
/**
*
*/
@SerializedName("na") @SerializedName("na")
val na: String? = "", val na: String? = "",
/**
* 蛋白质
*/
@SerializedName("protein") @SerializedName("protein")
val protein: String? = "", val protein: String? = "",
/**
* 最大推荐热量
*/
@SerializedName("recommendMax") @SerializedName("recommendMax")
val recommendMax: String? = "", val recommendMax: String? = "",
/**
* 最小推荐热量
*/
@SerializedName("recommendMin") @SerializedName("recommendMin")
val recommendMin: String? = "", val recommendMin: String? = "",
/**
* 热量详情
*/
@SerializedName("stFoodInfoPagoda") @SerializedName("stFoodInfoPagoda")
val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(), val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(),
@SerializedName("stUserFoodInfoList") @SerializedName("stUserFoodInfoList")
val stUserFoodInfoList: List<String?>? = listOf(), val stUserFoodInfoList: List<String?>? = listOf(),
/**
* 每日总热量
*/
@SerializedName("totalEnergyCalculateScore") @SerializedName("totalEnergyCalculateScore")
val totalEnergyCalculateScore: String? = "", val totalEnergyCalculateScore: String? = "",
/**
* 用户所在部门
*/
@SerializedName("userDept") @SerializedName("userDept")
val userDept: String? = "", val userDept: String? = "",
/**
* 用户id
*/
@SerializedName("userId") @SerializedName("userId")
val userId: String? = "", val userId: String? = "",
/**
* 姓名
*/
@SerializedName("userName") @SerializedName("userName")
val userName: String? = "" val userName: String? = ""
) : Parcelable { ) : Parcelable {
fun recommendMaxValue(): Double =
if (TextUtils.isEmpty(recommendMax)) 0.0
else recommendMax!!.toDouble()
fun recommendMinValue(): Double =
if (TextUtils.isEmpty(recommendMin)) 0.0
else recommendMin!!.toDouble()
fun energyValue(): Double =
if (TextUtils.isEmpty(energy)) 0.0
else energy!!.toDouble()
fun totalEnergyCalculateScoreValue(): Double =
if (TextUtils.isEmpty(totalEnergyCalculateScore)) 0.0
else totalEnergyCalculateScore!!.toDouble()
@Parcelize @Parcelize
data class StFoodInfoPagoda( data class StFoodInfoPagoda(
/**
* 水果
*/
@SerializedName("fruits") @SerializedName("fruits")
val fruits: String? = "", val fruits: String? = "",
@SerializedName("fruitsRecommend") @SerializedName("fruitsRecommend")
val fruitsRecommend: String? = "", val fruitsRecommend: String? = "",
/**
* 粮食
*/
@SerializedName("grain") @SerializedName("grain")
val grain: String? = "", val grain: String? = "",
@SerializedName("grainRecommend") @SerializedName("grainRecommend")
val grainRecommend: String? = "", val grainRecommend: String? = "",
/**
*
*/
@SerializedName("meat") @SerializedName("meat")
val meat: String? = "", val meat: String? = "",
@SerializedName("meatRecommend") @SerializedName("meatRecommend")
val meatRecommend: String? = "", val meatRecommend: String? = "",
/**
*
*/
@SerializedName("oil") @SerializedName("oil")
val oil: String? = "", val oil: String? = "",
/**
*
*/
@SerializedName("salt") @SerializedName("salt")
val salt: String? = "", val salt: String? = "",
/**
* 大豆
*/
@SerializedName("soya") @SerializedName("soya")
val soya: String? = "", val soya: String? = "",
@SerializedName("soyaRecommend") @SerializedName("soyaRecommend")
val soyaRecommend: String? = "", val soyaRecommend: String? = "",
/**
*
*/
@SerializedName("sugar") @SerializedName("sugar")
val sugar: String? = "", val sugar: String? = "",
/**
* 蔬菜
*/
@SerializedName("vegetable") @SerializedName("vegetable")
val vegetable: String? = "", val vegetable: String? = "",
@SerializedName("vegetableRecommend") @SerializedName("vegetableRecommend")
val vegetableRecommend: String? = "" val vegetableRecommend: String? = ""
) : Parcelable ) : Parcelable {
fun fruitsValue(): Double =
if (TextUtils.isEmpty(fruits))
0.0
else fruits!!.toDouble()
fun grainValue(): Double =
if (TextUtils.isEmpty(grain))
0.0
else grain!!.toDouble()
fun vegetableValue(): Double =
if (TextUtils.isEmpty(vegetable))
0.0
else vegetable!!.toDouble()
fun meatValue(): Double =
if (TextUtils.isEmpty(meat))
0.0
else meat!!.toDouble()
}
} }
@@ -3,10 +3,11 @@ package com.sw.dualscreen.network.api
import com.sw.dualscreen.GlobalData import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.EquipmentInfo import com.sw.dualscreen.model.response.EquipmentInfo
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.NutritionData
import com.sw.dualscreen.model.response.UserFaceInfo import com.sw.dualscreen.model.response.UserFaceInfo
import com.sw.dualscreen.model.response.UserNutritionData
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Header
@@ -78,7 +79,17 @@ interface ApiService {
@Query("restId") restId: String, @Query("restId") restId: String,
@Query("userId") userId: String, @Query("userId") userId: String,
@Query("foodId") foodId: String, @Query("foodId") foodId: String,
): ApiResponse<NutritionData> ): ApiResponse<UserNutritionData>
/**
* 获取当前餐点类型
*/
@GET
suspend fun getDinnerType(
@Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getCanteenDinnerType",
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Query("canteenId") restId: String,
): ApiResponse<DinnerTypeInfo>
/** /**
* 提交就餐数据 * 提交就餐数据
@@ -30,8 +30,13 @@ import com.sw.dualscreen.activity.MainActivity
import com.sw.dualscreen.databinding.ItemUserNutritionBinding import com.sw.dualscreen.databinding.ItemUserNutritionBinding
import com.sw.dualscreen.databinding.PresentationSecondaryScreenBinding import com.sw.dualscreen.databinding.PresentationSecondaryScreenBinding
import com.sw.dualscreen.ext.dp import com.sw.dualscreen.ext.dp
import com.sw.dualscreen.ext.format2String
import com.sw.dualscreen.ext.maskName import com.sw.dualscreen.ext.maskName
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.sdk.SensorScaleUtils
import com.sw.dualscreen.utils.Debouncer
import com.sw.dualscreen.utils.GlideUtils import com.sw.dualscreen.utils.GlideUtils
import com.sw.dualscreen.viewmodel.UserViewModel import com.sw.dualscreen.viewmodel.UserViewModel
import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.ToastUtils
@@ -70,6 +75,8 @@ class SecondaryScreenPresentation(
// 当前食物信息 // 当前食物信息
private var currentFood: FoodInfo? = null private var currentFood: FoodInfo? = null
private var userNutritionData: UserNutritionData? = null
private var dinnerType: DinnerTypeInfo? = null
private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding
private lateinit var stepChangeCallback: (Int) -> Unit private lateinit var stepChangeCallback: (Int) -> Unit
@@ -92,14 +99,16 @@ class SecondaryScreenPresentation(
viewModel.nutritionData.collect { viewModel.nutritionData.collect {
Timber.d("registerDataChange nutritionData = $it") Timber.d("registerDataChange nutritionData = $it")
if (it == null) return@collect if (it == null) return@collect
userNutritionData = it
step3()
itemUserNutritionBinding.tvUserName.text = it.userName.maskName() itemUserNutritionBinding.tvUserName.text = it.userName.maskName()
itemUserNutritionBinding.tvRecommendHeat.text = itemUserNutritionBinding.tvRecommendHeat.text =
"推荐热量:${it.recommendMin}-${it.recommendMax}" "推荐热量:${it.recommendMin}-${it.recommendMax}"
}
itemUserNutritionBinding.customKcalColumn.setCustomHeight(280, true) }
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(1f, true) activity.lifecycleScope.launch {
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(0.5f, true) viewModel.dinnerTypeInfo.collect {
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(0f, true) dinnerType = it
} }
} }
} }
@@ -163,6 +172,8 @@ class SecondaryScreenPresentation(
binding.tvBottomTip.visibility = View.VISIBLE binding.tvBottomTip.visibility = View.VISIBLE
itemUserNutritionBinding.clNutritionData.visibility = View.GONE itemUserNutritionBinding.clNutritionData.visibility = View.GONE
stopSensorScale()
viewModel.getDinnerType()
} }
/** /**
@@ -211,6 +222,7 @@ class SecondaryScreenPresentation(
} }
binding.tvFoodInfo.text = currentFood!!.foodName binding.tvFoodInfo.text = currentFood!!.foodName
startSensorScale()
GlideUtils.loadRoundCornerImage( GlideUtils.loadRoundCornerImage(
context, context,
@@ -229,11 +241,82 @@ class SecondaryScreenPresentation(
itemUserNutritionBinding.clNutritionData.visibility = View.VISIBLE itemUserNutritionBinding.clNutritionData.visibility = View.VISIBLE
viewModel.getUserNutritionData( viewModel.getUserNutritionData(
userId = "187c96f7bf294c08bc1d1e57b90a7210", userId = userNutritionData!!.userId!!,
foodId = currentFood!!.id!! foodId = currentFood!!.id!!
) )
} }
private fun startSensorScale() {
var lastWeight = 0.0
val debouncer = Debouncer(1000)
SensorScaleUtils.startScale { weight ->
if (weight == lastWeight) return@startScale
Timber.d("registerDataChange weight = $weight")
lastWeight = weight
if (currentFood == null) return@startScale
if (userNutritionData == null) return@startScale
if (dinnerType == null) return@startScale
debouncer.debounce {
val calcResultInfo = UserNutritionUtils.calculateNutrition(
currentFood!!,
userNutritionData!!,
weight,
dinnerType = dinnerType!!.dinnerType!!.dinnerType!!
)
Timber.d("calcResultInfo = $calcResultInfo")
activity.runOnUiThread {
val totalKcal = calcResultInfo.totalKcal
val grain = calcResultInfo.grain
val fruits = calcResultInfo.fruits
val meat = calcResultInfo.meat
itemUserNutritionBinding.customKcalColumn.setImageDrawable(
true,
totalKcal.first < totalKcal.second
)
itemUserNutritionBinding.totalKcalTv.text = totalKcal.second.format2String()
itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent(
(totalKcal.second / 100).toFloat(),
true
)
itemUserNutritionBinding.customFoodColumn.setImageDrawable(
false,
grain.first < grain.second
)
itemUserNutritionBinding.totalFoodTv.text = grain.second.format2String()
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(
(grain.second / 100).toFloat(),
true
)
itemUserNutritionBinding.customVegetableColumn.setImageDrawable(
false,
fruits.first < fruits.second
)
itemUserNutritionBinding.totalVegetableTv.text = fruits.second.format2String()
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(
(fruits.second / 100).toFloat(),
true
)
itemUserNutritionBinding.customMeatColumn.setImageDrawable(
false,
meat.first < meat.second
)
itemUserNutritionBinding.totalMeatTv.text = meat.second.format2String()
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(
(meat.second / 100).toFloat(),
true
)
}
}
}
}
private fun stopSensorScale() {
SensorScaleUtils.closeScale()
}
private fun openCamera(cameraId: String) { private fun openCamera(cameraId: String) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
PackageManager.PERMISSION_GRANTED PackageManager.PERMISSION_GRANTED
@@ -328,7 +411,8 @@ class SecondaryScreenPresentation(
recognizeViewModel.recognizeUserId.observe(activity, Observer { userId: String? -> recognizeViewModel.recognizeUserId.observe(activity, Observer { userId: String? ->
Timber.i("recognizeUserId observe userId = $userId") Timber.i("recognizeUserId observe userId = $userId")
// viewModel.getUserInfoById(memberId = userId?.toInt() ?: 0) if (userId == null) return@Observer
viewModel.getUserNutritionData(userId = userId, foodId = currentFood!!.id!!)
}) })
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info -> recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
@@ -534,7 +618,7 @@ class SecondaryScreenPresentation(
rgbCameraHelper!!.release() rgbCameraHelper!!.release()
rgbCameraHelper = null rgbCameraHelper = null
} }
SensorScaleUtils.closeScale()
recognizeViewModel.destroy() recognizeViewModel.destroy()
super.onStop() super.onStop()
} }
@@ -0,0 +1,79 @@
package com.sw.dualscreen.presentation
import android.text.TextUtils
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserNutritionData
object UserNutritionUtils {
/**
* 计算热量信息
*/
fun calculateNutrition(
foodInfo: FoodInfo,
userModel: UserNutritionData,
weight: Double,
dinnerType: String
): CalcResultInfo {
// 1. 初始化变量
var foodKcal = 0.0
var totalKcal = 0.0
var (vegetable, meat, fruits, grain) = List(4) { 0.0 }
// 2. 处理食物信息
foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight)
grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight)
fruits = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.fruitsValue(), weight)
vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight)
meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight)
// 3. 合并用户数据
grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0
fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0
vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0)
meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0
totalKcal = foodKcal + userModel.energyValue()
val fruitsAndVeg = fruits + vegetable
// 4. 判断当餐最大热量
val maxKcal =
userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10
val pagoda = userModel.stFoodInfoPagoda
val calcResult = CalcResultInfo(
totalKcal = maxKcal to totalKcal,
grain = parseMax(pagoda?.grainRecommend) to grain,
fruits = parseMax(pagoda?.fruitsRecommend) + parseMax(pagoda?.vegetableRecommend) to fruitsAndVeg,
meat = parseMax(pagoda?.meatRecommend) to meat
)
return calcResult
}
fun parseMax(recommend: String?): Double {
if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) return 0.0
val (min, max) = recommend.split("-")
return max.toDouble()
}
private fun calculateDinnerTypeRatio(dinnerType: String): Int {
return when (dinnerType) {
"早餐", "晚餐" -> 3
"午餐" -> 4
else -> 0
}
}
private fun calculateValue(nutrient: Double?, weight: Double): Double {
return weight * (nutrient ?: 1.0)
}
data class CalcResultInfo(
var totalKcal: Pair<Double, Double>,
var grain: Pair<Double, Double>,
var fruits: Pair<Double, Double>,
var meat: Pair<Double, Double>,
)
}
@@ -3,10 +3,11 @@ package com.sw.dualscreen.repository
import com.sw.dualscreen.GlobalData import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.EquipmentInfo import com.sw.dualscreen.model.response.EquipmentInfo
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.NutritionData
import com.sw.dualscreen.model.response.UserFaceInfo import com.sw.dualscreen.model.response.UserFaceInfo
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.network.api.ApiService import com.sw.dualscreen.network.api.ApiService
/** /**
@@ -80,12 +81,20 @@ class RemoteRepository constructor(
restId: String = GlobalData.restId, restId: String = GlobalData.restId,
userId: String, userId: String,
foodId: String, foodId: String,
): ApiResponse<NutritionData> { ): ApiResponse<UserNutritionData> {
return safeApiCall { return safeApiCall {
apiService.getUserNutritionData(restId = restId, userId = userId, foodId = foodId) apiService.getUserNutritionData(restId = restId, userId = userId, foodId = foodId)
} }
} }
suspend fun getDinnerType(
restId: String = GlobalData.restId,
): ApiResponse<DinnerTypeInfo> {
return safeApiCall {
apiService.getDinnerType(restId = restId)
}
}
/** /**
* 提交就餐数据 * 提交就餐数据
*/ */
@@ -143,6 +143,7 @@ object SensorScaleUtils {
* 关闭称重 * 关闭称重
*/ */
fun closeScale() { fun closeScale() {
Log.d(TAG, "closeScale")
isOpened = false isOpened = false
mSensorScale?.closeScale() mSensorScale?.closeScale()
mSensorScale == null mSensorScale == null
@@ -1,15 +1,18 @@
package com.sw.dualscreen.view; package com.sw.dualscreen.view;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.AlphaAnimation; import android.view.animation.AlphaAnimation;
import com.sw.dualscreen.R;
import com.sw.plate.utils.AppUtil; import com.sw.plate.utils.AppUtil;
public class CustomImageView extends androidx.appcompat.widget.AppCompatImageView { public class CustomImageView extends androidx.appcompat.widget.AppCompatImageView {
@@ -23,29 +26,37 @@ public class CustomImageView extends androidx.appcompat.widget.AppCompatImageVie
private static final int MAX_HEIGHT = 280; private static final int MAX_HEIGHT = 280;
private boolean isDrawText = false; private boolean isDrawText = false;
private Drawable bigRedDrawable;
private Drawable bigGreenDrawable;
private Drawable redDrawable;
private Drawable greenDrawable;
public CustomImageView(Context context) { public CustomImageView(Context context) {
super(context); super(context);
init(); init(context);
} }
public CustomImageView(Context context, AttributeSet attrs) { public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init(); init(context);
} }
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) { public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
init(); init(context);
} }
private void init() { @SuppressLint("UseCompatLoadingForDrawables")
private void init(Context context) {
textToDraw = "超标"; textToDraw = "超标";
mPaint = new Paint();//Paint.ANTI_ALIAS_FLAG mPaint = new Paint();//Paint.ANTI_ALIAS_FLAG
mPaint.setColor(Color.WHITE); // Set your desired color mPaint.setColor(Color.WHITE); // Set your desired color
mPaint.setTextSize(mTextSize); // Set your desired text size mPaint.setTextSize(mTextSize); // Set your desired text size
mPaint.setAntiAlias(true); mPaint.setAntiAlias(true);
bigRedDrawable = context.getDrawable(R.drawable.img_big_red_column);
bigGreenDrawable = context.getDrawable(R.drawable.img_big_green_column);
redDrawable = context.getDrawable(R.drawable.img_red_column);
greenDrawable = context.getDrawable(R.drawable.img_green_column);
// Typeface typeface = getResources().getFont(R.font.dakai); // Typeface typeface = getResources().getFont(R.font.dakai);
// Typeface typeface = Typeface.create(Typeface.createFromAsset(getContext().getAssets(), "fonts/dakai.TTF"), // Typeface typeface = Typeface.create(Typeface.createFromAsset(getContext().getAssets(), "fonts/dakai.TTF"),
// Typeface.BOLD); // 创建Typeface // Typeface.BOLD); // 创建Typeface
@@ -69,6 +80,20 @@ public class CustomImageView extends androidx.appcompat.widget.AppCompatImageVie
} }
} }
/**
* 设置图片
*
* @param isBig 大图
* @param isMore 是否超过
*/
public void setImageDrawable(boolean isBig, boolean isMore) {
if (isBig) {
setImageDrawable(isMore ? bigRedDrawable : bigGreenDrawable);
} else {
setImageDrawable(isMore ? redDrawable : greenDrawable);
}
}
public void setCustomHeightPercent(float percent, boolean isAnimation) { public void setCustomHeightPercent(float percent, boolean isAnimation) {
setCustomHeight((int) (percent * MAX_HEIGHT), isAnimation); setCustomHeight((int) (percent * MAX_HEIGHT), isAnimation);
} }
@@ -5,9 +5,10 @@ import com.arcsoft.face.ErrorInfo
import com.sw.dualscreen.GlobalData import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.NutritionData
import com.sw.dualscreen.model.response.UserFaceModel import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.inbound.utils.SPUtil import com.sw.inbound.utils.SPUtil
import com.sw.plate.App import com.sw.plate.App
import com.sw.plate.utils.Base64 import com.sw.plate.utils.Base64
@@ -35,8 +36,15 @@ class UserViewModel : BaseViewModel() {
val searchFoodInfoList: StateFlow<List<FoodInfo>> = _searchFoodInfoList val searchFoodInfoList: StateFlow<List<FoodInfo>> = _searchFoodInfoList
// 就餐数据 // 就餐数据
private val _nutritionData = MutableStateFlow<NutritionData?>(null) private val _nutritionData = MutableStateFlow<UserNutritionData?>(null)
val nutritionData: StateFlow<NutritionData?> = _nutritionData val nutritionData: StateFlow<UserNutritionData?> = _nutritionData
/**
* 饭点类型
*/
private val _dinnerTypeInfo = MutableStateFlow<DinnerTypeInfo?>(null)
val dinnerTypeInfo: StateFlow<DinnerTypeInfo?> = _dinnerTypeInfo
/** /**
* 获取token * 获取token
@@ -179,6 +187,16 @@ class UserViewModel : BaseViewModel() {
} }
} }
fun getDinnerType() {
Timber.d("getDinnerType")
launchWithLoading {
val response = repository.getDinnerType()
if (parseResponse(response)) {
_dinnerTypeInfo.value = response.result
}
}
}
/** /**
* 提交就餐数据 * 提交就餐数据
*/ */
@@ -76,7 +76,7 @@
<com.sw.dualscreen.view.CustomImageView <com.sw.dualscreen.view.CustomImageView
android:id="@+id/customKcalColumn" android:id="@+id/customKcalColumn"
android:layout_width="@dimen/dp87" android:layout_width="@dimen/dp87"
android:layout_height="10dp" android:layout_height="0dp"
android:layout_marginBottom="6dp" android:layout_marginBottom="6dp"
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/img_big_red_column" android:src="@drawable/img_big_red_column"
+1 -1
View File
@@ -92,7 +92,7 @@
<style name="takeFoodCustomColumn"> <style name="takeFoodCustomColumn">
<item name="android:layout_width">@dimen/dp53</item> <item name="android:layout_width">@dimen/dp53</item>
<item name="android:layout_height">10dp</item> <item name="android:layout_height">0dp</item>
<item name="android:layout_centerHorizontal">true</item> <item name="android:layout_centerHorizontal">true</item>
<!-- <item name="android:layout_marginBottom">-36dp</item>--> <!-- <item name="android:layout_marginBottom">-36dp</item>-->
<item name="android:scaleType">fitXY</item> <item name="android:scaleType">fitXY</item>