功能优化
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package com.sw.dualscreen.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.adapter.CollectedFoodAdapter
|
||||
import com.sw.dualscreen.databinding.ActivityCollectedDataBinding
|
||||
import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
|
||||
import com.sw.dualscreen.dialog.WarnDialog
|
||||
import com.sw.dualscreen.ext.addOnActionSearchListener
|
||||
import com.sw.dualscreen.ext.hideKeyboard
|
||||
import com.sw.dualscreen.objbox.CollectedFoodBean
|
||||
import com.sw.dualscreen.objbox.Food
|
||||
import com.sw.dualscreen.objbox.ObjectBox
|
||||
import com.sw.dualscreen.viewmodel.BaseViewModel
|
||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.kotlin.boxFor
|
||||
import kotlin.getValue
|
||||
|
||||
class CollectedDataActivity : BaseActivity<ActivityCollectedDataBinding>() {
|
||||
private val viewModel by viewModels<UserViewModel>()
|
||||
override fun getViewModel(): BaseViewModel {
|
||||
return viewModel
|
||||
}
|
||||
|
||||
override fun inflateViewBinding(): ActivityCollectedDataBinding {
|
||||
return ActivityCollectedDataBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private val list: MutableList<CollectedFoodBean> = mutableListOf()
|
||||
private val adapter by lazy {
|
||||
CollectedFoodAdapter(list).apply {
|
||||
isStateViewEnable = true
|
||||
addOnItemChildClickListener(R.id.ivDeleteFood) { _, _, position ->
|
||||
deleteGoods(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
super.initialize()
|
||||
binding.rvFoodList.let {
|
||||
it.layoutManager = LinearLayoutManager(this)
|
||||
it.adapter = adapter
|
||||
}
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
binding.ivGoodsSearch.setOnClickListener {
|
||||
val searchName = binding.etInputGoods.text.toString().trim()
|
||||
if (searchName.isBlank()) {
|
||||
ToastUtils.showToast("请输入物品名称")
|
||||
return@setOnClickListener
|
||||
}
|
||||
getCollectGoods(searchName)
|
||||
}
|
||||
binding.etInputGoods.let { v ->
|
||||
v.addOnActionSearchListener {
|
||||
val searchName = binding.etInputGoods.text.toString().trim()
|
||||
if (searchName.isBlank()) {
|
||||
ToastUtils.showToast("请输入物品名称")
|
||||
return@addOnActionSearchListener
|
||||
}
|
||||
getCollectGoods(searchName)
|
||||
}
|
||||
v.addTextChangedListener {
|
||||
if (it.isNullOrBlank()) {
|
||||
getCollectGoods()
|
||||
}
|
||||
}
|
||||
}
|
||||
getCollectGoods()
|
||||
}
|
||||
|
||||
|
||||
private var box: Box<Food>? = null
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun getCollectGoods(searchName:String?=null) {
|
||||
if (box == null) {
|
||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
||||
}
|
||||
list.clear()
|
||||
var queryList = box?.all?.distinctBy { it.name }
|
||||
if (searchName.isNullOrBlank().not()) {
|
||||
queryList = queryList?.filter { it.name?.contains(searchName) == true }
|
||||
}
|
||||
queryList?.forEach {
|
||||
list.add(CollectedFoodBean(foodName = it.name))
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
if (list.isEmpty()) {
|
||||
loadEmptyView()
|
||||
}
|
||||
binding.root.hideKeyboard()
|
||||
}
|
||||
|
||||
private var emptyBinding: LayoutEmptySearchBinding? = null
|
||||
private fun loadEmptyView() {
|
||||
if (emptyBinding == null) {
|
||||
emptyBinding = LayoutEmptySearchBinding.inflate(layoutInflater, binding.rvFoodList, false)
|
||||
}
|
||||
emptyBinding?.root?.let { layout ->
|
||||
layout.setOnClickListener { layout.hideKeyboard() }
|
||||
adapter.stateView = layout
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteGoods(position: Int) {
|
||||
WarnDialog(
|
||||
context = context,
|
||||
content = "请确认是否删除菜品:${list[position].foodName}?",
|
||||
confirmBlock = {
|
||||
Thread {
|
||||
runOnUiThread {
|
||||
showWaitingDialog("加载中……")
|
||||
}
|
||||
val name = list[position].foodName
|
||||
val filterIdList = box?.all?.filter { it.name == name }?.map { it.id }
|
||||
box?.removeByIds(filterIdList)
|
||||
runOnUiThread {
|
||||
hideWaitingDialog()
|
||||
adapter.removeAt(position)
|
||||
ToastUtils.showToast("删除成功")
|
||||
if (list.isEmpty()) {
|
||||
loadEmptyView()
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}).show()
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,13 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.ImageCapture
|
||||
import androidx.camera.core.ImageCaptureException
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.example.utils.FloatBase64Utils
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.adapter.FoodCollectionAdapter
|
||||
import com.sw.dualscreen.adapter.GenericItemAdapter
|
||||
@@ -31,20 +19,17 @@ import com.sw.dualscreen.adapter.GridSpacingItemDecoration
|
||||
import com.sw.dualscreen.adapter.dpToPx
|
||||
import com.sw.dualscreen.databinding.ActivityFoodCollectionBinding
|
||||
import com.sw.dualscreen.databinding.ItemSearchFoodInfoBinding
|
||||
import com.sw.dualscreen.databinding.ItemSearchFoodInfoBinding.inflate
|
||||
import com.sw.dualscreen.ext.clickWithDebounce
|
||||
import com.sw.dualscreen.model.response.FoodInfo
|
||||
import com.sw.dualscreen.objbox.Food
|
||||
import com.sw.dualscreen.objbox.FoodCollectionBean
|
||||
import com.sw.dualscreen.objbox.FoodModule
|
||||
import com.sw.dualscreen.objbox.ObjectBox
|
||||
import com.sw.dualscreen.presentation.SecondaryScreenPresentation
|
||||
import com.sw.dualscreen.sdk.SensorScaleUtils
|
||||
import com.sw.dualscreen.utils.BitmapCropper
|
||||
import com.sw.dualscreen.utils.BitmapSaver
|
||||
import com.sw.dualscreen.utils.CameraHelper
|
||||
import com.sw.dualscreen.utils.Debouncer
|
||||
import com.sw.dualscreen.utils.GlideUtils
|
||||
import com.sw.dualscreen.utils.ImageUtil
|
||||
import com.sw.dualscreen.utils.StorageUtils
|
||||
import com.sw.dualscreen.view.CustomBottomSheetDialog
|
||||
import com.sw.dualscreen.viewmodel.BaseViewModel
|
||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
@@ -55,48 +40,36 @@ import org.pytorch.IValue
|
||||
import org.pytorch.Module
|
||||
import org.pytorch.torchvision.TensorImageUtils
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
|
||||
private val TAG = "FoodCollectionActivity"
|
||||
private var imageCapture: ImageCapture? = null
|
||||
private var isAnalyzing = true // 控制是否进行图像分析
|
||||
private var imageAnalysis: ImageAnalysis? = null
|
||||
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
|
||||
private var presentation: SecondaryScreenPresentation? = null
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
|
||||
private val viewModel by viewModels<UserViewModel>()
|
||||
private var selectedFoodId: String? = ""
|
||||
private var selectedFoodName: String? = ""
|
||||
private var bottomSheetDialog: CustomBottomSheetDialog? = null
|
||||
|
||||
private val NO_MEAN_RGB = floatArrayOf(0.0f, 0.0f, 0.0f)
|
||||
private val NO_STD_RGB = floatArrayOf(1.0f, 1.0f, 1.0f)
|
||||
|
||||
private var module: Module? = null
|
||||
private var box: Box<Food>? = null
|
||||
private val list: MutableList<FoodCollectionBean> = mutableListOf()
|
||||
private val foodCollectionList: MutableList<FoodCollectionBean> = mutableListOf()
|
||||
|
||||
private lateinit var cameraHelper: CameraHelper
|
||||
|
||||
private lateinit var foodAdapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
|
||||
private val debouncer = Debouncer(2000)
|
||||
|
||||
private val adapter: FoodCollectionAdapter by lazy {
|
||||
FoodCollectionAdapter(list).apply {
|
||||
setOnItemClickListener { _, _, position ->
|
||||
if (list[position].isShowCamera) {
|
||||
// takePhoto()
|
||||
cameraHelper.openCamera()
|
||||
}
|
||||
}
|
||||
private val collectionAdapter: FoodCollectionAdapter by lazy {
|
||||
FoodCollectionAdapter(foodCollectionList).apply {
|
||||
// setOnItemClickListener { _, _, position ->
|
||||
// if (list[position].isShowCamera) {
|
||||
//// takePhoto()
|
||||
// cameraHelper.openCamera()
|
||||
// }
|
||||
// }
|
||||
addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
|
||||
list.removeAt(position)
|
||||
adapter.notifyItemRemoved(position)
|
||||
adapter.notifyItemRangeChanged(position, list.size)
|
||||
collectionAdapter.notifyItemRemoved(position)
|
||||
collectionAdapter.notifyItemRangeChanged(position, list.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,6 +82,30 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
return ActivityFoodCollectionBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private fun cameraCallback(uri:Uri){
|
||||
val index = foodCollectionList.indexOfFirst { it.bitmap == null }
|
||||
if (index == -1) {
|
||||
ToastUtils.showToast("每次只允许保存6条数据")
|
||||
return
|
||||
}
|
||||
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
||||
val cropBitmap = BitmapCropper.cropCenter(
|
||||
original = bitmap,
|
||||
targetWidth = 1300, targetHeight = 900,
|
||||
//offsetX = 30, offsetY = 100
|
||||
)
|
||||
val file = BitmapSaver.saveToAppFilesDir(
|
||||
cropBitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
)
|
||||
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
|
||||
foodCollectionList[index].let {
|
||||
it.bitmap = cropBitmap
|
||||
it.isShowCamera = false
|
||||
}
|
||||
collectionAdapter.notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
override fun initialize() {
|
||||
|
||||
// 初始化 CameraHelper
|
||||
@@ -117,14 +114,14 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
caller = this,
|
||||
authority = "${packageName}.fileprovider"
|
||||
) { uri, path ->
|
||||
if (list.size < 6) {
|
||||
val insertIndex = if (list.isEmpty()) 0 else list.size - 1
|
||||
list.add(insertIndex, FoodCollectionBean(imageUri = uri))
|
||||
} else {
|
||||
list[list.size - 1] = FoodCollectionBean(imageUri = uri)
|
||||
}
|
||||
|
||||
adapter.notifyDataSetChanged()
|
||||
//if (foodCollectionList.size < 6) {
|
||||
// val insertIndex = if (foodCollectionList.isEmpty()) 0 else foodCollectionList.size - 1
|
||||
// foodCollectionList.add(insertIndex, FoodCollectionBean(imageUri = uri))
|
||||
//} else {
|
||||
// foodCollectionList[foodCollectionList.size - 1] = FoodCollectionBean(imageUri = uri)
|
||||
//}
|
||||
//collectionAdapter.notifyDataSetChanged()
|
||||
cameraCallback(uri)
|
||||
}
|
||||
|
||||
binding.ivBack.setOnClickListener {
|
||||
@@ -132,10 +129,10 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
list.add(FoodCollectionBean(isShowCamera = true))
|
||||
foodCollectionList.add(FoodCollectionBean(isShowCamera = true))
|
||||
binding.rvFoodCollection.let {
|
||||
it.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
|
||||
it.adapter = adapter
|
||||
it.adapter = collectionAdapter
|
||||
}
|
||||
|
||||
binding.btnFoodSearch.setOnClickListener {
|
||||
@@ -147,7 +144,7 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
Toast.makeText(this, "请选择菜品名称", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (list.size <= 1) {
|
||||
if (foodCollectionList.size <= 1) {
|
||||
Toast.makeText(this, "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
@@ -166,6 +163,18 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnCollectedGoods.setOnClickListener {
|
||||
|
||||
}
|
||||
binding.btnTakePhoto.clickWithDebounce {
|
||||
val count = foodCollectionList.count { it.bitmap != null }
|
||||
if (count == 6) {
|
||||
ToastUtils.showToast("每次只允许保存6条数据")
|
||||
return@clickWithDebounce
|
||||
}
|
||||
cameraHelper.openCamera()
|
||||
}
|
||||
binding.btnClearData.setOnClickListener { clearData() }
|
||||
foodAdapter = createAdapter()
|
||||
binding.recyclerview.layoutManager = GridLayoutManager(context, 2)
|
||||
// 添加间距装饰(12dp)
|
||||
@@ -177,14 +186,13 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
)
|
||||
)
|
||||
binding.recyclerview.adapter = foodAdapter
|
||||
|
||||
}
|
||||
|
||||
private fun vectorThread() {
|
||||
//Loading.show(this)
|
||||
showWaitingDialog("加载中……")
|
||||
Thread {
|
||||
list.forEachIndexed { index, it ->
|
||||
foodCollectionList.forEachIndexed { index, it ->
|
||||
|
||||
if (!it.isShowCamera)
|
||||
image2VectorTask(it.imageUri!!, index)
|
||||
@@ -219,7 +227,7 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
Timber.tag("mzf1").e(base64Str)
|
||||
val imageVector = outputTensor.dataAsFloatArray
|
||||
box?.put(Food(name = selectedFoodName, foodIdx = 0, foodVector = imageVector))
|
||||
list[position].let {
|
||||
foodCollectionList[position].let {
|
||||
it.imageVector = imageVector
|
||||
it.isFinish = true
|
||||
|
||||
@@ -233,7 +241,7 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
)
|
||||
}
|
||||
runOnUiThread {
|
||||
adapter.notifyItemChanged(position)
|
||||
collectionAdapter.notifyItemChanged(position)
|
||||
}
|
||||
Timber.tag("registerDataChange").e("box.all.size=${box?.all?.size}")
|
||||
}
|
||||
@@ -286,4 +294,21 @@ class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
|
||||
}
|
||||
)
|
||||
}
|
||||
private var clickIndex = -1
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun clearData() {
|
||||
foodCollectionList.forEach {
|
||||
it.bitmap = null
|
||||
it.isShowCamera = true
|
||||
it.isFinish = false
|
||||
}
|
||||
collectionAdapter.notifyDataSetChanged()
|
||||
|
||||
clickIndex = -1
|
||||
binding.editFoodName.setText("")
|
||||
foodAdapter.updateData(mutableListOf())
|
||||
foodAdapter.notifyDataSetChanged()
|
||||
//loadEmptyView()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user