package com.sw.dualscreen.ext import android.content.Context import android.content.res.Resources import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.ImageFormat import android.graphics.Rect import android.graphics.YuvImage import android.util.TypedValue import android.view.View import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.EditText import androidx.annotation.Dimension import androidx.camera.core.ImageProxy import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.io.ByteArrayOutputStream import java.math.BigDecimal import java.math.RoundingMode /** * 将 Int 值转换为 dp 值 */ val Int.dp: Int @Dimension(unit = Dimension.DP) get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics ).toInt() /** * 将 Float 值转换为 dp 值 */ val Float.dp: Float @Dimension(unit = Dimension.DP) get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics ) /** * 将 Int 值转换为 sp 值 */ val Int.sp: Float @Dimension(unit = Dimension.SP) get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Resources.getSystem().displayMetrics ) /** * 将 Float 值转换为 sp 值 */ val Float.sp: Float @Dimension(unit = Dimension.SP) get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics ) fun Double.roundedDecimalPlace(num: Int = 2): Double { return BigDecimal(this).setScale(num, RoundingMode.HALF_UP).toDouble() } fun Double?.format2String(): String = this.format2String(1) fun Double?.format2String(num:Int): String = "%.${num}f".format(this?:0.0) // 添加扩展函数 fun ImageProxy.toSafeBitmap(): Bitmap { val yBuffer = planes[0].buffer // Y val uBuffer = planes[1].buffer // U val vBuffer = planes[2].buffer // V val ySize = yBuffer.remaining() val uSize = uBuffer.remaining() val vSize = vBuffer.remaining() val nv21 = ByteArray(ySize + uSize + vSize) // Y yBuffer.get(nv21, 0, ySize) // U/V vBuffer.get(nv21, ySize, vSize) uBuffer.get(nv21, ySize + vSize, uSize) val yuvImage = YuvImage(nv21, ImageFormat.NV21, this.width, this.height, null) val out = ByteArrayOutputStream() yuvImage.compressToJpeg(Rect(0, 0, this.width, this.height), 100, out) val imageBytes = out.toByteArray() return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) } fun View.hideKeyboard() { val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(this.windowToken, 0) this.clearFocus() // 清除焦点避免键盘再次弹出 } 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() // } // } //} /** * 极简版防重复点击扩展函数 * @param delay 防抖时间(默认300ms) * @param action 点击执行逻辑 */ fun View.clickWithDebounce(delay: Long = 300, action: () -> Unit) { setOnClickListener { // 用View的tag存储是否可点击的状态(默认可点击) if (tag as? Boolean ?: true) { tag = false // 标记为不可点击 action() // 立即执行点击逻辑 // 启动协程,延迟后恢复可点击状态 CoroutineScope(Dispatchers.Main).launch { delay(delay) tag = true // 恢复可点击 } } } } fun View.visible() { visibility = View.VISIBLE } fun View.invisible() { visibility = View.INVISIBLE } fun View.gone() { visibility = View.GONE }