diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 25d81d8..bfc5579 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -57,6 +57,9 @@ + + + () { - private val viewModel by viewModels() - override fun getViewModel(): BaseViewModel { - return viewModel - } - - override fun inflateViewBinding(): ActivityCollectedDataBinding { - return ActivityCollectedDataBinding.inflate(layoutInflater) - } - - private val list: MutableList = 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? = 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() - } -} \ No newline at end of file +//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() { +// private val viewModel by viewModels() +// override fun getViewModel(): BaseViewModel { +// return viewModel +// } +// +// override fun inflateViewBinding(): ActivityCollectedDataBinding { +// return ActivityCollectedDataBinding.inflate(layoutInflater) +// } +// +// private val list: MutableList = 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? = 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() +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/CollectedFoodActivity.kt b/app/src/main/java/com/sw/dualscreen/activity/CollectedFoodActivity.kt new file mode 100644 index 0000000..32687ff --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/CollectedFoodActivity.kt @@ -0,0 +1,137 @@ +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.CollectedFoodNewAdapter +import com.sw.dualscreen.databinding.ActivityCollectedFoodBinding +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 + +class CollectedFoodActivity : BaseActivity() { + private val viewModel by viewModels() + override fun getViewModel(): BaseViewModel { + return viewModel + } + + override fun inflateViewBinding(): ActivityCollectedFoodBinding { + return ActivityCollectedFoodBinding.inflate(layoutInflater) + } + + private val list: MutableList = mutableListOf() + private val adapter by lazy { + CollectedFoodNewAdapter(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.include.let { + it.tvPageTitle.text = "已采集餐品" + it.ivPageBack.setOnClickListener { finish() } + } + binding.ivFoodSearch.setOnClickListener { + val searchName = binding.etInputFood.text.toString().trim() + if (searchName.isBlank()) { + ToastUtils.showToast("请输入物品名称") + return@setOnClickListener + } + getCollectGoods(searchName) + } + binding.etInputFood.let { v -> + v.addOnActionSearchListener { + val searchName = binding.etInputFood.text.toString().trim() + if (searchName.isBlank()) { + ToastUtils.showToast("请输入物品名称") + return@addOnActionSearchListener + } + getCollectGoods(searchName) + } + v.addTextChangedListener { + if (it.isNullOrBlank()) { + getCollectGoods() + } + } + } + getCollectGoods() + } + + + private var box: Box? = 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() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/FoodCollectionActivity.kt b/app/src/main/java/com/sw/dualscreen/activity/FoodCollectionActivity.kt index 32f3b2b..be4bcc0 100644 --- a/app/src/main/java/com/sw/dualscreen/activity/FoodCollectionActivity.kt +++ b/app/src/main/java/com/sw/dualscreen/activity/FoodCollectionActivity.kt @@ -1,370 +1,370 @@ -package com.sw.dualscreen.activity - -import android.annotation.SuppressLint -import android.content.Context -import android.content.Intent -import android.graphics.Bitmap -import android.graphics.Typeface -import android.net.Uri -import android.view.View -import android.view.inputmethod.EditorInfo -import android.view.inputmethod.InputMethodManager -import android.widget.Toast -import androidx.activity.viewModels -import androidx.camera.view.PreviewView -import androidx.core.net.toUri -import androidx.core.view.updateLayoutParams -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.GridLayoutManager -import com.example.utils.FloatBase64Utils -import com.sw.dualscreen.R -import com.sw.dualscreen.adapter.FoodCollectionAdapter -import com.sw.dualscreen.adapter.GenericItemAdapter -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.LayoutCameraPreviewBinding -import com.sw.dualscreen.ext.clickWithDebounce -import com.sw.dualscreen.ext.dp -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.utils.BitmapCropper -import com.sw.dualscreen.utils.BitmapSaver -import com.sw.dualscreen.utils.CameraHelper -import com.sw.dualscreen.utils.CameraUtils -import com.sw.dualscreen.utils.Debouncer -import com.sw.dualscreen.utils.ImageUtil -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 kotlinx.coroutines.launch -import org.pytorch.IValue -import org.pytorch.Module -import org.pytorch.torchvision.TensorImageUtils -import timber.log.Timber -import kotlin.math.max - -class FoodCollectionActivity : BaseActivity() { - companion object { - val MAX_COUNT = 100 - } - private val viewModel by viewModels() - private var selectedFoodId: String? = "" - private var selectedFoodName: String? = "" - - private var box: Box? = null - private val foodCollectionList: MutableList = mutableListOf() - -// private lateinit var cameraHelper: CameraHelper - - private lateinit var foodAdapter: GenericItemAdapter - private val foodList = mutableListOf() // 适配器内部维护的数据列表 - private val debouncer = Debouncer(2000) - private lateinit var previewView: PreviewView - - private val cameraUtils: CameraUtils by lazy { - CameraUtils(this) - } - - private val collectionAdapter: FoodCollectionAdapter by lazy { - FoodCollectionAdapter(foodCollectionList).apply { -// setOnItemClickListener { _, _, position -> -// if (list[position].isShowCamera) { -//// takePhoto() -// cameraHelper.openCamera() +//package com.sw.dualscreen.activity +// +//import android.annotation.SuppressLint +//import android.content.Context +//import android.content.Intent +//import android.graphics.Bitmap +//import android.graphics.Typeface +//import android.net.Uri +//import android.view.View +//import android.view.inputmethod.EditorInfo +//import android.view.inputmethod.InputMethodManager +//import android.widget.Toast +//import androidx.activity.viewModels +//import androidx.camera.view.PreviewView +//import androidx.core.net.toUri +//import androidx.core.view.updateLayoutParams +//import androidx.lifecycle.lifecycleScope +//import androidx.recyclerview.widget.GridLayoutManager +//import com.example.utils.FloatBase64Utils +//import com.sw.dualscreen.R +//import com.sw.dualscreen.adapter.FoodCollectionAdapter +//import com.sw.dualscreen.adapter.GenericItemAdapter +//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.LayoutCameraPreviewBinding +//import com.sw.dualscreen.ext.clickWithDebounce +//import com.sw.dualscreen.ext.dp +//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.utils.BitmapCropper +//import com.sw.dualscreen.utils.BitmapSaver +//import com.sw.dualscreen.utils.CameraHelper +//import com.sw.dualscreen.utils.CameraUtils +//import com.sw.dualscreen.utils.Debouncer +//import com.sw.dualscreen.utils.ImageUtil +//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 kotlinx.coroutines.launch +//import org.pytorch.IValue +//import org.pytorch.Module +//import org.pytorch.torchvision.TensorImageUtils +//import timber.log.Timber +//import kotlin.math.max +// +//class FoodCollectionActivity : BaseActivity() { +// companion object { +// val MAX_COUNT = 100 +// } +// private val viewModel by viewModels() +// private var selectedFoodId: String? = "" +// private var selectedFoodName: String? = "" +// +// private var box: Box? = null +// private val foodCollectionList: MutableList = mutableListOf() +// +//// private lateinit var cameraHelper: CameraHelper +// +// private lateinit var foodAdapter: GenericItemAdapter +// private val foodList = mutableListOf() // 适配器内部维护的数据列表 +// private val debouncer = Debouncer(2000) +// private lateinit var previewView: PreviewView +// +// private val cameraUtils: CameraUtils by lazy { +// CameraUtils(this) +// } +// +// 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) +//// collectionAdapter.notifyItemRemoved(position) +//// collectionAdapter.notifyItemRangeChanged(position, list.size) +// foodCollectionList[position].let { +// it.bitmap = null +// it.isShowCamera = true +// it.isFinish = false +// } +// notifyItemChanged(position) +// } +// } +// } +// +// override fun getViewModel(): BaseViewModel { +// return viewModel +// } +// +// override fun inflateViewBinding(): ActivityFoodCollectionBinding { +// return ActivityFoodCollectionBinding.inflate(layoutInflater) +// } +// +// private val cameraCallback: (Uri) -> Unit = { uri -> +// val index = foodCollectionList.indexOfFirst { it.bitmap == null } +// if (index == -1) { +// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") +// rerurn@ cameraCallback +// } +// ImageUtil.uriToBitmap(this, uri)?.let { bitmap -> +//// val cropBitmap = BitmapCropper.cropCenter( +//// original = bitmap, +//// targetWidth = 1300, targetHeight = 900, +//// //offsetX = 30, offsetY = 100 +//// ) +// val file = BitmapSaver.saveToAppFilesDir( +// bitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg" +// ) +// Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}") +// +// foodCollectionList[index].let { +// it.bitmap = bitmap +// it.isShowCamera = false +// it.imageUri = file?.toUri() +// } +// collectionAdapter.notifyItemChanged(index) +// } +// } +// +// @SuppressLint("NotifyDataSetChanged") +// private fun takePhoto() { +// val count = foodCollectionList.count { it.bitmap != null } +// if (count >= MAX_COUNT) { +// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") +// return +// } +// cameraUtils.takePhoto(cameraCallback) +// } +// +// override fun initialize() { +// cameraUtils.initCamera() +// val previewBinding = +// LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview) +// previewView = previewBinding.previewView.also { +// it.updateLayoutParams { +// width = 180.dp +// height = 180.dp +// } +// } +// cameraUtils.setPreviewController(previewView) +// // 初始化 CameraHelper +//// cameraHelper = CameraHelper( +//// context = this, +//// caller = this, +//// authority = "${packageName}.fileprovider" +//// ) { uri, path -> +//// //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 { +// val intent = Intent(this, MainActivity::class.java) +// startActivity(intent) +// finish() +// } +// repeat(MAX_COUNT) { +// foodCollectionList.add(FoodCollectionBean(isShowCamera = true)) +// } +// binding.rvFoodCollection.let { +// it.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false) +// it.adapter = collectionAdapter +// } +// +// binding.btnFoodSearch.setOnClickListener { +// searchInfo() +// } +// +// binding.btnSave.setOnClickListener { +// if (selectedFoodName.isNullOrBlank()) { +// Toast.makeText(this, "请选择菜品名称", Toast.LENGTH_SHORT).show() +// return@setOnClickListener +// } +// if (foodCollectionList.size <= 1) { +// Toast.makeText(this, "请拍摄菜品照片", Toast.LENGTH_SHORT).show() +// return@setOnClickListener +// } +// vectorThread() +// } +// +// binding.editFoodName.setOnEditorActionListener { v, actionId, event -> +// if (actionId == EditorInfo.IME_ACTION_SEARCH) { +// searchInfo() +// val imm = +// v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager +// imm.hideSoftInputFromWindow(v.windowToken, 0) +// true +// } else { +// false +// } +// } +// +// binding.btnCollectedGoods.setOnClickListener { +// startActivity(Intent(this, CollectedDataActivity::class.java)) +// } +// binding.btnTakePhoto.clickWithDebounce { +// binding.btnTakePhoto.text = "拍照" +// val count = foodCollectionList.count { it.bitmap != null } +// if (count >= MAX_COUNT) { +// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") +// return@clickWithDebounce +// } +//// cameraHelper.openCamera() +// takePhoto() +// } +// binding.btnClearData.setOnClickListener { clearData() } +// foodAdapter = createAdapter() +// binding.recyclerview.layoutManager = GridLayoutManager(context, 2) +// // 添加间距装饰(12dp) +// binding.recyclerview.addItemDecoration( +// GridSpacingItemDecoration( +// spanCount = 2, +// spacing = dpToPx(30), +// includeEdge = false // 包含边缘间距 +// ) +// ) +// binding.recyclerview.adapter = foodAdapter +// } +// +// private fun vectorThread() { +// //Loading.show(this) +// showWaitingDialog("加载中……") +// Thread { +// foodCollectionList +// .filter { it.bitmap != null } +// .forEachIndexed { index, it -> +// image2VectorTask(it, index) +// } +// runOnUiThread { +// window.decorView.postDelayed({ +// //Loading.dismiss() +// hideWaitingDialog() +// }, 1000) +// } +// }.start() +// } +// +// private fun initBox() { +// if (box == null) { +// box = ObjectBox.boxStore.boxFor(Food::class) +// } +// } +// +// private fun image2VectorTask(item: FoodCollectionBean, position: Int) { +// initBox() +// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!) +// +// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector) +// Timber.tag("mzf1").e(base64Str) +//// viewModel.postImageData( +//// context, +//// foodId = selectedFoodId.toString(), +//// foodName = selectedFoodName.toString(), +//// foodVector = base64Str, +//// uri = item.imageUri!! +//// ) +// box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector)) +// foodCollectionList[position].let { +// it.imageVector = imageVector +// it.isFinish = true +// } +// +// runOnUiThread { +// collectionAdapter.notifyItemChanged(position) +// } +// } +// +// +// private fun searchInfo() { +// debouncer.debounce { +// viewModel.searchByFoodName(binding.editFoodName.text.toString()) +// } +// } +// +// override fun registerDataChange() { +// super.registerDataChange() +// lifecycleScope.launch { +// viewModel.searchFoodInfoList.collect { +//// foodList.clear() +//// foodList.addAll(it) +// foodAdapter.updateData(it) +// } +// } +// } +// +// +// private var checkedItem: FoodInfo? = null +// private fun createAdapter(): GenericItemAdapter { +// return GenericItemAdapter( +// items = emptyList(), +// bindingInflater = ItemSearchFoodInfoBinding::inflate, +// bindCallback = { item, position -> +// this.tvName.text = item.foodName +// if (item.id != checkedItem?.id) { +// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL) +// this.tvName.setTextColor(resources.getColor(R.color.search_normal)) +// this.llRoot.setBackgroundResource(R.drawable.grid_search_item_normal) +// } else { +// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD) +// this.tvName.setTextColor(resources.getColor(R.color.search_checked)) +// this.llRoot.setBackgroundResource(R.drawable.grid_search_item_checked) +// } +// +// this.llRoot.setOnClickListener { +// Timber.d("itemClick ${item.foodName}, position = $position") +// checkedItem = item +//// viewModel.updateCurrentItem(item) +//// itemClickCallback(item) +// selectedFoodName = item.foodName +// selectedFoodId = item.id +// +// foodAdapter.notifyDataSetChanged() // } // } - addOnItemChildClickListener(R.id.ivDelete) { _, _, position -> -// list.removeAt(position) -// collectionAdapter.notifyItemRemoved(position) -// collectionAdapter.notifyItemRangeChanged(position, list.size) - foodCollectionList[position].let { - it.bitmap = null - it.isShowCamera = true - it.isFinish = false - } - notifyItemChanged(position) - } - } - } - - override fun getViewModel(): BaseViewModel { - return viewModel - } - - override fun inflateViewBinding(): ActivityFoodCollectionBinding { - return ActivityFoodCollectionBinding.inflate(layoutInflater) - } - - private val cameraCallback: (Uri) -> Unit = { uri -> - val index = foodCollectionList.indexOfFirst { it.bitmap == null } - if (index == -1) { - ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") - rerurn@ cameraCallback - } - ImageUtil.uriToBitmap(this, uri)?.let { bitmap -> -// val cropBitmap = BitmapCropper.cropCenter( -// original = bitmap, -// targetWidth = 1300, targetHeight = 900, -// //offsetX = 30, offsetY = 100 -// ) - val file = BitmapSaver.saveToAppFilesDir( - bitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg" - ) - Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}") - - foodCollectionList[index].let { - it.bitmap = bitmap - it.isShowCamera = false - it.imageUri = file?.toUri() - } - collectionAdapter.notifyItemChanged(index) - } - } - - @SuppressLint("NotifyDataSetChanged") - private fun takePhoto() { - val count = foodCollectionList.count { it.bitmap != null } - if (count >= MAX_COUNT) { - ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") - return - } - cameraUtils.takePhoto(cameraCallback) - } - - override fun initialize() { - cameraUtils.initCamera() - val previewBinding = - LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview) - previewView = previewBinding.previewView.also { - it.updateLayoutParams { - width = 180.dp - height = 180.dp - } - } - cameraUtils.setPreviewController(previewView) - // 初始化 CameraHelper -// cameraHelper = CameraHelper( -// context = this, -// caller = this, -// authority = "${packageName}.fileprovider" -// ) { uri, path -> -// //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 { - val intent = Intent(this, MainActivity::class.java) - startActivity(intent) - finish() - } - repeat(MAX_COUNT) { - foodCollectionList.add(FoodCollectionBean(isShowCamera = true)) - } - binding.rvFoodCollection.let { - it.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false) - it.adapter = collectionAdapter - } - - binding.btnFoodSearch.setOnClickListener { - searchInfo() - } - - binding.btnSave.setOnClickListener { - if (selectedFoodName.isNullOrBlank()) { - Toast.makeText(this, "请选择菜品名称", Toast.LENGTH_SHORT).show() - return@setOnClickListener - } - if (foodCollectionList.size <= 1) { - Toast.makeText(this, "请拍摄菜品照片", Toast.LENGTH_SHORT).show() - return@setOnClickListener - } - vectorThread() - } - - binding.editFoodName.setOnEditorActionListener { v, actionId, event -> - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - searchInfo() - val imm = - v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.hideSoftInputFromWindow(v.windowToken, 0) - true - } else { - false - } - } - - binding.btnCollectedGoods.setOnClickListener { - startActivity(Intent(this, CollectedDataActivity::class.java)) - } - binding.btnTakePhoto.clickWithDebounce { - binding.btnTakePhoto.text = "拍照" - val count = foodCollectionList.count { it.bitmap != null } - if (count >= MAX_COUNT) { - ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") - return@clickWithDebounce - } -// cameraHelper.openCamera() - takePhoto() - } - binding.btnClearData.setOnClickListener { clearData() } - foodAdapter = createAdapter() - binding.recyclerview.layoutManager = GridLayoutManager(context, 2) - // 添加间距装饰(12dp) - binding.recyclerview.addItemDecoration( - GridSpacingItemDecoration( - spanCount = 2, - spacing = dpToPx(30), - includeEdge = false // 包含边缘间距 - ) - ) - binding.recyclerview.adapter = foodAdapter - } - - private fun vectorThread() { - //Loading.show(this) - showWaitingDialog("加载中……") - Thread { - foodCollectionList - .filter { it.bitmap != null } - .forEachIndexed { index, it -> - image2VectorTask(it, index) - } - runOnUiThread { - window.decorView.postDelayed({ - //Loading.dismiss() - hideWaitingDialog() - }, 1000) - } - }.start() - } - - private fun initBox() { - if (box == null) { - box = ObjectBox.boxStore.boxFor(Food::class) - } - } - - private fun image2VectorTask(item: FoodCollectionBean, position: Int) { - initBox() - val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!) - - val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector) - Timber.tag("mzf1").e(base64Str) -// viewModel.postImageData( -// context, -// foodId = selectedFoodId.toString(), -// foodName = selectedFoodName.toString(), -// foodVector = base64Str, -// uri = item.imageUri!! // ) - box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector)) - foodCollectionList[position].let { - it.imageVector = imageVector - it.isFinish = true - } - - runOnUiThread { - collectionAdapter.notifyItemChanged(position) - } - } - - - private fun searchInfo() { - debouncer.debounce { - viewModel.searchByFoodName(binding.editFoodName.text.toString()) - } - } - - override fun registerDataChange() { - super.registerDataChange() - lifecycleScope.launch { - viewModel.searchFoodInfoList.collect { -// foodList.clear() -// foodList.addAll(it) - foodAdapter.updateData(it) - } - } - } - - - private var checkedItem: FoodInfo? = null - private fun createAdapter(): GenericItemAdapter { - return GenericItemAdapter( - items = emptyList(), - bindingInflater = ItemSearchFoodInfoBinding::inflate, - bindCallback = { item, position -> - this.tvName.text = item.foodName - if (item.id != checkedItem?.id) { - this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL) - this.tvName.setTextColor(resources.getColor(R.color.search_normal)) - this.llRoot.setBackgroundResource(R.drawable.grid_search_item_normal) - } else { - this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD) - this.tvName.setTextColor(resources.getColor(R.color.search_checked)) - this.llRoot.setBackgroundResource(R.drawable.grid_search_item_checked) - } - - this.llRoot.setOnClickListener { - Timber.d("itemClick ${item.foodName}, position = $position") - checkedItem = item -// viewModel.updateCurrentItem(item) -// itemClickCallback(item) - selectedFoodName = item.foodName - selectedFoodId = item.id - - foodAdapter.notifyDataSetChanged() - } - } - ) - } - - 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("") -// foodList.clear() -// foodAdapter.updateData(mutableListOf()) -// foodAdapter.notifyDataSetChanged() - //loadEmptyView() - } - - override fun onResume() { - super.onResume() - cameraUtils.bind() - binding.llCameraFlag.run { - visibility = View.VISIBLE - postDelayed({ - visibility = View.GONE - }, 3000) - } - } - - override fun onPause() { - super.onPause() - cameraUtils.unbind() - binding.llCameraFlag.visibility = View.VISIBLE - } - -} \ No newline at end of file +// } +// +// 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("") +//// foodList.clear() +//// foodAdapter.updateData(mutableListOf()) +//// foodAdapter.notifyDataSetChanged() +// //loadEmptyView() +// } +// +// override fun onResume() { +// super.onResume() +// cameraUtils.bind() +// binding.llCameraFlag.run { +// visibility = View.VISIBLE +// postDelayed({ +// visibility = View.GONE +// }, 3000) +// } +// } +// +// override fun onPause() { +// super.onPause() +// cameraUtils.unbind() +// binding.llCameraFlag.visibility = View.VISIBLE +// } +// +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/MainActivity.kt b/app/src/main/java/com/sw/dualscreen/activity/MainActivity.kt index 454f28b..ed9cae1 100644 --- a/app/src/main/java/com/sw/dualscreen/activity/MainActivity.kt +++ b/app/src/main/java/com/sw/dualscreen/activity/MainActivity.kt @@ -1,5 +1,6 @@ package com.sw.dualscreen.activity +import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.graphics.Outline @@ -28,11 +29,13 @@ import com.sw.dualscreen.GlobalKey import com.sw.dualscreen.R import com.sw.dualscreen.adapter.GenericItemAdapter import com.sw.dualscreen.adapter.GridSpacingItemDecoration +import com.sw.dualscreen.adapter.SearchFoodAdapter import com.sw.dualscreen.adapter.dpToPx import com.sw.dualscreen.databinding.ActivityMainBinding import com.sw.dualscreen.databinding.ItemFoodInfoBinding import com.sw.dualscreen.ext.dp import com.sw.dualscreen.ext.format2String +import com.sw.dualscreen.ext.visible import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.objbox.FoodModule import com.sw.dualscreen.objbox.FoodModule.IdNameScore @@ -55,6 +58,10 @@ import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel import kotlinx.coroutines.launch import timber.log.Timber import java.io.File +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.util.Locale import java.util.concurrent.Executors import kotlin.math.roundToInt @@ -67,7 +74,23 @@ class MainActivity : BaseActivity() { private var isAnalyzing = true // 控制是否进行图像分析 private var presentation: SecondaryScreenPresentation? = null private val executor = Executors.newSingleThreadExecutor() - private lateinit var adapter: GenericItemAdapter + private val searchFoodList = mutableListOf() + private val adapter by lazy { + SearchFoodAdapter(searchFoodList).apply { + setOnItemClickListener { adapter, view, position -> + searchFoodList.forEachIndexed { index, info -> + searchFoodList[index].isChecked = index == position + } + val item = searchFoodList[position] + Timber.d("itemClick ${item.foodName}, position = $position") + item.photoUri = null + checkedItem = item + notifyDataSetChanged() + // TODO 暂时注释--------------- + //updateCurrentFood(item) + } + } + } private var checkedItem: FoodInfo? = null private var imageAnalysis: ImageAnalysis? = null private var cameraProviderFuture: ListenableFuture? = null @@ -102,11 +125,16 @@ class MainActivity : BaseActivity() { private fun initView() { viewModel.activeEngine() - binding.foodDisplayLayout.setOnClickListener { - val intent = Intent(this, FoodCollectionActivity::class.java) - startActivity(intent) + updateDateTime() + binding.ivSetting.setOnClickListener { + startActivity(Intent(this, SettingActivity::class.java)) finish() } + //binding.foodDisplayLayout.setOnClickListener { + // val intent = Intent(this, FoodCollectionActivity::class.java) + // startActivity(intent) + // finish() + //} binding.previewView.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setRoundRect(0, 0, view.width, view.height, 12f.dp) @@ -121,49 +149,57 @@ class MainActivity : BaseActivity() { bottomSheetDialog!!.show(supportFragmentManager, "CustomBottomSheetDialog") } - val spinnerAdapter = ArrayAdapter( - this, - R.layout.item_for_custom_spinner, - arrayOf("即放即取", "余量取餐") - ) - binding.spinner.adapter = spinnerAdapter + //val spinnerAdapter = ArrayAdapter( + // this, + // R.layout.item_for_custom_spinner, + // arrayOf("即放即取", "余量取餐") + //) + //binding.spinner.adapter = spinnerAdapter val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) - binding.spinner.setSelection(mode ?: 0) + //binding.spinner.setSelection(mode ?: 0) presentation?.updateMealPickupMode(mode ?: 0) - binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected( - parent: AdapterView<*>?, - view: View?, - position: Int, - id: Long - ) { - SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, position) - updateCurrentFood(null) - isRecognitionFood = true - presentation?.updateMealPickupMode(position) - - SensorScaleUtils.zero() - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} + //binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + // override fun onItemSelected( + // parent: AdapterView<*>?, + // view: View?, + // position: Int, + // id: Long + // ) { + // SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, position) + // updateCurrentFood(null) + // isRecognitionFood = true + // presentation?.updateMealPickupMode(position) +// + // SensorScaleUtils.zero() + // } +// + // override fun onNothingSelected(parent: AdapterView<*>?) {} + //} + //adapter = createAdapter() + binding.recyclerview.let { + it.layoutManager = GridLayoutManager(this, 2) + it.adapter = adapter } - adapter = createAdapter() - binding.recyclerview.layoutManager = GridLayoutManager(this, 2) // 添加间距装饰(12dp) - binding.recyclerview.addItemDecoration( - GridSpacingItemDecoration( - spanCount = 2, - spacing = dpToPx(30), - includeEdge = false // 包含边缘间距 - ) - ) - binding.recyclerview.adapter = adapter + //binding.recyclerview.addItemDecoration( + // GridSpacingItemDecoration( + // spanCount = 2, + // spacing = dpToPx(30), + // includeEdge = false // 包含边缘间距 + // ) + //) + //binding.recyclerview.adapter = adapter binding.tvFoodName.setOnClickListener { SensorScaleUtils.zero() } binding.tvRescan.setOnClickListener { debouncer.debounce { recognizeFood() } } + binding.btnPay.setOnClickListener { + startActivity(Intent(this, PayActivity::class.java).apply { + putExtra(PayActivity.FOOD_INFO, checkedItem) + }) + } } fun updateCurrentFood(foodInfo: FoodInfo?) { @@ -204,7 +240,23 @@ class MainActivity : BaseActivity() { // } lifecycleScope.launch { viewModel.identifiedFoodInfoList.collect { list -> - adapter.updateData(list) + //adapter.updateData(list) + searchFoodList.clear() + searchFoodList.addAll(list) + adapter.notifyDataSetChanged() + + //TODO 暂时写死数据测试--------------------------- + binding.flPay.visible() + binding.recyclerview.visible() + searchFoodList.clear() + searchFoodList.add(FoodInfo(foodName = "岐山臊子面")) + searchFoodList.add(FoodInfo(foodName = "肉末干拌面")) + searchFoodList.add(FoodInfo(foodName = "雪菜肉丝面")) + searchFoodList.add(FoodInfo(foodName = "康帅博方便面")) + searchFoodList.add(FoodInfo(foodName = "担担面")) + searchFoodList.add(FoodInfo(foodName = "四合一干拌面")) + adapter.notifyDataSetChanged() + if (list.isNotEmpty()) { checkedItem = list[0] checkedItem!!.photoUri = lastPhotoUri @@ -213,7 +265,8 @@ class MainActivity : BaseActivity() { } } } - SensorScaleUtils.startScale { weight -> + + SensorScaleUtils.addWeightListener { weight -> Timber.d("registerDataChange weight = $weight") presentation?.updateWeight(weight) @@ -281,6 +334,7 @@ class MainActivity : BaseActivity() { } } + @SuppressLint("NotifyDataSetChanged") private fun updateFoodInfo(list: List, scoreList: List) { Timber.d("registerDataChange识别后查询接口数据:${GsonUtils.toJson(list)}") list.forEach { foodInfo -> @@ -288,7 +342,10 @@ class MainActivity : BaseActivity() { val score = scoreItem?.score ?: 0.0 foodInfo.score = ((1 - score) * 10000).roundToInt() } - adapter.updateData(list) + searchFoodList.clear() + searchFoodList.addAll(list) + adapter.notifyDataSetChanged() + //adapter.updateData(list) if (list.isNotEmpty()) { checkedItem = list[0] checkedItem!!.photoUri = lastPhotoUri @@ -298,33 +355,33 @@ class MainActivity : BaseActivity() { } } - private fun createAdapter(): GenericItemAdapter { - return GenericItemAdapter( - items = emptyList(), - bindingInflater = ItemFoodInfoBinding::inflate, - bindCallback = { item, position -> - val score = (item.score / 100.0).format2String(2) - this.tvName.text = "${item.foodName}\n${score}%" - if (item.id != checkedItem?.id) { - this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL) - this.tvName.setTextColor(resources.getColor(R.color.identify_normal)) - this.llRoot.setBackgroundResource(R.drawable.grid_item_normal) - } else { - this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD) - this.tvName.setTextColor(resources.getColor(R.color.identify_checked)) - this.llRoot.setBackgroundResource(R.drawable.grid_item_checked) - } -// - this.llRoot.setOnClickListener { - Timber.d("itemClick ${item.foodName}, position = $position") - item.photoUri = null - checkedItem = item - adapter.notifyDataSetChanged() - updateCurrentFood(item) - } - } - ) - } +// private fun createAdapter(): GenericItemAdapter { +// return GenericItemAdapter( +// items = emptyList(), +// bindingInflater = ItemFoodInfoBinding::inflate, +// bindCallback = { item, position -> +// val score = (item.score / 100.0).format2String(2) +// this.tvName.text = "${item.foodName}\n${score}%" +// if (item.id != checkedItem?.id) { +// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL) +// this.tvName.setTextColor(resources.getColor(R.color.identify_normal)) +// this.llRoot.setBackgroundResource(R.drawable.grid_item_normal) +// } else { +// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD) +// this.tvName.setTextColor(resources.getColor(R.color.identify_checked)) +// this.llRoot.setBackgroundResource(R.drawable.grid_item_checked) +// } +//// +// this.llRoot.setOnClickListener { +// Timber.d("itemClick ${item.foodName}, position = $position") +// item.photoUri = null +// checkedItem = item +// adapter.notifyDataSetChanged() +// updateCurrentFood(item) +// } +// } +// ) +// } private fun setupCamera() { Timber.d("setupCamera") @@ -496,15 +553,24 @@ class MainActivity : BaseActivity() { } } + @SuppressLint("NotifyDataSetChanged") fun clearFoodList() { - adapter.updateData(listOf()) + //adapter.updateData(listOf()) + searchFoodList.clear() adapter.notifyDataSetChanged() } override fun onDestroy() { - SensorScaleUtils.closeScale() + //SensorScaleUtils.closeScale() presentation?.dismiss() super.onDestroy() shutdownCamera() } + + private fun updateDateTime() { + val formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 EEEE", Locale.CHINA) + val dateTime = formatter.format(LocalDateTime.now(ZoneId.of("Asia/Shanghai"))) + binding.tvTitleTime.text = dateTime + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/PayActivity.kt b/app/src/main/java/com/sw/dualscreen/activity/PayActivity.kt new file mode 100644 index 0000000..ed19bae --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/PayActivity.kt @@ -0,0 +1,128 @@ +package com.sw.dualscreen.activity + +import android.view.View +import androidx.activity.viewModels +import androidx.fragment.app.Fragment +import com.sw.dualscreen.R +import com.sw.dualscreen.activity.fragment.CashPayFragment +import com.sw.dualscreen.activity.fragment.FacePayFragment +import com.sw.dualscreen.activity.fragment.NumberPayFragment +import com.sw.dualscreen.activity.fragment.PayResultFragment +import com.sw.dualscreen.activity.fragment.QrCodePayFragment +import com.sw.dualscreen.databinding.ActivityPayBinding +import com.sw.dualscreen.model.response.FoodInfo +import com.sw.dualscreen.viewmodel.BaseViewModel +import com.sw.dualscreen.viewmodel.UserViewModel + +class PayActivity : BaseActivity() { + + companion object { + + const val FOOD_INFO = "foodInfo" + const val TAG_PAY_QR_CODE = "tagPayQrCode" + const val TAG_PAY_CASH = "tagPayCash" + const val TAG_PAY_NUMBER = "tagPayNumber" + const val TAG_PAY_FACE = "tagPayFace" + const val TAG_PAY_RESULT = "tagPayResult" + } + + private val viewModel by viewModels() + + override fun getViewModel(): BaseViewModel { + return viewModel + } + + override fun inflateViewBinding(): ActivityPayBinding { + return ActivityPayBinding.inflate(layoutInflater) + } + + var foodInfo: FoodInfo? = null + + private var qrCodePayFragment: QrCodePayFragment? = null + private var cashPayFragment: CashPayFragment? = null + private var numberPayFragment: NumberPayFragment? = null + private var facePayFragment: FacePayFragment? = null + private var payResultFragment: PayResultFragment? = null + + @Suppress("DEPRECATION") + override fun initialize() { + super.initialize() + foodInfo = intent.getParcelableExtra(FOOD_INFO) + binding.tvFoodName.text = foodInfo?.foodName + binding.include.ivPageBack.setOnClickListener { finish() } + binding.include.tvPageTitle.text = "下单结算" + val payQrCodeClickListener = View.OnClickListener { + if (qrCodePayFragment == null) { + qrCodePayFragment = QrCodePayFragment() + } + addFragment(qrCodePayFragment!!, TAG_PAY_QR_CODE) + switchButton(true, false, false, false) + } + binding.btnPayQrCode.setOnClickListener(payQrCodeClickListener) + binding.btnPayCash.setOnClickListener { + if (cashPayFragment == null) { + cashPayFragment = CashPayFragment() + } + addFragment(cashPayFragment!!, TAG_PAY_CASH) + switchButton(false, true, false, false) + } + binding.btnPayNumber.setOnClickListener { + if (numberPayFragment == null) { + numberPayFragment = NumberPayFragment() + } + addFragment(numberPayFragment!!, TAG_PAY_NUMBER) + switchButton(false, false, true, false) + } + binding.btnPayFace.setOnClickListener { + showFacePay() + } + + payQrCodeClickListener.onClick(binding.btnPayQrCode) + } + + private fun switchButton(vararg arr: Boolean) { + binding.btnPayQrCode.isChecked = arr[0] + binding.btnPayCash.isChecked = arr[1] + binding.btnPayNumber.isChecked = arr[2] + binding.btnPayFace.isChecked = arr[3] + } + + fun showFacePay() { + if (facePayFragment == null) { + facePayFragment = FacePayFragment() + } + addFragment(facePayFragment!!, TAG_PAY_FACE) + switchButton(false, false, false, true) + } + + private fun addFragment(currentFragment: Fragment, tag: String) { + runCatching { + supportFragmentManager.beginTransaction().apply { + val existFragment = supportFragmentManager.findFragmentByTag(tag) + if (existFragment == null) { + add(R.id.fragmentContainerView, currentFragment, tag) + } + val fragments = supportFragmentManager.fragments + fragments.forEach { + it?.let { fragment -> + if (fragment != currentFragment) { + hide(fragment) + } + } + } + show(currentFragment) + commitAllowingStateLoss() + } + }.onFailure { + it.printStackTrace() + } + } + + fun showPayResult() { + if (payResultFragment == null) { + payResultFragment = PayResultFragment() + } + addFragment(payResultFragment!!, TAG_PAY_RESULT) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/SettingActivity.kt b/app/src/main/java/com/sw/dualscreen/activity/SettingActivity.kt new file mode 100644 index 0000000..977bd4d --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/SettingActivity.kt @@ -0,0 +1,71 @@ +package com.sw.dualscreen.activity + +import android.content.Intent +import androidx.activity.viewModels +import androidx.fragment.app.Fragment +import com.sw.dualscreen.R +import com.sw.dualscreen.activity.fragment.BusinessFragment +import com.sw.dualscreen.activity.fragment.CollectFragment +import com.sw.dualscreen.databinding.ActivitySettingBinding +import com.sw.dualscreen.model.response.FoodInfo +import com.sw.dualscreen.viewmodel.BaseViewModel +import com.sw.dualscreen.viewmodel.UserViewModel +import kotlin.collections.get +import kotlin.text.replace + +class SettingActivity : BaseActivity() { + + private val viewModel by viewModels() + override fun getViewModel(): BaseViewModel { + return viewModel + } + + override fun inflateViewBinding(): ActivitySettingBinding { + return ActivitySettingBinding.inflate(layoutInflater) + } + + private val fragmentList = mutableListOf().apply { + add(BusinessFragment()) + add(CollectFragment()) + } + + override fun initialize() { + super.initialize() + binding.include.let { + it.ivPageBack.setOnClickListener { + val intent = Intent(this, MainActivity::class.java) + startActivity(intent) + finish() + } + it.tvPageTitle.text = "设置" + } + binding.rgSetting.setOnCheckedChangeListener { group, checkedId -> + if (checkedId == R.id.rbBusiness) { + showFragment(fragmentList[0]) + return@setOnCheckedChangeListener + } + if (checkedId == R.id.rbCollect) { + + showFragment(fragmentList[1]) + return@setOnCheckedChangeListener + } + } + binding.rgSetting.check(R.id.rbBusiness) + } + + private fun showFragment(fragment: Fragment) { + runCatching { + supportFragmentManager.beginTransaction().apply { + replace(R.id.fragmentContainerView, fragment) + commit() + } + }.onFailure { + it.printStackTrace() + } + } + + fun searchByFoodName(foodName:String, action: (List) -> Unit) { + viewModel.searchByFoodName(foodName, action) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/BaseFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/BaseFragment.kt new file mode 100644 index 0000000..4559989 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/BaseFragment.kt @@ -0,0 +1,32 @@ +package com.sw.dualscreen.activity.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.viewbinding.ViewBinding + +abstract class BaseFragment: Fragment() { + + protected lateinit var binding: VB + + protected abstract fun inflateViewBinding(): VB + + abstract fun initialize() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = inflateViewBinding() + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initialize() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/BusinessFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/BusinessFragment.kt new file mode 100644 index 0000000..1144834 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/BusinessFragment.kt @@ -0,0 +1,42 @@ +package com.sw.dualscreen.activity.fragment + +import android.view.LayoutInflater +import com.sw.dualscreen.GlobalKey +import com.sw.dualscreen.R +import com.sw.dualscreen.databinding.FragmentBusinessBinding +import com.sw.dualscreen.sdk.SensorScaleUtils +import com.sw.dualscreen.utils.SPUtil +import kotlin.math.roundToInt + +class BusinessFragment: BaseFragment() { + + override fun inflateViewBinding(): FragmentBusinessBinding { + return FragmentBusinessBinding.inflate(LayoutInflater.from(context)) + } + + override fun initialize() { + binding.rgCharge.let { + it.setOnCheckedChangeListener { group, checkedId -> + val mode = if (checkedId == R.id.rbChargeYes) 0 else 1 + SPUtil.getInstance().put(GlobalKey.KEY_CHARGE_MODE, mode) + } + val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) + it.check(if (mode == 0) R.id.rbChargeYes else R.id.rbChargeNot) + } + binding.rgTakeFood.let { + it.setOnCheckedChangeListener { group, checkedId -> + val mode = if (checkedId == R.id.rbPickAndPlace) 0 else 1 + SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode) + } + val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) + it.check(if (mode == 0) R.id.rbPickAndPlace else R.id.rbSurplusCalculate) + } + binding.btnClearZero.setOnClickListener { + SensorScaleUtils.tare() + } + SensorScaleUtils.addWeightListener { value -> + val realWeight = (value * 1000).roundToInt() + binding.tvFoodWeight.text = "$realWeight" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/CashPayFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/CashPayFragment.kt new file mode 100644 index 0000000..64e5b32 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/CashPayFragment.kt @@ -0,0 +1,25 @@ +package com.sw.dualscreen.activity.fragment + +import android.text.Spanned +import android.text.SpannedString +import android.text.style.AbsoluteSizeSpan +import androidx.core.text.buildSpannedString +import com.sw.dualscreen.databinding.FragmentCashPayBinding + +class CashPayFragment: BaseFragment() { + + override fun inflateViewBinding(): FragmentCashPayBinding { + return FragmentCashPayBinding.inflate(layoutInflater) + } + + override fun initialize() { + binding.tvRealAmount.text = getAmountText("36.8") + } + + private fun getAmountText(amount:String): SpannedString { + return buildSpannedString { + append("¥", AbsoluteSizeSpan(36, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + append(amount, AbsoluteSizeSpan(60, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt new file mode 100644 index 0000000..4db19cd --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/CollectFragment.kt @@ -0,0 +1,285 @@ +package com.sw.dualscreen.activity.fragment + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.view.LayoutInflater +import android.view.View +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputMethodManager +import android.widget.Toast +import androidx.camera.view.PreviewView +import androidx.core.net.toUri +import androidx.core.view.updateLayoutParams +import androidx.recyclerview.widget.GridLayoutManager +import com.sw.dualscreen.R +import com.sw.dualscreen.activity.CollectedFoodActivity +import com.sw.dualscreen.activity.SettingActivity +import com.sw.dualscreen.adapter.FoodCollectionAdapter +import com.sw.dualscreen.adapter.SearchFoodAdapter +import com.sw.dualscreen.databinding.FragmentCollectBinding +import com.sw.dualscreen.databinding.LayoutCameraPreviewBinding +import com.sw.dualscreen.ext.clickWithDebounce +import com.sw.dualscreen.ext.dp +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.utils.BitmapSaver +import com.sw.dualscreen.utils.CameraUtils +import com.sw.dualscreen.utils.Debouncer +import com.sw.dualscreen.utils.ImageUtil +import com.sw.plate.utils.ToastUtils +import io.objectbox.Box +import io.objectbox.kotlin.boxFor +import timber.log.Timber +import kotlin.getValue + +class CollectFragment : BaseFragment() { + + companion object { + const val MAX_COUNT = 5 + } + private var selectedFoodId: String? = "" + private var selectedFoodName: String? = "" + + private var box: Box? = null + private val foodCollectionList = mutableListOf().apply { + repeat(MAX_COUNT) { + add(FoodCollectionBean(isShowCamera = true)) + } + } + + private val searchFoodList = mutableListOf() + private var settingActivity: SettingActivity?=null + private var checkedItem: FoodInfo? = null + private val searchFoodAdapter by lazy { + SearchFoodAdapter(searchFoodList).apply { + setOnItemClickListener { adapter, view, position -> + checkedItem = searchFoodList[position] + selectedFoodId = checkedItem!!.id + val isChecked = checkedItem!!.isChecked + searchFoodList[position].isChecked = isChecked.not() + notifyItemChanged(position) + } + } + } + private val debouncer = Debouncer(2000) + private lateinit var previewView: PreviewView + private val cameraUtils: CameraUtils by lazy { + CameraUtils(requireActivity()) + } + + private val collectionAdapter: FoodCollectionAdapter by lazy { + FoodCollectionAdapter(foodCollectionList).apply { + addOnItemChildClickListener(R.id.ivDelete) { _, _, position -> + foodCollectionList[position].let { + it.bitmap = null + it.isShowCamera = true + it.isFinish = false + } + notifyItemChanged(position) + } + } + } + override fun inflateViewBinding(): FragmentCollectBinding { + return FragmentCollectBinding.inflate(LayoutInflater.from(context)) + } + + + private val cameraCallback: (Uri) -> Unit = { uri -> + val index = foodCollectionList.indexOfFirst { it.bitmap == null } + if (index == -1) { + ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") + rerurn@cameraCallback + } + ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap -> +// val cropBitmap = BitmapCropper.cropCenter( +// original = bitmap, +// targetWidth = 1300, targetHeight = 900, +// //offsetX = 30, offsetY = 100 +// ) + val file = BitmapSaver.saveToAppFilesDir( + bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg" + ) + Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}") + + foodCollectionList[index].let { + it.bitmap = bitmap + it.isShowCamera = false + it.imageUri = file?.toUri() + } + collectionAdapter.notifyItemChanged(index) + } + } + + @SuppressLint("NotifyDataSetChanged") + private fun takePhoto() { + val count = foodCollectionList.count { it.bitmap != null } + if (count >= MAX_COUNT) { + ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") + return + } + cameraUtils.takePhoto(cameraCallback) + } + + override fun initialize() { + settingActivity = activity as SettingActivity + cameraUtils.initCamera() + val previewBinding = + LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview) + previewView = previewBinding.previewView.also { + it.updateLayoutParams { + width = 456.dp + height = 342.dp + } + } + cameraUtils.setPreviewController(previewView) + + binding.rvFoodList.let { + it.layoutManager = GridLayoutManager(requireActivity(), 3, GridLayoutManager.VERTICAL, false) + it.adapter = collectionAdapter + } + + binding.btnFoodSearch.setOnClickListener { + searchInfo() + } + + binding.btnSave.setOnClickListener { + if (selectedFoodName.isNullOrBlank()) { + Toast.makeText(requireActivity(), "请选择菜品名称", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + if (foodCollectionList.size <= 1) { + Toast.makeText(requireActivity(), "请拍摄菜品照片", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + vectorThread() + } + + binding.editFoodName.setOnEditorActionListener { v, actionId, event -> + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + searchInfo() + val imm = + v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(v.windowToken, 0) + true + } else { + false + } + } + + binding.btnCollectedFood.setOnClickListener { + startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java)) + } + binding.btnTakePhoto.clickWithDebounce { + val count = foodCollectionList.count { it.bitmap != null } + if (count >= MAX_COUNT) { + ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") + return@clickWithDebounce + } + takePhoto() + } + binding.btnClearData.setOnClickListener { clearData() } + binding.rvSearchFood.let { + it.layoutManager = GridLayoutManager(context, 2) + it.adapter = searchFoodAdapter + } + } + + private fun vectorThread() { + settingActivity?.showWaitingDialog("加载中……") + Thread { + foodCollectionList + .filter { it.bitmap != null } + .forEachIndexed { index, it -> + image2VectorTask(it, index) + } + activity?.runOnUiThread { + binding.root.postDelayed({ + settingActivity?.hideWaitingDialog() + }, 1000) + } + }.start() + } + + private fun initBox() { + if (box == null) { + box = ObjectBox.boxStore.boxFor(Food::class) + } + } + + private fun image2VectorTask(item: FoodCollectionBean, position: Int) { + initBox() + val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!) + +// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector) +// Timber.tag("mzf1").e(base64Str) +//// viewModel.postImageData( +//// context, +//// foodId = selectedFoodId.toString(), +//// foodName = selectedFoodName.toString(), +//// foodVector = base64Str, +//// uri = item.imageUri!! +//// ) + box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector)) + foodCollectionList[position].let { + it.imageVector = imageVector + it.isFinish = true + } + + activity?.runOnUiThread { + collectionAdapter.notifyItemChanged(position) + } + } + + + @SuppressLint("NotifyDataSetChanged") + private fun searchInfo() { + debouncer.debounce { + settingActivity?.searchByFoodName(binding.editFoodName.text.toString()) { + searchFoodList.clear() + searchFoodList.addAll(it) + searchFoodAdapter.notifyDataSetChanged() + } + } + } + + 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("") +// foodList.clear() +// foodAdapter.updateData(mutableListOf()) +// foodAdapter.notifyDataSetChanged() + //loadEmptyView() + } + + override fun onResume() { + super.onResume() + cameraUtils.bind() + binding.llCameraFlag.run { + visibility = View.VISIBLE + postDelayed({ + visibility = View.GONE + }, 3000) + } + } + + override fun onPause() { + super.onPause() + cameraUtils.unbind() + binding.llCameraFlag.visibility = View.VISIBLE + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/FacePayFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/FacePayFragment.kt new file mode 100644 index 0000000..f89df12 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/FacePayFragment.kt @@ -0,0 +1,19 @@ +package com.sw.dualscreen.activity.fragment + +import com.sw.dualscreen.activity.PayActivity +import com.sw.dualscreen.databinding.FragmentFacePayBinding + +class FacePayFragment : BaseFragment() { + + override fun inflateViewBinding(): FragmentFacePayBinding { + return FragmentFacePayBinding.inflate(layoutInflater) + } + + private var payActivity: PayActivity? = null + override fun initialize() { + payActivity = activity as PayActivity + binding.tvFaceState.setOnClickListener { + payActivity?.showPayResult() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/NumberPayFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/NumberPayFragment.kt new file mode 100644 index 0000000..a8ab754 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/NumberPayFragment.kt @@ -0,0 +1,15 @@ +package com.sw.dualscreen.activity.fragment + +import com.sw.dualscreen.databinding.FragmentNumberPayBinding +import com.sw.dualscreen.ext.hideKeyboard + +class NumberPayFragment: BaseFragment() { + + override fun inflateViewBinding(): FragmentNumberPayBinding { + return FragmentNumberPayBinding.inflate(layoutInflater) + } + + override fun initialize() { + binding.root.hideKeyboard() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/PayResultFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/PayResultFragment.kt new file mode 100644 index 0000000..9cdb82b --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/PayResultFragment.kt @@ -0,0 +1,28 @@ +package com.sw.dualscreen.activity.fragment + +import com.sw.dualscreen.activity.PayActivity +import com.sw.dualscreen.databinding.FragmentPayResultBinding + +class PayResultFragment: BaseFragment() { + + override fun inflateViewBinding(): FragmentPayResultBinding { + return FragmentPayResultBinding.inflate(layoutInflater) + } + + + private var payActivity: PayActivity? = null + override fun initialize() { + payActivity = activity as PayActivity + binding.btnBack.setOnClickListener { + payActivity?.showFacePay() + } + } + + override fun onHiddenChanged(hidden: Boolean) { + super.onHiddenChanged(hidden) + //显示时重新查询接口 + if (hidden.not()) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/activity/fragment/QrCodePayFragment.kt b/app/src/main/java/com/sw/dualscreen/activity/fragment/QrCodePayFragment.kt new file mode 100644 index 0000000..f19b823 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/activity/fragment/QrCodePayFragment.kt @@ -0,0 +1,29 @@ +package com.sw.dualscreen.activity.fragment + +import android.text.Spanned +import android.text.SpannedString +import android.text.style.AbsoluteSizeSpan +import androidx.core.text.buildSpannedString +import com.sw.dualscreen.R +import com.sw.dualscreen.databinding.FragmentQrcodePayBinding + +class QrCodePayFragment: BaseFragment() { + + override fun inflateViewBinding(): FragmentQrcodePayBinding { + return FragmentQrcodePayBinding.inflate(layoutInflater) + } + + override fun initialize() { + binding.tvRealAmount.text = getAmountText("36.8") + binding.ivPayQrCode.setImageResource(R.drawable.ic_qrcode) + binding.tvPayResult.text = "待支付(60s)..." + } + + private fun getAmountText(amount:String): SpannedString { + return buildSpannedString { + append("¥", AbsoluteSizeSpan(36, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + append(amount, AbsoluteSizeSpan(60, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodAdapter.kt index c1471ef..fe24e3b 100644 --- a/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodAdapter.kt +++ b/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodAdapter.kt @@ -1,34 +1,34 @@ -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.CollectedFoodBean -import com.sw.dualscreen.objbox.FoodCollectionBean - -class CollectedFoodAdapter (var list: MutableList) : - BaseQuickAdapter(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: CollectedFoodBean?) { - holder.binding.tvFoodName.text = item?.foodName - holder.binding.divider.run { - visibility = if (position == list.size - 1) View.GONE else View.VISIBLE - } - } - -} \ No newline at end of file +//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.CollectedFoodBean +//import com.sw.dualscreen.objbox.FoodCollectionBean +// +//class CollectedFoodAdapter (var list: MutableList) : +// BaseQuickAdapter(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: CollectedFoodBean?) { +// holder.binding.tvFoodName.text = item?.foodName +// holder.binding.divider.run { +// visibility = if (position == list.size - 1) View.GONE else View.VISIBLE +// } +// } +// +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodNewAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodNewAdapter.kt new file mode 100644 index 0000000..17901ab --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/adapter/CollectedFoodNewAdapter.kt @@ -0,0 +1,27 @@ +package com.sw.dualscreen.adapter + +import android.content.Context +import android.view.LayoutInflater +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.objbox.CollectedFoodBean + +class CollectedFoodNewAdapter(var list: MutableList) : + BaseQuickAdapter(list) { + + inner class VH(var binding: ListItemCollectedFoodBinding) : QuickViewHolder(binding.root) + + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val inflater = LayoutInflater.from(context) + val binding = ListItemCollectedFoodBinding.inflate(inflater, parent, false) + return VH(binding) + } + + override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodBean?) { + holder.binding.tvFoodName.text = item?.foodName + holder.binding.tvCollectedNum.text = "已采集153" + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt index 306112c..ea86512 100644 --- a/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt +++ b/app/src/main/java/com/sw/dualscreen/adapter/FoodCollectionAdapter.kt @@ -9,7 +9,9 @@ import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.viewholder.QuickViewHolder import com.sw.dualscreen.R import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding +import com.sw.dualscreen.ext.dp import com.sw.dualscreen.objbox.FoodCollectionBean +import com.sw.dualscreen.utils.GlideUtils class FoodCollectionAdapter (var list: MutableList) : BaseQuickAdapter(list) { @@ -30,11 +32,20 @@ class FoodCollectionAdapter (var list: MutableList) : binding.imageView.run { if (it.isShowCamera) { scaleType = ImageView.ScaleType.CENTER - setImageResource(R.drawable.ic_camera256) + setImageResource(R.drawable.ic_camera_default) } else { - scaleType = ImageView.ScaleType.FIT_CENTER + //scaleType = ImageView.ScaleType.FIT_CENTER + scaleType = ImageView.ScaleType.CENTER_CROP //setImageURI(it.imageUri) - setImageBitmap(it.bitmap) + //setImageBitmap(it.bitmap) + it.bitmap?.let { bitmap -> + GlideUtils.loadRoundCornerWitBitmap( + context, + url = bitmap, + imageView = this, + radius = 8.dp + ) + } } } } diff --git a/app/src/main/java/com/sw/dualscreen/adapter/SearchFoodAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/SearchFoodAdapter.kt new file mode 100644 index 0000000..f2f0078 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/adapter/SearchFoodAdapter.kt @@ -0,0 +1,35 @@ +package com.sw.dualscreen.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import com.chad.library.adapter4.BaseQuickAdapter +import com.chad.library.adapter4.viewholder.QuickViewHolder +import com.sw.dualscreen.databinding.ListItemSearchFoodBinding +import com.sw.dualscreen.ext.format2String +import com.sw.dualscreen.model.response.FoodInfo + +class SearchFoodAdapter(var list: MutableList) : + BaseQuickAdapter(list) { + + inner class VH(var binding: ListItemSearchFoodBinding) : QuickViewHolder(binding.root) + + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val inflater = LayoutInflater.from(context) + val binding = ListItemSearchFoodBinding.inflate(inflater, parent, false) + return VH(binding) + } + + override fun onBindViewHolder(holder: VH, position: Int, item: FoodInfo?) { + holder.binding.tvFoodName.run { + if (item!!.score == 0) { + text = item.foodName + } else { + val score = (item.score / 100.0).format2String(2) + text = "${item.foodName}\n${score}%" + } + isChecked = item.isChecked + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/ext/CommonExt.kt b/app/src/main/java/com/sw/dualscreen/ext/CommonExt.kt index 4725fe8..d3529c7 100644 --- a/app/src/main/java/com/sw/dualscreen/ext/CommonExt.kt +++ b/app/src/main/java/com/sw/dualscreen/ext/CommonExt.kt @@ -120,3 +120,15 @@ fun View.clickWithDebounce(delay: Long = 500, action: () -> Unit) { } } } + +fun View.visible() { + visibility = View.VISIBLE +} + +fun View.invisible() { + visibility = View.INVISIBLE +} + +fun View.gone() { + visibility = View.GONE +} diff --git a/app/src/main/java/com/sw/dualscreen/model/response/FoodInfo.kt b/app/src/main/java/com/sw/dualscreen/model/response/FoodInfo.kt index 7b584cc..0f1fc7a 100644 --- a/app/src/main/java/com/sw/dualscreen/model/response/FoodInfo.kt +++ b/app/src/main/java/com/sw/dualscreen/model/response/FoodInfo.kt @@ -39,7 +39,8 @@ data class FoodInfo( val stFoodInfoSetting: StFoodInfoSetting? = StFoodInfoSetting(), @SerializedName("stFoodInfoSpecificationList") val stFoodInfoSpecificationList: List? = listOf(), - var score: Int = 0 + var score: Int = 0, + var isChecked: Boolean = false ) : Parcelable { @Parcelize data class FoodTypeAndRealIntakeVo( diff --git a/app/src/main/java/com/sw/dualscreen/sdk/SensorScaleUtils.kt b/app/src/main/java/com/sw/dualscreen/sdk/SensorScaleUtils.kt index 04402f0..6ad5388 100644 --- a/app/src/main/java/com/sw/dualscreen/sdk/SensorScaleUtils.kt +++ b/app/src/main/java/com/sw/dualscreen/sdk/SensorScaleUtils.kt @@ -4,8 +4,10 @@ import com.sw.plate.utils.ToastUtils import com.wabon.wbintelligenthardwaresdk.api.SensorScale import com.wabon.wbintelligenthardwaresdk.api.SensorScale.OnScaleResult import timber.log.Timber +import kotlin.math.roundToInt typealias Callback = (Double) -> Unit +typealias WeightCallback = (Double) -> Unit private const val TAG = "SensorScaleUtils" @@ -41,6 +43,10 @@ object SensorScaleUtils { lastWeight = value callback?.invoke(value) } + + weightCallbackList.forEach { + it.invoke(value) + } } /** @@ -60,7 +66,7 @@ object SensorScaleUtils { * 开启称重 * @param autoScale 是否开启自动读取 */ - fun startScale(autoScale: Boolean = true, callback: Callback?) { + fun startScale(autoScale: Boolean = true, callback: Callback? = null) { Timber.d("startScale isOpened = $isOpened") if (isOpened) { startContinuousRead(callback = callback) @@ -112,6 +118,13 @@ object SensorScaleUtils { mSensorScale?.readWeight() } + private var weightCallbackList: MutableList = mutableListOf() + fun addWeightListener(weightCallback: WeightCallback) { + if (weightCallbackList.contains(weightCallback).not()) { + weightCallbackList.add(weightCallback) + } + } + /** * 零位标定 */ diff --git a/app/src/main/java/com/sw/dualscreen/utils/ActivityManager.kt b/app/src/main/java/com/sw/dualscreen/utils/ActivityManager.kt new file mode 100644 index 0000000..0937ba8 --- /dev/null +++ b/app/src/main/java/com/sw/dualscreen/utils/ActivityManager.kt @@ -0,0 +1,57 @@ +package com.sw.dualscreen.utils + +import android.app.Activity +import android.os.Process +import java.util.Stack + +object ActivityManager { + + private val activityStack = Stack() + + // 添加Activity到栈 + fun addActivity(activity: Activity) { + activityStack.add(activity) + } + + // 移除指定Activity + fun removeActivity(activity: Activity) { + activityStack.remove(activity) + } + + // 获取当前Activity + fun currentActivity(): Activity? { + return if (activityStack.isEmpty()) null else activityStack.lastElement() + } + + // 结束指定Activity + fun finishActivity(activity: Activity) { + if (!activity.isFinishing) { + activity.finish() + } + } + + // 结束所有Activity + fun finishAllActivity() { + activityStack.forEach { + if (!it.isFinishing) { + it.finish() + } + } + activityStack.clear() + } + + // 退出应用程序 + fun exitApp() { + finishAllActivity() + Process.killProcess(Process.myPid()) + } + + fun getActivityStack(): Stack{ + return activityStack + } + + fun isEmpty() : Boolean { + return activityStack.isEmpty() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/dualscreen/utils/GlideUtils.kt b/app/src/main/java/com/sw/dualscreen/utils/GlideUtils.kt index a0aa45f..3581e75 100644 --- a/app/src/main/java/com/sw/dualscreen/utils/GlideUtils.kt +++ b/app/src/main/java/com/sw/dualscreen/utils/GlideUtils.kt @@ -104,6 +104,21 @@ object GlideUtils { .into(imageView) } + fun loadRoundCornerWitBitmap( + context: Context, + url: Bitmap, + imageView: ImageView, + radius: Int, + @DrawableRes placeholderResId: Int = 0, + @DrawableRes errorResId: Int = 0 + ) { + val requestBuilder = Glide.with(context) + .load(url) + .apply(RequestOptions.bitmapTransform(RoundedCorners(radius))) + + applyPlaceholder(requestBuilder, placeholderResId, errorResId) + .into(imageView) + } /** * 加载图片并获取Bitmap * @param context 上下文 diff --git a/app/src/main/java/com/sw/dualscreen/viewmodel/UserViewModel.kt b/app/src/main/java/com/sw/dualscreen/viewmodel/UserViewModel.kt index abf66d1..724eb91 100644 --- a/app/src/main/java/com/sw/dualscreen/viewmodel/UserViewModel.kt +++ b/app/src/main/java/com/sw/dualscreen/viewmodel/UserViewModel.kt @@ -158,12 +158,14 @@ class UserViewModel : BaseViewModel() { /** * 搜索食物 */ - fun searchByFoodName(foodName: String) { + fun searchByFoodName(foodName: String, action: (List) -> Unit = {}) { Timber.d("searchByFoodName foodName = $foodName") launchWithLoading { val response = repository.getRestInfoFoodsByType(foodName = foodName) if (parseResponse(response)) { - _searchFoodInfoList.value = response.result ?: emptyList() + val list = response.result ?: emptyList() + action(list) + _searchFoodInfoList.value = list } } } diff --git a/app/src/main/res/color/color_search_food.xml b/app/src/main/res/color/color_search_food.xml new file mode 100644 index 0000000..e6c6fd0 --- /dev/null +++ b/app/src/main/res/color/color_search_food.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/setting_radio.xml b/app/src/main/res/color/setting_radio.xml new file mode 100644 index 0000000..e6c6fd0 --- /dev/null +++ b/app/src/main/res/color/setting_radio.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/face_mask.png b/app/src/main/res/drawable-xxhdpi/face_mask.png new file mode 100644 index 0000000..6cb6f06 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/face_mask.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png new file mode 100644 index 0000000..cb7df73 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_back2.png b/app/src/main/res/drawable-xxhdpi/ic_back2.png new file mode 100644 index 0000000..d1644c1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_back2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_camera_default.png b/app/src/main/res/drawable-xxhdpi/ic_camera_default.png new file mode 100644 index 0000000..c63a559 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_camera_default.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_close2.png b/app/src/main/res/drawable-xxhdpi/ic_close2.png new file mode 100644 index 0000000..a6d77e4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_close2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_del2.png b/app/src/main/res/drawable-xxhdpi/ic_del2.png new file mode 100644 index 0000000..8456dff Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_del2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_delete_red.png b/app/src/main/res/drawable-xxhdpi/ic_delete_red.png index ff00640..8456dff 100644 Binary files a/app/src/main/res/drawable-xxhdpi/ic_delete_red.png and b/app/src/main/res/drawable-xxhdpi/ic_delete_red.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_pay_success.png b/app/src/main/res/drawable-xxhdpi/ic_pay_success.png new file mode 100644 index 0000000..f14edb9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pay_success.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_qrcode.png b/app/src/main/res/drawable-xxhdpi/ic_qrcode.png new file mode 100644 index 0000000..95920a3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_qrcode.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_retake_photo.png b/app/src/main/res/drawable-xxhdpi/ic_retake_photo.png new file mode 100644 index 0000000..62e6b7e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_retake_photo.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_search2.png b/app/src/main/res/drawable-xxhdpi/ic_search2.png new file mode 100644 index 0000000..17e266d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_search2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_setting.png b/app/src/main/res/drawable-xxhdpi/ic_setting.png new file mode 100644 index 0000000..9936850 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_setting.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_setting_checked.png b/app/src/main/res/drawable-xxhdpi/ic_setting_checked.png new file mode 100644 index 0000000..b9cebb2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_setting_checked.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_take_photo.png b/app/src/main/res/drawable-xxhdpi/ic_take_photo.png new file mode 100644 index 0000000..952051d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_take_photo.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_vip_level.png b/app/src/main/res/drawable-xxhdpi/ic_vip_level.png new file mode 100644 index 0000000..f18bc68 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_vip_level.png differ diff --git a/app/src/main/res/drawable/bg_border_red.xml b/app/src/main/res/drawable/bg_border_red.xml new file mode 100644 index 0000000..751bec1 --- /dev/null +++ b/app/src/main/res/drawable/bg_border_red.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_clear.xml b/app/src/main/res/drawable/bg_btn_clear.xml new file mode 100644 index 0000000..86ea423 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_clear.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_confirm.xml b/app/src/main/res/drawable/bg_btn_confirm.xml new file mode 100644 index 0000000..4b76298 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_confirm.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_save.xml b/app/src/main/res/drawable/bg_btn_save.xml new file mode 100644 index 0000000..d0c6549 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_save.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_save2.xml b/app/src/main/res/drawable/bg_btn_save2.xml new file mode 100644 index 0000000..771f6c6 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_save2.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_gray2.xml b/app/src/main/res/drawable/bg_gray2.xml new file mode 100644 index 0000000..d499b62 --- /dev/null +++ b/app/src/main/res/drawable/bg_gray2.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_pay_content.xml b/app/src/main/res/drawable/bg_pay_content.xml new file mode 100644 index 0000000..769a644 --- /dev/null +++ b/app/src/main/res/drawable/bg_pay_content.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_search_food.xml b/app/src/main/res/drawable/bg_search_food.xml new file mode 100644 index 0000000..e71abfc --- /dev/null +++ b/app/src/main/res/drawable/bg_search_food.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/line_shape.xml b/app/src/main/res/drawable/line_shape.xml new file mode 100644 index 0000000..7a0315c --- /dev/null +++ b/app/src/main/res/drawable/line_shape.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_border.xml b/app/src/main/res/drawable/setting_border.xml new file mode 100644 index 0000000..b744f3a --- /dev/null +++ b/app/src/main/res/drawable/setting_border.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_border_gray.xml b/app/src/main/res/drawable/setting_border_gray.xml new file mode 100644 index 0000000..4b57809 --- /dev/null +++ b/app/src/main/res/drawable/setting_border_gray.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_border_gray2.xml b/app/src/main/res/drawable/setting_border_gray2.xml new file mode 100644 index 0000000..da566f9 --- /dev/null +++ b/app/src/main/res/drawable/setting_border_gray2.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_border_gray3.xml b/app/src/main/res/drawable/setting_border_gray3.xml new file mode 100644 index 0000000..49ae121 --- /dev/null +++ b/app/src/main/res/drawable/setting_border_gray3.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_border_gray4.xml b/app/src/main/res/drawable/setting_border_gray4.xml new file mode 100644 index 0000000..4b57809 --- /dev/null +++ b/app/src/main/res/drawable/setting_border_gray4.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/setting_check_selector.xml b/app/src/main/res/drawable/setting_check_selector.xml new file mode 100644 index 0000000..44bc631 --- /dev/null +++ b/app/src/main/res/drawable/setting_check_selector.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/vip_level.xml b/app/src/main/res/drawable/vip_level.xml new file mode 100644 index 0000000..ac99d9e --- /dev/null +++ b/app/src/main/res/drawable/vip_level.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_collected_food.xml b/app/src/main/res/layout/activity_collected_food.xml new file mode 100644 index 0000000..bcdb30d --- /dev/null +++ b/app/src/main/res/layout/activity_collected_food.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index feaaddf..0f7dc33 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,7 +4,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@mipmap/bg" + android:background="#FFE7EFF8" android:gravity="center_horizontal" android:orientation="vertical" tools:context=".activity.MainActivity"> @@ -12,25 +12,44 @@ + android:layout_height="150dp"> - + android:layout_gravity="center_vertical" + android:layout_marginStart="32dp" + android:textColor="#ff0a1428" + android:textSize="30sp" + android:textStyle="bold" + tools:text="2025年11月11日 周二" /> - - + + + + + + + + + + + + + + + + + @@ -91,7 +110,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="未识别出菜品,请重试或手动搜索" - android:textColor="@color/white" + android:textColor="#FFFF3232" android:textSize="24sp" /> @@ -111,11 +130,32 @@ android:id="@+id/tv_to_search" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="90dp" - android:layout_marginBottom="90dp" + android:layout_marginTop="40dp" + android:layout_marginBottom="60dp" android:padding="10dp" android:text="以上都不是,手动搜索" - android:textColor="#ffff9900" + android:textStyle="bold" + android:textColor="#FFFF3232" android:textSize="36sp" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pay.xml b/app/src/main/res/layout/activity_pay.xml index d1cfb38..75eba32 100644 --- a/app/src/main/res/layout/activity_pay.xml +++ b/app/src/main/res/layout/activity_pay.xml @@ -1,21 +1,43 @@ + android:orientation="vertical" + tools:ignore="HardcodedText"> - + + + + + android:layout_marginHorizontal="32dp" + android:layout_weight="1" + android:background="@drawable/bg_pay_content" /> diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml new file mode 100644 index 0000000..baa4e8e --- /dev/null +++ b/app/src/main/res/layout/activity_setting.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_business.xml b/app/src/main/res/layout/fragment_business.xml new file mode 100644 index 0000000..47b06a5 --- /dev/null +++ b/app/src/main/res/layout/fragment_business.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_cash_pay.xml b/app/src/main/res/layout/fragment_cash_pay.xml new file mode 100644 index 0000000..4f66683 --- /dev/null +++ b/app/src/main/res/layout/fragment_cash_pay.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_collect.xml b/app/src/main/res/layout/fragment_collect.xml new file mode 100644 index 0000000..22aa04f --- /dev/null +++ b/app/src/main/res/layout/fragment_collect.xml @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_face_pay.xml b/app/src/main/res/layout/fragment_face_pay.xml new file mode 100644 index 0000000..d7e4a67 --- /dev/null +++ b/app/src/main/res/layout/fragment_face_pay.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_number_pay.xml b/app/src/main/res/layout/fragment_number_pay.xml new file mode 100644 index 0000000..e041d77 --- /dev/null +++ b/app/src/main/res/layout/fragment_number_pay.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_pay_result.xml b/app/src/main/res/layout/fragment_pay_result.xml new file mode 100644 index 0000000..f13b590 --- /dev/null +++ b/app/src/main/res/layout/fragment_pay_result.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_qrcode_pay.xml b/app/src/main/res/layout/fragment_qrcode_pay.xml new file mode 100644 index 0000000..fe6c468 --- /dev/null +++ b/app/src/main/res/layout/fragment_qrcode_pay.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_title_bar.xml b/app/src/main/res/layout/layout_title_bar.xml new file mode 100644 index 0000000..1ff98b7 --- /dev/null +++ b/app/src/main/res/layout/layout_title_bar.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_collected_food.xml b/app/src/main/res/layout/list_item_collected_food.xml new file mode 100644 index 0000000..139245e --- /dev/null +++ b/app/src/main/res/layout/list_item_collected_food.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_food_collection.xml b/app/src/main/res/layout/list_item_food_collection.xml index b4462ab..1f53c86 100644 --- a/app/src/main/res/layout/list_item_food_collection.xml +++ b/app/src/main/res/layout/list_item_food_collection.xml @@ -1,31 +1,30 @@ + android:layout_width="212dp" + android:layout_height="159dp" + android:layout_margin="16dp" + android:background="@drawable/bg_gray2"> + tools:src="@drawable/ic_camera_default" /> diff --git a/app/src/main/res/layout/list_item_search_food.xml b/app/src/main/res/layout/list_item_search_food.xml new file mode 100644 index 0000000..72d9bfb --- /dev/null +++ b/app/src/main/res/layout/list_item_search_food.xml @@ -0,0 +1,18 @@ + + \ No newline at end of file