优化
This commit is contained in:
@@ -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) {
|
||||
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
||||
val imageVector = try {
|
||||
FoodModule.bitmap2FloatArray(bitmap)
|
||||
FoodModule.bitmap2FloatArray(bitmap, false)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return@let
|
||||
|
||||
@@ -148,7 +148,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
//// offsetX = 30, offsetY = 100
|
||||
// )
|
||||
val imageVector = try {
|
||||
FoodModule.bitmap2FloatArray(bitmap)
|
||||
FoodModule.bitmap2FloatArray(bitmap, false)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
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.viewholder.QuickViewHolder
|
||||
import com.sw.dualscreen.databinding.ListItemCollectedFoodBinding
|
||||
import com.sw.dualscreen.ext.gone
|
||||
import com.sw.dualscreen.ext.visible
|
||||
import com.sw.dualscreen.objbox.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?) {
|
||||
holder.binding.tvFoodName.text = item?.foodName
|
||||
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.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import androidx.core.graphics.scale
|
||||
import com.sw.dualscreen.MyApp
|
||||
import com.sw.dualscreen.utils.GsonUtils
|
||||
import com.sw.dualscreen.utils.ImageUtil
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.kotlin.boxFor
|
||||
import org.pytorch.IValue
|
||||
@@ -23,25 +25,34 @@ object FoodModule {
|
||||
private const val THRESHOLD = 0.8
|
||||
|
||||
// private const val THRESHOLD = 0.0
|
||||
private lateinit var module: Module
|
||||
private lateinit var box: Box<Food>
|
||||
private var module: Module?=null
|
||||
private var box: Box<Food>?=null
|
||||
|
||||
// private lateinit var embeddingsList: List<List<Float>>
|
||||
// private lateinit var labelsList: IntArray
|
||||
// private lateinit var classInfo: FoodClassInfo
|
||||
val NO_MEAN_RGB = floatArrayOf(0.0f, 0.0f, 0.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")
|
||||
fun init(context: Context, block: () -> Unit = {}) {
|
||||
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)
|
||||
//初始化默认重新拉取数据,先清空本地数据
|
||||
// ObjectBox.boxStore.runInTx {
|
||||
if (box.all.isNotEmpty()) {
|
||||
box.removeAll()
|
||||
box?.run {
|
||||
if (all.isNotEmpty()) {
|
||||
removeAll()
|
||||
}
|
||||
}
|
||||
//if (box.all.isEmpty()) {
|
||||
// initDefFoodData(context)
|
||||
@@ -50,29 +61,46 @@ object FoodModule {
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun uri2FloatArray(uri: Uri): FloatArray? {
|
||||
return MyApp.instance?.let { context ->
|
||||
ImageUtil.uriToBitmap(context, uri)?.let {
|
||||
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())
|
||||
// fun uri2FloatArray(uri: Uri): FloatArray? {
|
||||
// return MyApp.instance?.let { context ->
|
||||
// ImageUtil.uriToBitmap(context, uri)?.let {
|
||||
// bitmap2FloatArray(it)
|
||||
// }
|
||||
// }
|
||||
tensorStartTime = System.currentTimeMillis()
|
||||
val outputTensor = module.forward(IValue.from(inputTensor)).toTensor()
|
||||
Timber.tag(TAG).d("bitmap2FloatArray-toTensor耗时:${System.currentTimeMillis() - tensorStartTime}")
|
||||
return outputTensor.dataAsFloatArray
|
||||
// }
|
||||
|
||||
fun bitmap2FloatArray(originBitmap: Bitmap, isRecycle: Boolean): FloatArray? {
|
||||
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>? {
|
||||
@@ -97,22 +125,24 @@ object FoodModule {
|
||||
// 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()
|
||||
Timber.tag(TAG).d("queryFoodNameScore-已采集向量总数:${box.all.filter { it.isDel.not() }.size}")
|
||||
box.store.runInTx { }
|
||||
val query = box.query()
|
||||
.equal(Food_.isDel, false)
|
||||
.and()
|
||||
.nearestNeighbors(Food_.foodVector, floatArray, queryCount)
|
||||
.build()
|
||||
Timber.tag(TAG)
|
||||
.d("queryFoodNameScore-已采集向量总数:${box?.all?.filter { it.isDel.not() }?.size}")
|
||||
//box.store.runInTx { }
|
||||
val query = box?.query()
|
||||
?.equal(Food_.isDel, false)
|
||||
?.and()
|
||||
?.nearestNeighbors(Food_.foodVector, floatArray, queryCount)
|
||||
?.build()
|
||||
//查询比较分数
|
||||
// val tempList = query.findWithScores().sortedBy { it.score }.map { "${it.get().name}|${it.get().foodIdx}|${it.score}" }
|
||||
// val idScoreList = query.findIdsWithScores()
|
||||
val objScoreList = query.findWithScores()
|
||||
val objScoreList = query?.findWithScores()
|
||||
Timber.tag(TAG).d("idScoreList:${GsonUtils.toJson(objScoreList)}")
|
||||
val nameScoreList = mutableListOf<IdNameScore>()
|
||||
objScoreList.forEach {
|
||||
objScoreList?.forEach {
|
||||
val food = it.get()
|
||||
nameScoreList.add(
|
||||
IdNameScore(
|
||||
@@ -123,14 +153,15 @@ object FoodModule {
|
||||
)
|
||||
}
|
||||
val nameScoreData = GsonUtils.toJson(nameScoreList)
|
||||
Timber.tag(TAG).d("queryFood,耗时:${System.currentTimeMillis() - startTime},数据:$nameScoreData")
|
||||
query.close()
|
||||
Timber.tag(TAG)
|
||||
.d("queryFood,耗时:${System.currentTimeMillis() - startTime},数据:$nameScoreData")
|
||||
query?.close()
|
||||
return nameScoreList
|
||||
}
|
||||
|
||||
fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val floatArray = bitmap2FloatArray(bitmap)
|
||||
val floatArray = bitmap2FloatArray(bitmap, false)
|
||||
Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}")
|
||||
|
||||
val nameScoreList = queryFoodNameScore(floatArray, queryCount)
|
||||
@@ -156,6 +187,9 @@ object FoodModule {
|
||||
val sortedScoreList = maxScoreList.sortedWith(compareBy {
|
||||
orderList.indexOf(it.name)
|
||||
})
|
||||
if (bitmap.isRecycled.not()) {
|
||||
bitmap.recycle()
|
||||
}
|
||||
//Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toJsonString()}")
|
||||
return sortedScoreList
|
||||
}
|
||||
@@ -241,47 +275,75 @@ object FoodModule {
|
||||
*
|
||||
* 不可能反正SD
|
||||
*/
|
||||
fun copyAssetToCache(context: Context, fileName: String): String? {
|
||||
// 此app的缓存目录 --> 会默认在 cache目录...,可以自己去看看哦
|
||||
val cacheDir = context.cacheDir
|
||||
if (!cacheDir.exists()) {
|
||||
cacheDir.mkdirs() // TODO 如果没有缓存目录,就创建
|
||||
}
|
||||
val outPath = File(cacheDir, fileName) // TODO 创建输出的文件位置
|
||||
if (outPath.exists()) {
|
||||
outPath.delete() // TODO 如果该文件已经存在,就删掉
|
||||
}
|
||||
var `is`: InputStream? = null // 读取
|
||||
var fos: FileOutputStream? = null // 写入
|
||||
try {
|
||||
// 创建文件,如果创建成功,就返回true
|
||||
val res = outPath.createNewFile()
|
||||
if (res) {
|
||||
`is` = context.assets.open(fileName) // 拿到main/assets目录的输入流,用于读取字节
|
||||
fos = FileOutputStream(outPath) // 读取出来的字节最终写到outPath
|
||||
val buf = ByteArray(`is`.available()) // 缓存区
|
||||
var byteCount: Int
|
||||
// fun copyAssetToCache(context: Context, fileName: String): String? {
|
||||
// // 此app的缓存目录 --> 会默认在 cache目录...,可以自己去看看哦
|
||||
// val cacheDir = context.cacheDir
|
||||
// if (!cacheDir.exists()) {
|
||||
// cacheDir.mkdirs() // TODO 如果没有缓存目录,就创建
|
||||
// }
|
||||
// val outPath = File(cacheDir, fileName) // TODO 创建输出的文件位置
|
||||
// if (outPath.exists()) {
|
||||
// outPath.delete() // TODO 如果该文件已经存在,就删掉
|
||||
// }
|
||||
// var `is`: InputStream? = null // 读取
|
||||
// var fos: FileOutputStream? = null // 写入
|
||||
// try {
|
||||
// // 创建文件,如果创建成功,就返回true
|
||||
// val res = outPath.createNewFile()
|
||||
// if (res) {
|
||||
// `is` = context.assets.open(fileName) // 拿到main/assets目录的输入流,用于读取字节
|
||||
// fos = FileOutputStream(outPath) // 读取出来的字节最终写到outPath
|
||||
// val buf = ByteArray(`is`.available()) // 缓存区
|
||||
// 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
|
||||
// }
|
||||
|
||||
// 开始循环读取
|
||||
while ((`is`.read(buf).also { byteCount = it }) != -1) {
|
||||
fos.write(buf, 0, byteCount)
|
||||
}
|
||||
return outPath.absolutePath
|
||||
fun copyAssetToCache(context: Context, fileName: String): String? {
|
||||
val cacheFile = File(context.cacheDir, fileName)
|
||||
val buffer = ByteArray(8 * 1024)
|
||||
var inputStream: InputStream? = null
|
||||
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) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
try {
|
||||
// TODO 一定要记得关闭资源,为了不去性能的磨损
|
||||
fos!!.flush()
|
||||
`is`!!.close()
|
||||
fos.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Timber.tag("FoodModule").d("文件拷贝失败 fileName=$fileName, error=${e.message}")
|
||||
// 拷贝失败时删除残缺文件,避免下次读取到损坏文件
|
||||
if (cacheFile.exists()) {
|
||||
cacheFile.delete()
|
||||
}
|
||||
} finally {
|
||||
outputStream?.close()
|
||||
inputStream?.close()
|
||||
}
|
||||
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>
|
||||
@@ -1,14 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFE7EFF8"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activity.MainActivity">
|
||||
tools:context=".activity.MainActivity"
|
||||
tools:theme="@style/Theme.AppCompat.Light.DarkActionBar">
|
||||
|
||||
|
||||
<FrameLayout
|
||||
@@ -36,22 +37,6 @@
|
||||
android:src="@drawable/ic_setting"
|
||||
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>
|
||||
|
||||
<TextView
|
||||
@@ -59,10 +44,10 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="50dp"
|
||||
android:textStyle="bold"
|
||||
android:textSize="52sp"
|
||||
android:text="羊肉臊子荞面饸饹"
|
||||
android:textColor="#FF0A1428"
|
||||
android:text="羊肉臊子荞面饸饹" />
|
||||
android:textSize="52sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/foodDisplayLayout"
|
||||
@@ -83,76 +68,57 @@
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="食物图预览"
|
||||
android:scaleType="centerCrop"
|
||||
app:shapeAppearance="@style/round10dpCornerStyle"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
app:shapeAppearance="@style/round10dpCornerStyle" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="27dp"
|
||||
android:background="@drawable/ic_camera_rect" />
|
||||
<!-- preview_border-->
|
||||
<!-- preview_border-->
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
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_marginTop="42dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:id="@+id/layoutRescan"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- 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>-->
|
||||
android:layout_weight="1"
|
||||
android:overScrollMode="never"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="2"
|
||||
tools:itemCount="8"
|
||||
tools:listitem="@layout/list_item_search_food" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvToSearch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="38dp"
|
||||
android:layout_marginBottom="54dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:padding="10dp"
|
||||
android:text="以上都不是,手动搜索"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFF3232"
|
||||
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
|
||||
android:id="@+id/flPay"
|
||||
android:layout_width="match_parent"
|
||||
@@ -163,13 +129,13 @@
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnPay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_margin="32dp"
|
||||
android:layout_height="100dp"
|
||||
android:textStyle="bold"
|
||||
android:text="去结算"
|
||||
android:textSize="40sp"
|
||||
android:layout_margin="32dp"
|
||||
android:background="@drawable/bg_btn_save"
|
||||
android:textColor="@color/white"/>
|
||||
android:text="去结算"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="40sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
@@ -97,7 +97,9 @@
|
||||
android:src="@drawable/ic_retake_photo"
|
||||
app:layout_constraintEnd_toEndOf="@id/btnCollectedFood"
|
||||
app:layout_constraintTop_toTopOf="@id/flPreview"
|
||||
tools:ignore="ContentDescription" />
|
||||
tools:ignore="ContentDescription"
|
||||
android:foreground="@drawable/ripple_effect"/>
|
||||
<!-- android:background="?android:attr/selectableItemBackgroundBorderless"-->
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnTakePhoto"
|
||||
@@ -106,7 +108,8 @@
|
||||
android:src="@drawable/ic_take_photo"
|
||||
app:layout_constraintBottom_toBottomOf="@id/flPreview"
|
||||
app:layout_constraintEnd_toEndOf="@id/btnCollectedFood"
|
||||
tools:ignore="ContentDescription" />
|
||||
tools:ignore="ContentDescription"
|
||||
android:foreground="@drawable/ripple_effect"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvFoodList"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
@@ -8,11 +8,13 @@
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutFood"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="25dp"
|
||||
android:layout_marginTop="25dp"
|
||||
android:layout_marginStart="80dp"
|
||||
android:layout_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
@@ -43,8 +45,20 @@
|
||||
android:layout_height="80dp"
|
||||
android:layout_marginEnd="75dp"
|
||||
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"
|
||||
tools:ignore="ContentDescription"
|
||||
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>
|
||||
Reference in New Issue
Block a user