代码提交

This commit is contained in:
2025-08-11 18:32:04 +08:00
parent 317ac05278
commit 3b4ba599bf
188 changed files with 9770 additions and 34 deletions
@@ -0,0 +1,52 @@
package com.shuwei.dish.match.utils
import android.app.Activity
import java.util.Stack
object ActivityManager {
private val activityStack = Stack<Activity>()
// 添加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()
android.os.Process.killProcess(android.os.Process.myPid())
}
fun getActivityStack(): Stack<Activity>{
return activityStack
}
}
@@ -0,0 +1,28 @@
package com.shuwei.dish.match.utils
import android.util.SparseIntArray
object DataUtil {
fun getWeighAddressArray(): SparseIntArray {
return SparseIntArray().apply {
put(0, 12)
put(1, 13)
put(2, 14)
put(3, 9)
put(4, 10)
put(5, 11)
put(6, 6)
put(7, 7)
put(8, 8)
put(9, 5)
put(12, 4)
put(10, 3)
put(11, 3)
put(13, 3)
put(14, 3)
}
}
}
@@ -0,0 +1,32 @@
package com.shuwei.dish.match.utils
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Date
object DateTimeUtil {
const val YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"
fun formatDateTime(dateTime: LocalDateTime, pattern: String = YYYY_MM_DD_HH_MM_SS): String {
val formatter = DateTimeFormatter.ofPattern(pattern)
return dateTime.format(formatter)
}
fun convert(dateStr: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date {
val formatter = DateTimeFormatter.ofPattern(pattern)
val ldt = LocalDateTime.parse(dateStr, formatter)
val zdt = ldt.atZone(ZoneId.systemDefault())
return Date.from(zdt.toInstant())
}
fun main() {
val now = LocalDateTime.now()
println("默认格式: ${formatDateTime(now)}")
println("自定义格式: ${formatDateTime(now, "yyyy年MM月dd日 HH时mm分ss秒")}")
}
}
@@ -0,0 +1,26 @@
package com.shuwei.dish.match.utils
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
class DecimalAdapter : TypeAdapter<Number>() {
override fun write(out: JsonWriter, value: Number) {
// out.value(value.toString()) // 强制以字符串形式写入
out.value("$value") // 强制以字符串形式写入
}
override fun read(reader: JsonReader): Number {
return when (reader.peek()) {
JsonToken.NUMBER -> reader.nextDouble()
JsonToken.STRING -> reader.nextString().toDouble()
else -> 0.0
}
}
}
// 使用方式
//val gson = GsonBuilder()
// .registerTypeAdapter(Double::class.java, DecimalAdapter())
// .create()
@@ -0,0 +1,17 @@
package com.shuwei.dish.match.utils
import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager
object KeyboardUtil {
fun hideKeyboard(context: Context, view: View) {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
view.clearFocus() // 清除焦点避免键盘再次弹出
}
}
@@ -0,0 +1,11 @@
package com.shuwei.dish.match.utils
import android.util.Log
//object LogUtil {
//
// fun d(tag: String, msg: String) {
// Log.d(tag, msg)
// }
//
//}
@@ -0,0 +1,62 @@
package com.shuwei.dish.match.utils
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.adapter.DishPartAdapter
import com.shuwei.dish.match.adapter.DishShowAdapter
import com.shuwei.dish.match.adapter.SamplingAdapter
class SwipeCallback(
private val adapter: BaseQuickAdapter<*,*>,
private val callback: (position: Int) -> Unit = {}
) :
ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return false // 不允许拖动,只允许滑动删除
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.getBindingAdapterPosition()
callback(position)
}
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val position = viewHolder.getBindingAdapterPosition()
// 默认的拖动和滑动方向
val dragFlags = 0
// ItemTouchHelper.UP or ItemTouchHelper.DOWN
var swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
if (adapter is SamplingAdapter) {
if (!adapter.items[position].isCooking) {
swipeFlags = 0
}
} else if (adapter is DishShowAdapter) {
if (!adapter.items[position].isCooking) {
swipeFlags = 0
}
} else if (adapter is DishPartAdapter) {
if (!adapter.items[position].isNewDishType) {
swipeFlags = 0
}
}
// 根据viewHolder的逻辑判断是否允许滑动
val count = recyclerView.adapter?.itemCount ?:0
//BaseQuickAdapter中空布局使用的ViewHolder是这个import com.chad.library.adapter4.viewholder.StateLayoutVH
if (count == 1 && viewHolder !is QuickViewHolder) {
swipeFlags = 0 // 不允许滑动
}
return makeMovementFlags(dragFlags, swipeFlags)
}
}
@@ -0,0 +1,28 @@
package com.shuwei.dish.match.utils
import android.content.Context
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import android.widget.Toast
import com.shuwei.dish.match.R
object ToastUtil {
fun show(context: Context, message: String, duration:Int = Toast.LENGTH_SHORT) {
val inflater = LayoutInflater.from(context)
val layout: View = inflater.inflate(R.layout.custom_toast, null)
val textView = layout.findViewById<TextView>(R.id.tvMessage)
textView.text = message
val toast = Toast(context)
toast.view = layout // 设置自定义视图
toast.setGravity(Gravity.CENTER, 0, 0) // 调整位置居中显示
toast.setDuration(duration)
toast.show()
}
}
@@ -0,0 +1,148 @@
package com.shuwei.dish.match.utils
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.aithings.Weigher
import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.utils.ext.toast
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
object WeightUtil {
fun connect(initCallback: (connect: Boolean) -> Unit) {
Weigher.setListener(object : WeightListenerImpl() {
override fun onInit(connect: Boolean) {
initCallback(connect)
Log.d("WeightUtil", "connect=$connect")
}
override fun onZero() {
Log.d("WeightUtil", "zero ok")
}
override fun onTare() {
Log.d("WeightUtil", "去皮置零操作成功")
}
override fun onSetIdentify() {
Log.d("WeightUtil", "鉴别率设置操作成功")
}
override fun onGetWeight(address: Int, state: Int, weight: Int) {
runOnUiThread {
val stateStr = when (state) {
SensorScale.STATE_STABLE -> "稳定"
SensorScale.STATE_UNSTABLE -> "不稳定"
SensorScale.STATE_OVER_WEIGHT -> "量程溢出"
else -> ""
}
val result1 = String.format("$stateStr 重量:%s kg", weight / 1000f)
Log.d("WeightUtil", "ttlReturn, address:$address,$result1")
}
}
override fun onReadIdentify(rate: Int) {
Log.d("WeightUtil", "读取鉴别率成功:rate=$rate")
}
override fun onFail(errCode: Int) {
val str = when (errCode) {
Weigher.ERR_001 -> "电子称未初始化"
Weigher.ERR_002 -> "开机零位异常"
Weigher.ERR_003 -> "传感器故障"
Weigher.ERR_004 -> "鉴别率超出范围"
Weigher.ERR_PCB_NOT_SUPPORT -> "主板不支持, " + Build.MODEL
else -> ""
}
Log.d("WeightUtil", str)
}
override fun onFastFilter() {
Log.d("WeightUtil", "快速滤波设置成功")
}
override fun onReadParam() {
Log.d("WeightUtil", "prepare ok")
}
override fun onRangCal() {
Log.d("WeightUtil", "rang cal ok")
}
override fun onSetParam() {
Log.d("WeightUtil", "onSetParam")
}
})
}
private fun runOnUiThread(action: () -> Unit) {
Handler(Looper.getMainLooper()).post {
action()
}
}
fun addWeightListener(
zero: (() -> Unit) = {},
getWeight: ((address: Int, state: Int, weight: Int) -> Unit) = { _, _, _ -> }
) {
Weigher.setListener(object : WeightListenerImpl() {
override fun onZero() {
zero()
}
override fun onGetWeight(address: Int, state: Int, weight: Int) {
getWeight(address, state, weight)
}
})
}
}
open class WeightListenerImpl : Weigher.Listener {
override fun onInit(connect: Boolean) {
}
override fun onZero() {
}
override fun onTare() {
}
override fun onSetIdentify() {
}
override fun onGetWeight(address: Int, state: Int, weight: Int) {
}
override fun onReadIdentify(rate: Int) {
}
override fun onFail(errCode: Int) {
}
override fun onFastFilter() {
}
override fun onReadParam() {
}
override fun onRangCal() {
}
override fun onSetParam() {
}
}
@@ -0,0 +1,175 @@
package com.shuwei.dish.match.utils.ext
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Resources
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.Toast
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.shuwei.dish.match.utils.ToastUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
fun Context.toast(
message: String?,
duration: Int = Toast.LENGTH_SHORT,
) {
if (message.isNullOrBlank()) {
return
}
//Toast.makeText(this, message, duration).show()
ToastUtil.show(this, message, duration)
}
fun Fragment.toast(
message: String?,
duration: Int = 2000
) {
activity?.toast(message, duration)
}
//fun Fragment.toast(
// message: String?,
// duration: Int = 2000
//) {
// if (isAdded.not()) {
// return
// }
// CustomToast(
// activity = requireActivity(),
// message = message,
// duration = duration
// ).show()
//}
//
//public fun BaseActivity.toast(message: String?, duration: Int = 2000) {
// CustomToast(
// activity = this,
// message = message,
// duration = duration
// ).show()
//}
fun View.visible() {
visibility = View.VISIBLE
}
fun View.invisible() {
visibility = View.INVISIBLE
}
fun View.gone() {
visibility = View.GONE
}
inline fun <reified T : Activity> Context.startActivity(
bundle: Bundle? = null,
options: ActivityOptionsCompat? = null
) {
Intent(this, T::class.java).apply {
bundle?.let { putExtras(it) }
if (options != null && this@startActivity is Activity) {
startActivity(this, options.toBundle())
} else {
startActivity(this)
}
}
}
inline fun <reified T> Context.startActivity(
block: Intent.() -> Unit = {}
) {
Intent(this, T::class.java).apply {
block()
startActivity(this)
}
}
//inline fun <reified T : Activity> Context.startActivity(action:(bundle: Bundle)-> Unit) {
// Intent(this, T::class.java).apply {
// action(Bundle())
// startActivity(this)
// }
//}
inline fun <reified T> String.toType(gson: Gson? = null, typeToken: TypeToken<T>): T {
return (gson ?: Gson()).fromJson(this, typeToken.type)
}
inline fun <reified T> String.toObject(gson: Gson? = null): T {
return (gson ?: Gson()).fromJson(this, T::class.java)
}
fun Any?.toJsonString(gson: Gson? = null): String {
return (gson ?: Gson()).toJson(this) ?: ""
}
@SuppressLint("ApplySharedPref")
inline fun SharedPreferences.edit(
commit: Boolean = false,
action: SharedPreferences.Editor.() -> Unit
) {
val editor = edit()
action(editor)
if (commit) editor.commit() else editor.apply()
}
fun SharedPreferences.put(vararg pairs: Pair<String, Any>) {
edit {
pairs.forEach { (key, value) ->
when (value) {
is Int -> putInt(key, value)
is String -> putString(key, value)
is Boolean -> putBoolean(key, value)
is Float -> putFloat(key, value)
is Long -> putLong(key, value)
}
}
}
}
val Float.dp: Float
get() = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this,
Resources.getSystem().displayMetrics
)
val Int.dp: Int
get() = this.toFloat().dp.toInt()
fun EditText.addOnActionSearchListener(searchCallback: () -> Unit) {
setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// 处理搜索逻辑
searchCallback()
return@setOnEditorActionListener true // 阻止事件继续传递
}
return@setOnEditorActionListener false
}
}
fun View.clickWithDebounce(delay: Long = 500, action: () -> Unit) {
var job: Job? = null
setOnClickListener {
job?.cancel()
job = CoroutineScope(Dispatchers.Main).launch {
delay(delay)
action()
}
}
}
@@ -0,0 +1,25 @@
package com.shuwei.dish.match.utils.ext
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
inline fun buildSpannableString(builderAction: SpannableStringBuilder.() -> Unit): SpannableStringBuilder {
return SpannableStringBuilder().apply(builderAction)
}
fun SpannableStringBuilder.appendText(text: String, vararg spans: Any): SpannableStringBuilder {
val start = length
append(text)
spans.forEach { span ->
setSpan(span, start, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
}
return this
}
fun SpannableStringBuilder.withSpan(span: Any, block: SpannableStringBuilder.() -> Unit) {
val start = length
block()
setSpan(span, start, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
}