添加注释
This commit is contained in:
@@ -43,6 +43,9 @@ import timber.log.Timber
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务员显示界面
|
||||||
|
*/
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
private val viewModel by viewModels<UserViewModel>()
|
private val viewModel by viewModels<UserViewModel>()
|
||||||
private var imageCapture: ImageCapture? = null
|
private var imageCapture: ImageCapture? = null
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.sw.dualscreen.network.interceptor
|
|||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.inbound.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
import com.sw.plate.App
|
import com.sw.plate.App
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ 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 timber.log.Timber
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户营养信息计算工具
|
||||||
|
*/
|
||||||
object UserNutritionUtils {
|
object UserNutritionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.sw.dualscreen.utils
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖工具
|
||||||
|
*/
|
||||||
class Debouncer(private val delayMillis: Long = 2000) {
|
class Debouncer(private val delayMillis: Long = 2000) {
|
||||||
private var lastActionTime = 0L
|
private var lastActionTime = 0L
|
||||||
|
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
package com.sw.dualscreen.utils
|
|
||||||
|
|
||||||
import android.content.ContentUris
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
||||||
import okhttp3.MultipartBody
|
|
||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
object FileUtils {
|
|
||||||
/**
|
|
||||||
* 从Uri获取File
|
|
||||||
* example: file:///data/user/0/com.sw.inbound/cache/IMG_17515262353556856678814444882273.jpg
|
|
||||||
*/
|
|
||||||
private fun getFileFromUri(context: Context, uri: Uri): File? {
|
|
||||||
Timber.d("getFileFromUri uri = ${uri.scheme}")
|
|
||||||
return when (uri.scheme) {
|
|
||||||
"file" -> File(uri.path ?: return null)
|
|
||||||
"content" -> {
|
|
||||||
try {
|
|
||||||
val inputStream = context.contentResolver.openInputStream(uri) ?: return null
|
|
||||||
val cacheDir = context.cacheDir
|
|
||||||
val file = File.createTempFile(
|
|
||||||
"upload_${System.currentTimeMillis()}",
|
|
||||||
".jpg",
|
|
||||||
cacheDir
|
|
||||||
)
|
|
||||||
file.outputStream().use { output ->
|
|
||||||
inputStream.copyTo(output)
|
|
||||||
}
|
|
||||||
file
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过uri生成http请求体
|
|
||||||
*/
|
|
||||||
fun genRequestPart(context: Context, imageUri: Uri): MultipartBody.Part? {
|
|
||||||
Timber.d("genRequestPart imageUri = $imageUri")
|
|
||||||
// 1. 从Uri获取文件
|
|
||||||
val file = getFileFromUri(context, imageUri)
|
|
||||||
if (file == null) {
|
|
||||||
Timber.e("getFileFromUri file is null")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
// 2. 创建请求体
|
|
||||||
val requestFile = file
|
|
||||||
.asRequestBody("application/octet-stream".toMediaTypeOrNull())
|
|
||||||
val imagePart = MultipartBody.Part.createFormData(
|
|
||||||
"file",
|
|
||||||
file.name,
|
|
||||||
requestFile
|
|
||||||
)
|
|
||||||
return imagePart
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过Uri删除文件
|
|
||||||
* @param context 上下文
|
|
||||||
* @param uri 文件Uri
|
|
||||||
* @return Boolean 是否删除成功
|
|
||||||
*/
|
|
||||||
fun deleteFileWithUri(context: Context, uri: Uri): Boolean {
|
|
||||||
Timber.d("deleteFileWithUri uri = ${uri.scheme}")
|
|
||||||
return when {
|
|
||||||
// 1. 处理 content:// 类型的Uri (MediaStore)
|
|
||||||
uri.scheme.equals("content", ignoreCase = true) -> {
|
|
||||||
deleteContentUriFile(context, uri)
|
|
||||||
}
|
|
||||||
// 2. 处理 file:// 类型的Uri
|
|
||||||
uri.scheme.equals("file", ignoreCase = true) -> {
|
|
||||||
deleteFileUriFile(uri)
|
|
||||||
}
|
|
||||||
// 3. 其他情况尝试直接解析路径
|
|
||||||
else -> {
|
|
||||||
deleteFileFromPath(uri.path ?: return false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除Content Uri文件
|
|
||||||
private fun deleteContentUriFile(context: Context, uri: Uri): Boolean {
|
|
||||||
Timber.d("deleteContentUriFile uri = ${uri.scheme}")
|
|
||||||
return try {
|
|
||||||
context.contentResolver.delete(uri, null, null) > 0
|
|
||||||
} catch (e: SecurityException) {
|
|
||||||
// Android 10+需要特殊处理
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
||||||
deleteMediaStoreFile(context, uri)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Android 10+删除MediaStore文件
|
|
||||||
@RequiresApi(Build.VERSION_CODES.Q)
|
|
||||||
private fun deleteMediaStoreFile(context: Context, uri: Uri): Boolean {
|
|
||||||
Timber.d("deleteMediaStoreFile uri = ${uri.scheme}")
|
|
||||||
val contentResolver = context.contentResolver
|
|
||||||
val projection = arrayOf(MediaStore.MediaColumns._ID)
|
|
||||||
|
|
||||||
return try {
|
|
||||||
contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
val id =
|
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
|
|
||||||
val contentUri = ContentUris.withAppendedId(uri, id)
|
|
||||||
contentResolver.delete(contentUri, null, null) > 0
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} ?: false
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除File Uri文件
|
|
||||||
private fun deleteFileUriFile(uri: Uri): Boolean {
|
|
||||||
Timber.d("deleteFileUriFile uri = $uri")
|
|
||||||
return try {
|
|
||||||
File(uri.path ?: return false).delete()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接通过路径删除文件
|
|
||||||
private fun deleteFileFromPath(path: String): Boolean {
|
|
||||||
Timber.d("deleteFileFromPath path = $path")
|
|
||||||
return try {
|
|
||||||
File(path).delete()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.sw.inbound.utils
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
@@ -9,6 +9,9 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 持久化工具
|
||||||
|
*/
|
||||||
class SPUtil private constructor(context: Context, private val spName: String) {
|
class SPUtil private constructor(context: Context, private val spName: String) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.sw.dualscreen.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.WindowManager
|
|
||||||
import timber.log.Timber
|
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
object ScreenUtils {
|
|
||||||
fun printScreenInfo(context: Context, tag: String) {
|
|
||||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
|
||||||
val displayMetrics = DisplayMetrics()
|
|
||||||
|
|
||||||
// 方法 1:获取应用可用区域(排除系统装饰,如状态栏)
|
|
||||||
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
|
||||||
|
|
||||||
// 方法 2:获取整个屏幕的物理尺寸(包括状态栏和导航栏)
|
|
||||||
// windowManager.defaultDisplay.getRealMetrics(displayMetrics)
|
|
||||||
|
|
||||||
val screenWidthPx = displayMetrics.widthPixels // 屏幕宽度(像素)
|
|
||||||
val screenHeightPx = displayMetrics.heightPixels // 屏幕高度(像素)
|
|
||||||
val density = displayMetrics.density // 逻辑密度(1.0 = mdpi, 2.0 = xhdpi)
|
|
||||||
val densityDpi = displayMetrics.densityDpi // 屏幕 DPI 分类(160 = mdpi, 320 = xhdpi)
|
|
||||||
val xdpi = displayMetrics.xdpi // 物理水平 DPI
|
|
||||||
val ydpi = displayMetrics.ydpi // 物理垂直 DPI
|
|
||||||
|
|
||||||
// 打印信息
|
|
||||||
Timber.d("$tag 屏幕信息")
|
|
||||||
Timber.d("屏幕分辨率(像素): ${screenWidthPx}x${screenHeightPx}")
|
|
||||||
Timber.d("逻辑密度: $density")
|
|
||||||
Timber.d("DPI 分类: $densityDpi")
|
|
||||||
Timber.d("物理 DPI (x/y): $xdpi / $ydpi")
|
|
||||||
|
|
||||||
// 计算屏幕物理尺寸(英寸)
|
|
||||||
val screenWidthInches = screenWidthPx / xdpi
|
|
||||||
val screenHeightInches = screenHeightPx / ydpi
|
|
||||||
val diagonalInches = sqrt(
|
|
||||||
(screenWidthInches * screenWidthInches + screenHeightInches * screenHeightInches).toDouble()
|
|
||||||
)
|
|
||||||
Timber.d(
|
|
||||||
"屏幕物理尺寸(英寸): %.1f x %.1f (对角线: %.1f\")".format(
|
|
||||||
screenWidthInches, screenHeightInches, diagonalInches
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ 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
|
||||||
@@ -25,6 +24,9 @@ import com.sw.dualscreen.viewmodel.UserViewModel
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部搜索结果弹窗
|
||||||
|
*/
|
||||||
class CustomBottomSheetDialog(
|
class CustomBottomSheetDialog(
|
||||||
val viewModel: UserViewModel,
|
val viewModel: UserViewModel,
|
||||||
val itemClickCallback: (FoodInfo) -> Unit
|
val itemClickCallback: (FoodInfo) -> Unit
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import android.view.View;
|
|||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载进度条弹窗
|
||||||
|
*/
|
||||||
public class CustomDialog extends Dialog {
|
public class CustomDialog extends Dialog {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ import com.sw.plate.utils.AppUtil;
|
|||||||
|
|
||||||
import timber.log.Timber;
|
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;
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import androidx.appcompat.widget.AppCompatSpinner
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spinner控件
|
||||||
|
*/
|
||||||
class CustomSpinner @JvmOverloads constructor(
|
class CustomSpinner @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package com.sw.dualscreen.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
|
|
||||||
class CylinderDrawView @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : View(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
// 圆柱属性(默认红色)
|
|
||||||
var cylinderColor: Int = Color.RED
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
var cylinderWidth: Int = 120 // 默认宽度(px)
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
requestLayout()
|
|
||||||
}
|
|
||||||
var cylinderHeight: Int = 360 // 默认高度(px)
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
requestLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val paint = Paint().apply {
|
|
||||||
isAntiAlias = true // 抗锯齿
|
|
||||||
style = Paint.Style.FILL // 填充模式
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
||||||
val measuredWidth = resolveSize(cylinderWidth, widthMeasureSpec)
|
|
||||||
val measuredHeight = resolveSize(cylinderHeight, heightMeasureSpec)
|
|
||||||
setMeasuredDimension(measuredWidth, measuredHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
super.onDraw(canvas)
|
|
||||||
paint.color = cylinderColor
|
|
||||||
// 绘制圆角矩形(半径=宽度的一半,形成圆柱效果)
|
|
||||||
val radius = cylinderWidth / 2f
|
|
||||||
canvas.drawRoundRect(
|
|
||||||
0f, 0f,
|
|
||||||
cylinderWidth.toFloat(), cylinderHeight.toFloat(),
|
|
||||||
radius, radius,
|
|
||||||
paint
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.sw.dualscreen.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.sw.dualscreen.R
|
|
||||||
|
|
||||||
class CylinderView @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
private val valueText: TextView
|
|
||||||
private val unitText: TextView
|
|
||||||
private val cylinderDrawView: CylinderDrawView
|
|
||||||
private val topImage: ImageView
|
|
||||||
private val bottomImage: ImageView
|
|
||||||
private val bottomText: TextView
|
|
||||||
|
|
||||||
init {
|
|
||||||
// 加载内部布局
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.view_cylinder, this, true)
|
|
||||||
|
|
||||||
// 绑定控件
|
|
||||||
valueText = findViewById(R.id.valueText)
|
|
||||||
unitText = findViewById(R.id.unitText)
|
|
||||||
cylinderDrawView = findViewById(R.id.cylinderDrawView)
|
|
||||||
topImage = findViewById(R.id.topImage)
|
|
||||||
bottomImage = findViewById(R.id.bottomImage)
|
|
||||||
bottomText = findViewById(R.id.bottomText)
|
|
||||||
|
|
||||||
// 解析自定义属性
|
|
||||||
context.obtainStyledAttributes(attrs, R.styleable.CylinderView).apply {
|
|
||||||
// 顶部文字:数值+单位合并
|
|
||||||
val value = getString(R.styleable.CylinderView_valueText) ?: ""
|
|
||||||
val unit = getString(R.styleable.CylinderView_unitText) ?: ""
|
|
||||||
valueText.text = value
|
|
||||||
valueText.textSize = getDimension(R.styleable.CylinderView_valueTextSize, 20f)
|
|
||||||
valueText.setTextColor(
|
|
||||||
getColor(
|
|
||||||
R.styleable.CylinderView_valueTextColor,
|
|
||||||
0xFFFFFFFF.toInt()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
unitText.text = unit
|
|
||||||
unitText.textSize = getDimension(R.styleable.CylinderView_valueTextSize, 10f)
|
|
||||||
unitText.setTextColor(
|
|
||||||
getColor(
|
|
||||||
R.styleable.CylinderView_valueTextColor,
|
|
||||||
0xFFFFFFFF.toInt()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// 圆柱属性
|
|
||||||
cylinderDrawView.cylinderColor =
|
|
||||||
getColor(R.styleable.CylinderView_cylinderColor, Color.RED)
|
|
||||||
cylinderDrawView.cylinderWidth =
|
|
||||||
getDimensionPixelSize(R.styleable.CylinderView_cylinderWidth, 60)
|
|
||||||
cylinderDrawView.cylinderHeight =
|
|
||||||
getDimensionPixelSize(R.styleable.CylinderView_cylinderHeight, 180)
|
|
||||||
|
|
||||||
getResourceId(R.styleable.CylinderView_topImageSrc, -1).takeIf { it != -1 }?.let {
|
|
||||||
topImage.setImageResource(it)
|
|
||||||
// val layoutParams = cylinderDrawView.layoutParams
|
|
||||||
// layoutParams.height = (layoutParams.width / 2.45).toInt()
|
|
||||||
// topImage.layoutParams = layoutParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// 底部图片
|
|
||||||
getResourceId(R.styleable.CylinderView_bottomImageSrc, -1).takeIf { it != -1 }?.let {
|
|
||||||
bottomImage.setImageResource(it)
|
|
||||||
// val layoutParams = cylinderDrawView.layoutParams
|
|
||||||
// layoutParams.height = 44
|
|
||||||
// bottomImage.layoutParams = layoutParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// 底部文字
|
|
||||||
bottomText.text = getString(R.styleable.CylinderView_bottomText) ?: "热量"
|
|
||||||
bottomText.textSize = getDimension(R.styleable.CylinderView_bottomTextSize, 16f)
|
|
||||||
bottomText.setTextColor(
|
|
||||||
getColor(
|
|
||||||
R.styleable.CylinderView_bottomTextColor,
|
|
||||||
0xFFFFFFFF.toInt()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
recycle() // 回收属性
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setToImageSize() {
|
|
||||||
// topImage.layoutParams = LayoutParams.
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setBottomSize() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import com.sw.dualscreen.GlobalData
|
|||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.dualscreen.model.response.EquipmentInfo
|
import com.sw.dualscreen.model.response.EquipmentInfo
|
||||||
import com.sw.dualscreen.utils.GsonUtils
|
import com.sw.dualscreen.utils.GsonUtils
|
||||||
import com.sw.inbound.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ 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.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
import com.sw.dualscreen.model.response.UserNutritionData
|
import com.sw.dualscreen.model.response.UserNutritionData
|
||||||
import com.sw.inbound.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
import com.sw.plate.App
|
import com.sw.plate.App
|
||||||
import com.sw.plate.utils.Base64
|
import com.sw.plate.utils.Base64
|
||||||
import com.sw.plate.utils.ToastUtils
|
import com.sw.plate.utils.ToastUtils
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="8dp"> <!-- 深蓝色背景 -->
|
|
||||||
|
|
||||||
<!-- 顶部文字:数值+单位 -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/valueText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/unitText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="10sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 圆柱容器 -->
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/cylinderContainer"
|
|
||||||
android:layout_width="87dp"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<!-- 圆柱绘制View -->
|
|
||||||
<com.sw.dualscreen.view.CylinderDrawView
|
|
||||||
android:id="@+id/cylinderDrawView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="top|center_horizontal" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/topImage"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_gravity="top|center_horizontal"
|
|
||||||
android:background="@drawable/img_red_column" />
|
|
||||||
<!-- 底部火焰图片(覆盖圆柱底部) -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/bottomImage"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|center_horizontal"
|
|
||||||
android:src="@drawable/ic_heat" /> <!-- 替换为你的火焰图片资源 -->
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<!-- 底部文字:热量 -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/bottomText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:text="热量"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
Reference in New Issue
Block a user