This commit is contained in:
2026-01-14 10:38:09 +08:00
parent e86db688e1
commit 50d12de534
10 changed files with 254 additions and 189 deletions
@@ -0,0 +1,42 @@
package com.sw.dualscreen
class Test {
private var lastWeight = 0
// private var currentWeight = 0
data class WeightRecord(
var eatWeight: Int = 0,
var deviceWeight: Int = 0,
var lastWeight: Int = 0,
var state: Boolean = false
)
private val weightRecord by lazy { WeightRecord() }
fun main() {
readWeight { weight ->
if (weightRecord.state) {
//数据已记录
return@readWeight
}
if (weight == 0 || lastWeight == 0) {
return@readWeight
}
if (weight < lastWeight) {
weightRecord.let {
it.deviceWeight = weight
it.eatWeight = it.deviceWeight - it.lastWeight
it.state = true
}
}
lastWeight = weight
}
}
fun readWeight(block: (Int) -> Unit) {
}
}
@@ -884,7 +884,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private fun uri2File(uri: Uri, block: (File?, FloatArray?) -> Unit) { private fun uri2File(uri: Uri, block: (File?, FloatArray?) -> Unit) {
ImageUtil.uriToBitmap(this, uri)?.let { bitmap -> ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
val imageVector = try { val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap) FoodModule.bitmap2FloatArray(bitmap, false)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
return@let return@let
@@ -148,7 +148,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
//// offsetX = 30, offsetY = 100 //// offsetX = 30, offsetY = 100
// ) // )
val imageVector = try { val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap) FoodModule.bitmap2FloatArray(bitmap, false)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
ToastUtils.showToast("操作失败") ToastUtils.showToast("操作失败")
@@ -1,34 +0,0 @@
//package com.sw.dualscreen.adapter
//
//import android.content.Context
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import android.widget.ImageView
//import com.chad.library.adapter4.BaseQuickAdapter
//import com.chad.library.adapter4.viewholder.QuickViewHolder
//import com.sw.dualscreen.R
//import com.sw.dualscreen.databinding.ListItemCollectedDataBinding
//import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding
//import com.sw.dualscreen.objbox.CollectedFoodInfo
//import com.sw.dualscreen.objbox.FoodCollectionBean
//
//class CollectedFoodAdapter (var list: MutableList<CollectedFoodInfo>) :
// BaseQuickAdapter<CollectedFoodInfo, CollectedFoodAdapter.VH>(list) {
//
// inner class VH(var binding: ListItemCollectedDataBinding) : QuickViewHolder(binding.root)
//
// override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
// val inflater = LayoutInflater.from(context)
// val binding = ListItemCollectedDataBinding.inflate(inflater, parent, false)
// return VH(binding)
// }
//
// override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodInfo?) {
// holder.binding.tvFoodName.text = item?.foodName
// holder.binding.divider.run {
// visibility = if (position == list.size - 1) View.GONE else View.VISIBLE
// }
// }
//
//}
@@ -6,6 +6,8 @@ import android.view.ViewGroup
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.sw.dualscreen.databinding.ListItemCollectedFoodBinding import com.sw.dualscreen.databinding.ListItemCollectedFoodBinding
import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.objbox.CollectedFoodInfo import com.sw.dualscreen.objbox.CollectedFoodInfo
class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodInfo>) : class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodInfo>) :
@@ -22,6 +24,9 @@ class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodInfo>) :
override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodInfo?) { override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodInfo?) {
holder.binding.tvFoodName.text = item?.foodName holder.binding.tvFoodName.text = item?.foodName
holder.binding.tvCollectedNum.text = "已采集${item?.foodCount}" holder.binding.tvCollectedNum.text = "已采集${item?.foodCount}"
holder.binding.divider.run {
if (position == list.size-1) gone() else visible()
}
} }
} }
@@ -4,9 +4,11 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import androidx.core.graphics.scale
import com.sw.dualscreen.MyApp import com.sw.dualscreen.MyApp
import com.sw.dualscreen.utils.GsonUtils import com.sw.dualscreen.utils.GsonUtils
import com.sw.dualscreen.utils.ImageUtil import com.sw.dualscreen.utils.ImageUtil
import com.sw.plate.utils.ToastUtils
import io.objectbox.Box import io.objectbox.Box
import io.objectbox.kotlin.boxFor import io.objectbox.kotlin.boxFor
import org.pytorch.IValue import org.pytorch.IValue
@@ -23,25 +25,34 @@ object FoodModule {
private const val THRESHOLD = 0.8 private const val THRESHOLD = 0.8
// private const val THRESHOLD = 0.0 // private const val THRESHOLD = 0.0
private lateinit var module: Module private var module: Module?=null
private lateinit var box: Box<Food> private var box: Box<Food>?=null
// private lateinit var embeddingsList: List<List<Float>> // private lateinit var embeddingsList: List<List<Float>>
// private lateinit var labelsList: IntArray // private lateinit var labelsList: IntArray
// private lateinit var classInfo: FoodClassInfo // private lateinit var classInfo: FoodClassInfo
val NO_MEAN_RGB = floatArrayOf(0.0f, 0.0f, 0.0f) val NO_MEAN_RGB = floatArrayOf(0.0f, 0.0f, 0.0f)
val NO_STD_RGB = floatArrayOf(1.0f, 1.0f, 1.0f) val NO_STD_RGB = floatArrayOf(1.0f, 1.0f, 1.0f)
// val DEFAULT_FOOD_INDEX = -1
// val DEFAULT_FOOD_INDEX = -1
// 1. 定义你的模型固定输入尺寸 (根据你的tflite模型修改,比如224x224)
private const val MODEL_INPUT_WIDTH = 224
private const val MODEL_INPUT_HEIGHT = 224
@SuppressLint("SuspiciousIndentation") @SuppressLint("SuspiciousIndentation")
fun init(context: Context, block: () -> Unit = {}) { fun init(context: Context, block: () -> Unit = {}) {
Thread { Thread {
module = Module.load(copyAssetToCache(context, "best_embedding_model_mobile.pt")) val modelPath = copyAssetToCache(context, "best_embedding_model_mobile.pt")
// ToastUtils.showToast("modelPath==null:${modelPath == null}")
module = Module.load(modelPath)
// ToastUtils.showToast("module==null:${module == null}")
box = ObjectBox.boxStore.boxFor(Food::class) box = ObjectBox.boxStore.boxFor(Food::class)
//初始化默认重新拉取数据,先清空本地数据 //初始化默认重新拉取数据,先清空本地数据
// ObjectBox.boxStore.runInTx { // ObjectBox.boxStore.runInTx {
if (box.all.isNotEmpty()) { box?.run {
box.removeAll() if (all.isNotEmpty()) {
removeAll()
}
} }
//if (box.all.isEmpty()) { //if (box.all.isEmpty()) {
// initDefFoodData(context) // initDefFoodData(context)
@@ -50,29 +61,46 @@ object FoodModule {
}.start() }.start()
} }
fun uri2FloatArray(uri: Uri): FloatArray? { // fun uri2FloatArray(uri: Uri): FloatArray? {
return MyApp.instance?.let { context -> // return MyApp.instance?.let { context ->
ImageUtil.uriToBitmap(context, uri)?.let { // ImageUtil.uriToBitmap(context, uri)?.let {
bitmap2FloatArray(it) // bitmap2FloatArray(it)
} // }
}
}
fun bitmap2FloatArray(bitmap: Bitmap): FloatArray {
var tensorStartTime = System.currentTimeMillis()
val inputTensor = TensorImageUtils.bitmapToFloat32Tensor(
bitmap,
NO_MEAN_RGB, // [0.485, 0.456, 0.406] TORCHVISION_NORM_MEAN_RGB
NO_STD_RGB // [0.229, 0.224, 0.225] TORCHVISION_NORM_STD_RGB
)
Timber.tag(TAG).d("bitmap2FloatArray-inputTensor耗时:${System.currentTimeMillis() - tensorStartTime}")
// if (module_mobile == null) {
// init(App.getContext())
// } // }
tensorStartTime = System.currentTimeMillis() // }
val outputTensor = module.forward(IValue.from(inputTensor)).toTensor()
Timber.tag(TAG).d("bitmap2FloatArray-toTensor耗时:${System.currentTimeMillis() - tensorStartTime}") fun bitmap2FloatArray(originBitmap: Bitmap, isRecycle: Boolean): FloatArray? {
return outputTensor.dataAsFloatArray var rgb565Bitmap: Bitmap? = null
try {
val scaledBitmap = originBitmap.scale(
MODEL_INPUT_WIDTH,
MODEL_INPUT_HEIGHT
)
if (isRecycle) {
originBitmap.recycle()
}
rgb565Bitmap = scaledBitmap.copy(Bitmap.Config.RGB_565, false)
scaledBitmap.recycle()
val inputTensor = TensorImageUtils.bitmapToFloat32Tensor(
rgb565Bitmap,
NO_MEAN_RGB, // [0.485, 0.456, 0.406] TORCHVISION_NORM_MEAN_RGB
NO_STD_RGB // [0.229, 0.224, 0.225] TORCHVISION_NORM_STD_RGB
)
if (module == null) {
return null
}
val outputTensor = module?.forward(IValue.from(inputTensor))?.toTensor()
return outputTensor?.dataAsFloatArray
} catch (e: OutOfMemoryError) {
e.printStackTrace()
} finally {
if (rgb565Bitmap != null && rgb565Bitmap.isRecycled.not()) {
rgb565Bitmap.recycle()
}
//System.gc()
//System.runFinalization()
}
return null
} }
// fun queryFood(uri: Uri, queryCount: Int = 15): List<String>? { // fun queryFood(uri: Uri, queryCount: Int = 15): List<String>? {
@@ -97,22 +125,24 @@ object FoodModule {
// return queryFoodNameScore(floatArray, queryCount) // return queryFoodNameScore(floatArray, queryCount)
// } // }
fun queryFoodNameScore(floatArray: FloatArray, queryCount: Int = 15): List<IdNameScore> { fun queryFoodNameScore(floatArray: FloatArray?, queryCount: Int = 15): List<IdNameScore> {
if (floatArray == null) return emptyList()
val startTime = System.currentTimeMillis() val startTime = System.currentTimeMillis()
Timber.tag(TAG).d("queryFoodNameScore-已采集向量总数:${box.all.filter { it.isDel.not() }.size}") Timber.tag(TAG)
box.store.runInTx { } .d("queryFoodNameScore-已采集向量总数:${box?.all?.filter { it.isDel.not() }?.size}")
val query = box.query() //box.store.runInTx { }
.equal(Food_.isDel, false) val query = box?.query()
.and() ?.equal(Food_.isDel, false)
.nearestNeighbors(Food_.foodVector, floatArray, queryCount) ?.and()
.build() ?.nearestNeighbors(Food_.foodVector, floatArray, queryCount)
?.build()
//查询比较分数 //查询比较分数
// val tempList = query.findWithScores().sortedBy { it.score }.map { "${it.get().name}|${it.get().foodIdx}|${it.score}" } // val tempList = query.findWithScores().sortedBy { it.score }.map { "${it.get().name}|${it.get().foodIdx}|${it.score}" }
// val idScoreList = query.findIdsWithScores() // val idScoreList = query.findIdsWithScores()
val objScoreList = query.findWithScores() val objScoreList = query?.findWithScores()
Timber.tag(TAG).d("idScoreList:${GsonUtils.toJson(objScoreList)}") Timber.tag(TAG).d("idScoreList:${GsonUtils.toJson(objScoreList)}")
val nameScoreList = mutableListOf<IdNameScore>() val nameScoreList = mutableListOf<IdNameScore>()
objScoreList.forEach { objScoreList?.forEach {
val food = it.get() val food = it.get()
nameScoreList.add( nameScoreList.add(
IdNameScore( IdNameScore(
@@ -123,14 +153,15 @@ object FoodModule {
) )
} }
val nameScoreData = GsonUtils.toJson(nameScoreList) val nameScoreData = GsonUtils.toJson(nameScoreList)
Timber.tag(TAG).d("queryFood,耗时:${System.currentTimeMillis() - startTime},数据:$nameScoreData") Timber.tag(TAG)
query.close() .d("queryFood,耗时:${System.currentTimeMillis() - startTime},数据:$nameScoreData")
query?.close()
return nameScoreList return nameScoreList
} }
fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> { fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
val startTime = System.currentTimeMillis() val startTime = System.currentTimeMillis()
val floatArray = bitmap2FloatArray(bitmap) val floatArray = bitmap2FloatArray(bitmap, false)
Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}") Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}")
val nameScoreList = queryFoodNameScore(floatArray, queryCount) val nameScoreList = queryFoodNameScore(floatArray, queryCount)
@@ -156,6 +187,9 @@ object FoodModule {
val sortedScoreList = maxScoreList.sortedWith(compareBy { val sortedScoreList = maxScoreList.sortedWith(compareBy {
orderList.indexOf(it.name) orderList.indexOf(it.name)
}) })
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
//Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toJsonString()}") //Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toJsonString()}")
return sortedScoreList return sortedScoreList
} }
@@ -241,47 +275,75 @@ object FoodModule {
* *
* 不可能反正SD * 不可能反正SD
*/ */
fun copyAssetToCache(context: Context, fileName: String): String? { // fun copyAssetToCache(context: Context, fileName: String): String? {
// 此app的缓存目录 --> 会默认在 cache目录...,可以自己去看看哦 // // 此app的缓存目录 --> 会默认在 cache目录...,可以自己去看看哦
val cacheDir = context.cacheDir // val cacheDir = context.cacheDir
if (!cacheDir.exists()) { // if (!cacheDir.exists()) {
cacheDir.mkdirs() // TODO 如果没有缓存目录,就创建 // cacheDir.mkdirs() // TODO 如果没有缓存目录,就创建
} // }
val outPath = File(cacheDir, fileName) // TODO 创建输出的文件位置 // val outPath = File(cacheDir, fileName) // TODO 创建输出的文件位置
if (outPath.exists()) { // if (outPath.exists()) {
outPath.delete() // TODO 如果该文件已经存在,就删掉 // outPath.delete() // TODO 如果该文件已经存在,就删掉
} // }
var `is`: InputStream? = null // 读取 // var `is`: InputStream? = null // 读取
var fos: FileOutputStream? = null // 写入 // var fos: FileOutputStream? = null // 写入
try { // try {
// 创建文件,如果创建成功,就返回true // // 创建文件,如果创建成功,就返回true
val res = outPath.createNewFile() // val res = outPath.createNewFile()
if (res) { // if (res) {
`is` = context.assets.open(fileName) // 拿到main/assets目录的输入流,用于读取字节 // `is` = context.assets.open(fileName) // 拿到main/assets目录的输入流,用于读取字节
fos = FileOutputStream(outPath) // 读取出来的字节最终写到outPath // fos = FileOutputStream(outPath) // 读取出来的字节最终写到outPath
val buf = ByteArray(`is`.available()) // 缓存区 // val buf = ByteArray(`is`.available()) // 缓存区
var byteCount: Int // var byteCount: Int
//
// // 开始循环读取
// while ((`is`.read(buf).also { byteCount = it }) != -1) {
// fos.write(buf, 0, byteCount)
// }
// return outPath.absolutePath
// }
// } catch (e: IOException) {
// e.printStackTrace()
// } finally {
// try {
// // TODO 一定要记得关闭资源,为了不去性能的磨损
// fos!!.flush()
// `is`!!.close()
// fos.close()
// } catch (e: IOException) {
// e.printStackTrace()
// }
// }
// return null
// }
// 开始循环读取 fun copyAssetToCache(context: Context, fileName: String): String? {
while ((`is`.read(buf).also { byteCount = it }) != -1) { val cacheFile = File(context.cacheDir, fileName)
fos.write(buf, 0, byteCount) val buffer = ByteArray(8 * 1024)
} var inputStream: InputStream? = null
return outPath.absolutePath var outputStream: FileOutputStream? = null
try {
inputStream = context.assets.open(fileName)
outputStream = FileOutputStream(cacheFile)
var byteCount: Int
while (inputStream.read(buffer).also { byteCount = it } != -1) {
outputStream.write(buffer, 0, byteCount)
} }
outputStream.channel.force(true) // 强制物理落盘,比flush更彻底
return cacheFile.absolutePath
} catch (e: IOException) { } catch (e: IOException) {
e.printStackTrace() e.printStackTrace()
} finally { Timber.tag("FoodModule").d("文件拷贝失败 fileName=$fileName, error=${e.message}")
try { // 拷贝失败时删除残缺文件,避免下次读取到损坏文件
// TODO 一定要记得关闭资源,为了不去性能的磨损 if (cacheFile.exists()) {
fos!!.flush() cacheFile.delete()
`is`!!.close()
fos.close()
} catch (e: IOException) {
e.printStackTrace()
} }
} finally {
outputStream?.close()
inputStream?.close()
} }
return null return null
} }
} }
@@ -0,0 +1,7 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<color android:color="@android:color/white" />
</item>
</ripple>
+38 -72
View File
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#FFE7EFF8" android:background="#FFE7EFF8"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
tools:context=".activity.MainActivity"> tools:context=".activity.MainActivity"
tools:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<FrameLayout <FrameLayout
@@ -36,22 +37,6 @@
android:src="@drawable/ic_setting" android:src="@drawable/ic_setting"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<!-- <LinearLayout-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="end"-->
<!-- android:background="@drawable/bg_detection_selector">-->
<!-- <Spinner-->
<!-- android:id="@+id/spinner"-->
<!-- style="@style/customSpinnerStyle"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="end"-->
<!-- android:padding="0dp"-->
<!-- android:popupBackground="@drawable/shape_for_custom_spinner" />-->
<!-- </LinearLayout>-->
</FrameLayout> </FrameLayout>
<TextView <TextView
@@ -59,10 +44,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="50dp" android:layout_marginTop="50dp"
android:textStyle="bold" android:text="羊肉臊子荞面饸饹"
android:textSize="52sp"
android:textColor="#FF0A1428" android:textColor="#FF0A1428"
android:text="羊肉臊子荞面饸饹" /> android:textSize="52sp"
android:textStyle="bold" />
<FrameLayout <FrameLayout
android:id="@+id/foodDisplayLayout" android:id="@+id/foodDisplayLayout"
@@ -83,76 +68,57 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="食物图预览" android:contentDescription="食物图预览"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:shapeAppearance="@style/round10dpCornerStyle" android:visibility="gone"
android:visibility="gone" /> app:shapeAppearance="@style/round10dpCornerStyle" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="27dp" android:layout_margin="27dp"
android:background="@drawable/ic_camera_rect" /> android:background="@drawable/ic_camera_rect" />
<!-- preview_border--> <!-- preview_border-->
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview" android:id="@+id/recyclerview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:spanCount="2"
tools:itemCount="8"
android:overScrollMode="never"
tools:listitem="@layout/list_item_search_food"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
android:layout_marginHorizontal="14dp" android:layout_marginHorizontal="14dp"
android:layout_marginTop="42dp" android:layout_marginTop="42dp"
android:layout_weight="1" /> android:layout_weight="1"
android:overScrollMode="never"
<!-- <LinearLayout--> app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
<!-- android:id="@+id/layoutRescan"--> app:spanCount="2"
<!-- android:layout_width="wrap_content"--> tools:itemCount="8"
<!-- android:layout_height="wrap_content"--> tools:listitem="@layout/list_item_search_food" />
<!-- android:layout_marginBottom="140dp"-->
<!-- android:gravity="center"-->
<!-- android:orientation="vertical"-->
<!-- android:visibility="gone">-->
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="未识别出菜品,请重试或手动搜索"-->
<!-- android:textColor="#FFFF3232"-->
<!-- android:textSize="24sp" />-->
<!-- <CheckedTextView-->
<!-- android:id="@+id/tv_rescan"-->
<!-- android:layout_width="360dp"-->
<!-- android:layout_height="90dp"-->
<!-- android:layout_marginTop="20dp"-->
<!-- android:background="@drawable/bg_search_food"-->
<!-- android:gravity="center"-->
<!-- android:padding="10dp"-->
<!-- android:text="重试"-->
<!-- android:paddingHorizontal="15dp"-->
<!-- android:textAlignment="center"-->
<!-- android:textColor="@color/color_search_food"-->
<!-- android:textStyle="bold"-->
<!-- android:checked="true"-->
<!-- android:textSize="32sp" />-->
<!-- </LinearLayout>-->
<TextView <TextView
android:id="@+id/tvToSearch" android:id="@+id/tvToSearch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="38dp" android:layout_marginTop="38dp"
android:layout_marginBottom="54dp" android:layout_marginBottom="0dp"
android:padding="10dp" android:padding="10dp"
android:text="以上都不是,手动搜索" android:text="以上都不是,手动搜索"
android:textStyle="bold"
android:textColor="#FFFF3232" android:textColor="#FFFF3232"
android:textSize="31sp" android:textSize="31sp"
android:visibility="gone"/> android:textStyle="bold"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="54dp"
android:gravity="center">
<TextView
android:id="@+id/tvWeightRealInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="12sp"
tools:text="以上都不是,手动搜索" />
</LinearLayout>
<FrameLayout <FrameLayout
android:id="@+id/flPay" android:id="@+id/flPay"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -163,13 +129,13 @@
<androidx.appcompat.widget.AppCompatButton <androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnPay" android:id="@+id/btnPay"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_margin="32dp"
android:layout_height="100dp" android:layout_height="100dp"
android:textStyle="bold" android:layout_margin="32dp"
android:text="去结算"
android:textSize="40sp"
android:background="@drawable/bg_btn_save" android:background="@drawable/bg_btn_save"
android:textColor="@color/white"/> android:text="去结算"
android:textColor="@color/white"
android:textSize="40sp"
android:textStyle="bold" />
</FrameLayout> </FrameLayout>
+5 -2
View File
@@ -97,7 +97,9 @@
android:src="@drawable/ic_retake_photo" android:src="@drawable/ic_retake_photo"
app:layout_constraintEnd_toEndOf="@id/btnCollectedFood" app:layout_constraintEnd_toEndOf="@id/btnCollectedFood"
app:layout_constraintTop_toTopOf="@id/flPreview" app:layout_constraintTop_toTopOf="@id/flPreview"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription"
android:foreground="@drawable/ripple_effect"/>
<!-- android:background="?android:attr/selectableItemBackgroundBorderless"-->
<ImageView <ImageView
android:id="@+id/btnTakePhoto" android:id="@+id/btnTakePhoto"
@@ -106,7 +108,8 @@
android:src="@drawable/ic_take_photo" android:src="@drawable/ic_take_photo"
app:layout_constraintBottom_toBottomOf="@id/flPreview" app:layout_constraintBottom_toBottomOf="@id/flPreview"
app:layout_constraintEnd_toEndOf="@id/btnCollectedFood" app:layout_constraintEnd_toEndOf="@id/btnCollectedFood"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription"
android:foreground="@drawable/ripple_effect"/>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFoodList" android:id="@+id/rvFoodList"
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -8,11 +8,13 @@
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout
android:id="@+id/layoutFood"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginVertical="25dp" android:layout_marginTop="25dp"
android:layout_marginStart="80dp" android:layout_marginStart="80dp"
android:layout_weight="1" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
@@ -43,8 +45,20 @@
android:layout_height="80dp" android:layout_height="80dp"
android:layout_marginEnd="75dp" android:layout_marginEnd="75dp"
android:paddingHorizontal="18dp" android:paddingHorizontal="18dp"
app:layout_constraintTop_toTopOf="@id/layoutFood"
app:layout_constraintBottom_toBottomOf="@id/layoutFood"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/ic_close2" android:src="@drawable/ic_close2"
tools:ignore="ContentDescription" tools:ignore="ContentDescription"
android:visibility="visible"/> android:visibility="visible"/>
</LinearLayout> <com.google.android.material.divider.MaterialDivider
android:id="@+id/divider"
android:layout_width="match_parent"
app:layout_constraintTop_toBottomOf="@id/layoutFood"
android:layout_height="1dp"
android:layout_marginHorizontal="80dp"
android:layout_marginTop="25dp"
app:dividerColor="#FFC4CFDA"/>
</androidx.constraintlayout.widget.ConstraintLayout>