162 lines
4.4 KiB
Kotlin
162 lines
4.4 KiB
Kotlin
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
|
||
}
|