调整了个人营养数据计算逻辑,修复了摄像头逻辑

This commit is contained in:
zxj
2025-08-07 10:49:50 +08:00
parent 561a2fc9b2
commit 71ce668e3c
9 changed files with 283 additions and 164 deletions
@@ -124,11 +124,7 @@ class MainActivity : AppCompatActivity() {
) )
binding.recyclerview.adapter = adapter binding.recyclerview.adapter = adapter
binding.tvFoodName.setOnClickListener { binding.tvFoodName.setOnClickListener {
if (presentation.currentStep == 2) { SensorScaleUtils.zero()
presentation.step3()
} else {
presentation.step1()
}
} }
registerDataChange() registerDataChange()
} }
@@ -35,3 +35,12 @@ fun String?.maskPhone(): String {
} }
return sb.toString() return sb.toString()
} }
fun String?.toSafeDouble(): Double {
if (this == null) return 0.0
return try {
toDouble()
} catch (e: Exception) {
0.0
}
}
@@ -35,7 +35,7 @@ data class UserNutritionData(
* 食物类型和实际摄入量清单 * 食物类型和实际摄入量清单
*/ */
@SerializedName("foodTypeAndRealIntakeVoList") @SerializedName("foodTypeAndRealIntakeVoList")
val foodTypeAndRealIntakeVoList: List<String?>? = listOf(), val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo?>? = listOf(),
@SerializedName("foodWeight") @SerializedName("foodWeight")
val foodWeight: String? = "", val foodWeight: String? = "",
@SerializedName("message") @SerializedName("message")
@@ -66,7 +66,7 @@ data class UserNutritionData(
@SerializedName("stFoodInfoPagoda") @SerializedName("stFoodInfoPagoda")
val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(), val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(),
@SerializedName("stUserFoodInfoList") @SerializedName("stUserFoodInfoList")
val stUserFoodInfoList: List<String?>? = listOf(), val stUserFoodInfoList: List<StUserFoodInfo?>? = listOf(),
/** /**
* 每日总热量 * 每日总热量
*/ */
@@ -104,6 +104,26 @@ data class UserNutritionData(
if (TextUtils.isEmpty(totalEnergyCalculateScore)) 0.0 if (TextUtils.isEmpty(totalEnergyCalculateScore)) 0.0
else totalEnergyCalculateScore!!.toDouble() else totalEnergyCalculateScore!!.toDouble()
@Parcelize
data class FoodTypeAndRealIntakeVo(
@SerializedName("childMaterClassName")
val childMaterClassName: String? = "",
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("goodsId")
val goodsId: String? = "",
@SerializedName("goodsName")
val goodsName: String? = "",
@SerializedName("materClassName")
val materClassName: String? = "",
@SerializedName("materId")
val materId: String? = "",
@SerializedName("materialType")
val materialType: String? = "",
@SerializedName("realityIntake")
val realityIntake: String? = ""
) : Parcelable
@Parcelize @Parcelize
data class StFoodInfoPagoda( data class StFoodInfoPagoda(
/** /**
@@ -178,4 +198,56 @@ data class UserNutritionData(
else meat!!.toDouble() else meat!!.toDouble()
} }
@Parcelize
data class StUserFoodInfo(
@SerializedName("canteenId")
val canteenId: String? = "",
@SerializedName("createBy")
val createBy: String? = "",
@SerializedName("createTime")
val createTime: String? = "",
@SerializedName("dataSource")
val dataSource: String? = "",
@SerializedName("dataType")
val dataType: String? = "",
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("deviceId")
val deviceId: String? = "",
@SerializedName("dinnerType")
val dinnerType: String? = "",
@SerializedName("eatDay")
val eatDay: String? = "",
@SerializedName("eatNum")
val eatNum: String? = "",
@SerializedName("eatWeight")
val eatWeight: Double? = 0.0,
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("foodImg")
val foodImg: String? = "",
@SerializedName("foodMaterialId")
val foodMaterialId: String? = "",
@SerializedName("foodName")
val foodName: String? = "",
@SerializedName("foodWeight")
val foodWeight: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("specId")
val specId: String? = "",
@SerializedName("stBasicDiningInformationUserESVo")
val stBasicDiningInformationUserESVo: String? = "",
@SerializedName("stallType")
val stallType: String? = "",
@SerializedName("type")
val type: String? = "",
@SerializedName("userId")
val userId: String? = ""
) : Parcelable
} }
@@ -8,8 +8,6 @@ import android.graphics.Bitmap
import android.graphics.Outline import android.graphics.Outline
import android.graphics.Point import android.graphics.Point
import android.hardware.Camera import android.hardware.Camera
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
@@ -68,8 +66,6 @@ class SecondaryScreenPresentation(
val recognizeViewModel: RecognizeViewModel val recognizeViewModel: RecognizeViewModel
) : Presentation(context, display), ViewTreeObserver.OnGlobalLayoutListener { ) : Presentation(context, display), ViewTreeObserver.OnGlobalLayoutListener {
private lateinit var binding: PresentationSecondaryScreenBinding private lateinit var binding: PresentationSecondaryScreenBinding
private lateinit var cameraManager: CameraManager
private var cameraIdList: Array<String> = arrayOf()
// 当前食物信息 // 当前食物信息
private var currentFood: FoodInfo? = null private var currentFood: FoodInfo? = null
@@ -82,7 +78,7 @@ class SecondaryScreenPresentation(
// 上一次的计算热量结果 // 上一次的计算热量结果
private var lastCalcResultInfo: UserNutritionUtils.CalcResultInfo? = null private var lastCalcResultInfo: UserNutritionUtils.CalcResultInfo? = null
private var lastWeight = 0.0 private var lastWeight = 0.0
private val debouncer = Debouncer(2000) private val debouncer = Debouncer(500)
private var faceTime: Long = 0L // 人脸识别时的时间 private var faceTime: Long = 0L // 人脸识别时的时间
private var recognitionWeight: Double = 0.0 // 人脸识别时的重量 private var recognitionWeight: Double = 0.0 // 人脸识别时的重量
private var lastFaceTrackId: Int = 0 // 上一次的人脸信息 private var lastFaceTrackId: Int = 0 // 上一次的人脸信息
@@ -113,7 +109,7 @@ class SecondaryScreenPresentation(
itemUserNutritionBinding.tvRecommendHeat.text = itemUserNutritionBinding.tvRecommendHeat.text =
"推荐热量:${it.recommendMin}-${it.recommendMax}" "推荐热量:${it.recommendMin}-${it.recommendMax}"
updateWeight(lastWeight) updateWeight(lastWeight / 1000)
} }
} }
activity.lifecycleScope.launch { activity.lifecycleScope.launch {
@@ -246,8 +242,7 @@ class SecondaryScreenPresentation(
} }
fun updateWeight(weight: Double) { fun updateWeight(weight: Double) {
Timber.d("updateWeight weight = $weight") lastWeight = weight * 1000 // 将千克转成克
lastWeight = weight
Timber.d("updateWeight lastWeight = $weight") Timber.d("updateWeight lastWeight = $weight")
if (currentFood == null) { if (currentFood == null) {
Timber.e("updateWeight currentFood is null") Timber.e("updateWeight currentFood is null")
@@ -261,27 +256,28 @@ class SecondaryScreenPresentation(
Timber.e("updateWeight dinnerType is null") Timber.e("updateWeight dinnerType is null")
return return
} }
// 重量和 当前食物都没变,则不再计算 calculateNutrition(recognitionWeight - lastWeight)
if (lastFood == currentFood) {
// Timber.e("updateWeight 物品未改变")
return
} }
lastFood = currentFood
private fun calculateNutrition(weight: Double) {
debouncer.debounce { debouncer.debounce {
Timber.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
val dinnerType = dinnerTypeInfo!!.dinnerType!!.dinnerType!! val dinnerType = dinnerTypeInfo!!.dinnerType!!.dinnerType!!
Timber.d("updateWeight foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}") Timber.d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
val calcResultInfo = UserNutritionUtils.calculateNutrition( val calcResultInfo = UserNutritionUtils.calculateNutrition(
currentFood!!, currentFood!!,
userNutritionData!!, userNutritionData!!,
weight, weight,
dinnerType = dinnerType dinnerType = dinnerType
) )
Timber.d("updateWeight calcResultInfo = $calcResultInfo") Timber.d("calculateNutrition calcResultInfo = $calcResultInfo")
if (lastCalcResultInfo == calcResultInfo) { if (lastCalcResultInfo == calcResultInfo) {
Timber.d("updateWeight 与上次计算结果无变化") Timber.d("calculateNutrition 与上次计算结果无变化")
return@debounce return@debounce
} }
lastCalcResultInfo = calcResultInfo lastCalcResultInfo = calcResultInfo
val columnMax = UserNutritionUtils.getMaxInt(calcResultInfo)
activity.runOnUiThread { activity.runOnUiThread {
val totalKcal = calcResultInfo.totalKcal val totalKcal = calcResultInfo.totalKcal
val grain = calcResultInfo.grain val grain = calcResultInfo.grain
@@ -290,41 +286,47 @@ class SecondaryScreenPresentation(
// 设置热量 // 设置热量
itemUserNutritionBinding.customKcalColumn.setImageDrawable( itemUserNutritionBinding.customKcalColumn.setImageDrawable(
true, true,
totalKcal.first < totalKcal.second totalKcal.max < totalKcal.current
) )
itemUserNutritionBinding.totalKcalTv.text = totalKcal.second.format2String() var maxKcal = totalKcal.max
Timber.d("maxKcal = $maxKcal")
if (maxKcal <= 0.0) {
maxKcal = 100.0
}
Timber.d("maxKcal 1 = $maxKcal")
itemUserNutritionBinding.totalKcalTv.text = totalKcal.current.format2String()
itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent( itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent(
(totalKcal.second / 100).toFloat(), (totalKcal.current / maxKcal).toFloat(),
true true
) )
// 设置主食 // 设置主食
itemUserNutritionBinding.customFoodColumn.setImageDrawable( itemUserNutritionBinding.customFoodColumn.setImageDrawable(
false, false,
grain.first < grain.second grain.max < grain.current
) )
itemUserNutritionBinding.totalFoodTv.text = grain.second.format2String() itemUserNutritionBinding.totalFoodTv.text = grain.current.format2String()
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent( itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(
(grain.second / 100).toFloat(), (grain.current / columnMax).toFloat(),
true true
) )
// 设置果蔬 // 设置果蔬
itemUserNutritionBinding.customVegetableColumn.setImageDrawable( itemUserNutritionBinding.customVegetableColumn.setImageDrawable(
false, false,
fruits.first < fruits.second fruits.max < fruits.current
) )
itemUserNutritionBinding.totalVegetableTv.text = fruits.second.format2String() itemUserNutritionBinding.totalVegetableTv.text = fruits.current.format2String()
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent( itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(
(fruits.second / 100).toFloat(), (fruits.current / columnMax).toFloat(),
true true
) )
// 设置肉蛋 // 设置肉蛋
itemUserNutritionBinding.customMeatColumn.setImageDrawable( itemUserNutritionBinding.customMeatColumn.setImageDrawable(
false, false,
meat.first < meat.second meat.max < meat.current
) )
itemUserNutritionBinding.totalMeatTv.text = meat.second.format2String() itemUserNutritionBinding.totalMeatTv.text = meat.current.format2String()
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent( itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(
(meat.second / 100).toFloat(), (meat.current / columnMax).toFloat(),
true true
) )
} }
@@ -340,50 +342,22 @@ class SecondaryScreenPresentation(
return return
} }
try { try {
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager val cameraCount = Camera.getNumberOfCameras()
// 获取摄像头列表 if (cameraCount < 3){
cameraIdList = cameraManager.cameraIdList
if (cameraIdList.isEmpty()) {
ToastUtils.showToast("没有可用的摄像头")
return
}
if (cameraIdList.size < 3) {
ToastUtils.showToast("摄像头数量异常") ToastUtils.showToast("摄像头数量异常")
return return
} }
cameraIdList.forEach {
Timber.d("摄像头id列表 = $it")
}
val cameraId = cameraIdList.last()
Timber.d("openCamera cameraId = $cameraId")
val c1 = cameraIdList[0]
val c2 = cameraIdList[1]
val c3 = cameraIdList[2]
cameraManager.openCamera(c3, object : CameraDevice.StateCallback() {
override fun onOpened(device: CameraDevice) {
recognizeViewModel.init( recognizeViewModel.init(
PreviewConfig( PreviewConfig(
c3.toInt(), c2.toInt(), 90, 90 2, 1, 90, 90
) )
) )
initRgbCamera() initRgbCamera()
// resumeCamera()
if (DualCameraHelper.hasDualCamera() && livenessType === LivenessType.IR) { if (DualCameraHelper.hasDualCamera() && livenessType === LivenessType.IR) {
initIrCamera() initIrCamera()
} }
}
override fun onDisconnected(device: CameraDevice) {
device.close()
}
override fun onError(device: CameraDevice, error: Int) {
device.close()
}
}, null)
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Camera2", "打开摄像头失败", e) Timber.e(e, "打开摄像头失败")
} }
} }
@@ -441,20 +415,23 @@ class SecondaryScreenPresentation(
Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}") Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
}) })
recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? -> recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? ->
Timber.i("recognizeNotice observe notice = $notice") // Timber.i("recognizeNotice observe notice = $notice")
}) })
recognizeViewModel.recognizeUserId.observe( recognizeViewModel.recognizeUserId.observe(
activity, activity,
Observer { compareResult: CompareResult -> Observer { compareResult: CompareResult ->
Timber.i("recognizeUserId observe compareResult = $compareResult") Timber.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}")
faceTime = System.currentTimeMillis() faceTime = System.currentTimeMillis()
recognitionWeight = lastWeight recognitionWeight = lastWeight
lastFaceTrackId = compareResult.trackId lastFaceTrackId = compareResult.trackId
val faceEntity = compareResult.faceEntity val faceEntity = compareResult.faceEntity
val userId = faceEntity.userName val userId = faceEntity.userName
if (userId == null) return@Observer if (userId == null) return@Observer
viewModel.getUserNutritionData(userId = userId, foodId = currentFood!!.id!!) viewModel.getUserNutritionData(
userId = userId,
foodId = currentFood!!.id!!
)
}) })
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info -> recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
@@ -727,6 +704,11 @@ class SecondaryScreenPresentation(
} }
fun postUserData() { fun postUserData() {
Timber.d("postUserData")
if (userNutritionData == null || currentFood == null) {
Timber.d("postUserData userNutritionData = ${userNutritionData == null}, currentFood = ${currentFood == null}")
return
}
val userNutritionParam = UserNutritionParam( val userNutritionParam = UserNutritionParam(
userId = userNutritionData?.userId!!, userId = userNutritionData?.userId!!,
foodId = currentFood?.id!!, foodId = currentFood?.id!!,
@@ -2,8 +2,12 @@ package com.sw.dualscreen.presentation
import android.text.TextUtils import android.text.TextUtils
import com.sw.dualscreen.ext.toSafeDouble
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.model.response.UserNutritionData
import timber.log.Timber
import kotlin.math.max
import kotlin.math.min
object UserNutritionUtils { object UserNutritionUtils {
@@ -16,12 +20,12 @@ object UserNutritionUtils {
weight: Double, weight: Double,
dinnerType: String dinnerType: String
): CalcResultInfo { ): CalcResultInfo {
// 1. 初始化变量 // 初始化变量
var foodKcal = 0.0 var foodKcal = 0.0
var totalKcal = 0.0 var totalKcal = 0.0
var (vegetable, meat, fruits, grain) = List(4) { 0.0 } var (vegetable, meat, fruits, grain) = List(4) { 0.0 }
// 2. 处理食物信息 // 处理食物信息
foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight) foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight)
grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight) grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight)
@@ -29,33 +33,52 @@ object UserNutritionUtils {
vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight) vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight)
meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight) meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight)
// 3. 合并用户数据 // 合并用户数据
grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0 grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0
fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0 fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0
vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0) vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0)
meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0 meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0
totalKcal = foodKcal + userModel.energyValue() totalKcal = foodKcal + userModel.energyValue()
val fruitsAndVeg = fruits + vegetable if (totalKcal < 0){
totalKcal = 0.0
// 4. 判断当餐最大热量 }
// 判断当餐最大热量
val maxKcal = val maxKcal =
userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10 userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10
val pagoda = userModel.stFoodInfoPagoda val pagoda = userModel.stFoodInfoPagoda
val fruitsInfo = parseRecommend(pagoda?.fruitsRecommend, fruits)
val vegetableInfo = parseRecommend(pagoda?.vegetableRecommend, vegetable)
val calcResult = CalcResultInfo( val calcResult = CalcResultInfo(
totalKcal = maxKcal to totalKcal, totalKcal = CalcInfo(
grain = parseMax(pagoda?.grainRecommend) to grain, max = maxKcal,
fruits = parseMax(pagoda?.fruitsRecommend) + parseMax(pagoda?.vegetableRecommend) to fruitsAndVeg, min = 0.0,
meat = parseMax(pagoda?.meatRecommend) to meat current = totalKcal
),
grain = parseRecommend(pagoda?.grainRecommend, grain),
fruits = CalcInfo( // 果蔬 = 水果+蔬菜
max = fruitsInfo.max + vegetableInfo.max,
min = fruitsInfo.min + vegetableInfo.min,
current = fruitsInfo.current + vegetableInfo.current
),
meat = parseRecommend(pagoda?.meatRecommend, meat)
) )
return calcResult return calcResult
} }
fun parseMax(recommend: String?): Double { fun parseRecommend(recommend: String?, current: Double): CalcInfo {
if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) return 0.0 var newCurrent = if (current < 0) 0.0 else current
if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) {
Timber.e("parseRecommend recommend 格式错误")
return CalcInfo(
newCurrent,
0.0,
newCurrent
)
}
val (min, max) = recommend.split("-") val (min, max) = recommend.split("-")
return max.toDouble() return CalcInfo(max = max.toSafeDouble(), min = min.toSafeDouble(), current = newCurrent)
} }
private fun calculateDinnerTypeRatio(dinnerType: String): Int { private fun calculateDinnerTypeRatio(dinnerType: String): Int {
@@ -66,14 +89,28 @@ object UserNutritionUtils {
} }
} }
/**
* 计算每百克含量
*/
private fun calculateValue(nutrient: Double?, weight: Double): Double { private fun calculateValue(nutrient: Double?, weight: Double): Double {
return weight * (nutrient ?: 1.0) return weight * (nutrient ?: 1.0) / 100
} }
fun getMaxInt(calcResultInfo: CalcResultInfo): Int {
val max1 = max(calcResultInfo.grain.max, calcResultInfo.fruits.max)
return max(max1, calcResultInfo.meat.max).toInt()
}
data class CalcInfo(
var max: Double,
var min: Double,
var current: Double,
)
data class CalcResultInfo( data class CalcResultInfo(
var totalKcal: Pair<Double, Double>, var totalKcal: CalcInfo,
var grain: Pair<Double, Double>, var grain: CalcInfo,
var fruits: Pair<Double, Double>, var fruits: CalcInfo,
var meat: Pair<Double, Double>, var meat: CalcInfo,
) )
} }
@@ -72,12 +72,13 @@ object SensorScaleUtils {
isOpened = open isOpened = open
Timber.d("isOpened = $isOpened") Timber.d("isOpened = $isOpened")
if (open) { if (open) {
// zero()
if (autoScale) { if (autoScale) {
Thread({ Thread({
Thread.sleep(1000) Thread.sleep(1000)
// 打开后需要等待后才能调用,否则会 1001 SDK未初始化 // 打开后需要等待后才能调用,否则会 1001 SDK未初始化
mSensorScale?.startContinuousRead() mSensorScale?.startContinuousRead()
zero()
}).start() }).start()
} }
} }
@@ -8,6 +8,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@@ -30,6 +31,7 @@ class CustomBottomSheetDialog(
private lateinit var binding: BottomSheetDialogBinding private lateinit var binding: BottomSheetDialogBinding
private lateinit var adapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding> private lateinit var adapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
private var checkedItem: FoodInfo? = null private var checkedItem: FoodInfo? = null
private val debouncer = Debouncer(2000)
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@@ -42,13 +44,8 @@ class CustomBottomSheetDialog(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val debouncer = Debouncer(3000)
initView() initView()
binding.ivSearch.setOnClickListener {
debouncer.debounce {
viewModel.searchByFoodName(binding.etSearch.text.toString())
}
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -95,9 +92,26 @@ class CustomBottomSheetDialog(
) )
) )
binding.recyclerview.adapter = adapter binding.recyclerview.adapter = adapter
binding.ivSearch.setOnClickListener {
searchInfo()
}
binding.etSearch.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
searchInfo()
true
} else {
false
}
}
registerDataChange() registerDataChange()
} }
private fun searchInfo(){
debouncer.debounce {
viewModel.searchByFoodName(binding.etSearch.text.toString())
}
}
private fun registerDataChange() { private fun registerDataChange() {
lifecycleScope.launch { lifecycleScope.launch {
viewModel.searchFoodInfoList.collect { viewModel.searchFoodInfoList.collect {
@@ -15,6 +15,8 @@ import android.view.animation.AlphaAnimation;
import com.sw.dualscreen.R; import com.sw.dualscreen.R;
import com.sw.plate.utils.AppUtil; import com.sw.plate.utils.AppUtil;
import timber.log.Timber;
public class CustomImageView extends androidx.appcompat.widget.AppCompatImageView { public class CustomImageView extends androidx.appcompat.widget.AppCompatImageView {
private AlphaAnimation alphaAnimation; private AlphaAnimation alphaAnimation;
private String textToDraw; private String textToDraw;
@@ -95,16 +97,21 @@ public class CustomImageView extends androidx.appcompat.widget.AppCompatImageVie
} }
public void setCustomHeightPercent(float percent, boolean isAnimation) { public void setCustomHeightPercent(float percent, boolean isAnimation) {
// if (percent<= 0){ Timber.d("setCustomHeightPercent percent = %s", percent);
// percent = 0.01f; if (percent<= 0){
// } percent = 0f;
setCustomHeight((int) (percent * MAX_HEIGHT), isAnimation); }
setCustomHeight((int) (percent * MAX_HEIGHT), false);
} }
// 用于设置自定义高度的方法 // 用于设置自定义高度的方法
public void setCustomHeight(int height, boolean isAnimation) { public void setCustomHeight(int height, boolean isAnimation) {
Timber.d("setCustomHeight height = %s", height);
if (height > 0) { if (height > 0) {
height += 40; height += 30;
}
if (height > MAX_HEIGHT){
height = MAX_HEIGHT;
} }
ViewGroup.LayoutParams layoutParams = getLayoutParams(); ViewGroup.LayoutParams layoutParams = getLayoutParams();
int height1 = layoutParams.height; int height1 = layoutParams.height;
@@ -42,6 +42,7 @@
android:hint="输入菜品名称" android:hint="输入菜品名称"
android:imeOptions="actionSearch" android:imeOptions="actionSearch"
android:maxLines="1" android:maxLines="1"
android:inputType="text"
android:textColor="#333333" android:textColor="#333333"
android:textColorHint="#ffc8c8c8" android:textColorHint="#ffc8c8c8"
android:textSize="36sp" /> android:textSize="36sp" />