import android.app.Activity import android.content.Context import android.content.res.ColorStateList import android.content.res.Resources import android.graphics.Color import android.os.Build import android.os.Bundle import android.text.Editable import android.util.TypedValue import android.view.Gravity import android.view.View import android.view.WindowManager import android.widget.ImageView import androidx.appcompat.widget.AppCompatEditText import androidx.core.graphics.drawable.DrawableCompat import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.baselibrary.R import com.baselibrary.common.BaseApplication import com.baselibrary.utils.DefaultTextWatcher import com.baselibrary.utils.Internals.internalStartActivity import com.baselibrary.utils.format import com.baselibrary.utils.toLocalDateTime import com.blankj.utilcode.util.ActivityUtils import com.blankj.utilcode.util.AdaptScreenUtils import com.blankj.utilcode.util.ColorUtils import com.blankj.utilcode.util.LanguageUtils import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.PermissionUtils import com.blankj.utilcode.util.SPUtils import com.blankj.utilcode.util.ToastUtils import com.google.gson.Gson import com.gyf.immersionbar.ktx.hideStatusBar import com.gyf.immersionbar.ktx.immersionBar import com.luck.picture.lib.language.LanguageConfig import com.scwang.smartrefresh.layout.SmartRefreshLayout import com.scwang.smartrefresh.layout.footer.ClassicsFooter import com.scwang.smartrefresh.layout.header.ClassicsHeader import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody import java.io.File import java.time.LocalDate import java.util.Locale val displayWidth get() = Resources.getSystem().displayMetrics.widthPixels val displayHeight get() = Resources.getSystem().displayMetrics.heightPixels val Int.pt get() = toFloat().pt val Float.pt get() = AdaptScreenUtils.pt2Px(this) val Float.dp get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics ) val Int.dp get() = this.toFloat().dp val Int.dpi get() = this.toFloat().dp.toInt() val widthPixels by lazy { Resources.getSystem().displayMetrics.widthPixels } val Int.dpf get() = this * widthPixels / 375f val Float.sp get() = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics ) val Int.sp get() = this.toFloat().sp fun View.singleClick(onClickListener: View.OnClickListener?) { var lastClickTime = 0L setOnClickListener { val currentTimeMillis = System.currentTimeMillis() if (currentTimeMillis - lastClickTime > 600) { lastClickTime = currentTimeMillis onClickListener?.onClick(this) } } } inline fun <T> Flow<T>.launchAndCollectIn( owner: LifecycleOwner, minActiveState: Lifecycle.State = Lifecycle.State.STARTED, crossinline action: suspend CoroutineScope.(T) -> Unit ) = owner.lifecycleScope.launch { owner.repeatOnLifecycle(minActiveState) { collect { action(it) } } } fun Int.alpha(alpha: Float): Int { return ColorUtils.setAlphaComponent(this, alpha) } fun <T> T.toJsonString(): String { return Gson().toJson(this) } @Suppress("UNCHECKED_CAST") operator fun <T> Bundle?.get(key: String): T? = this?.get(key) as? T fun <T> Activity.intentExtras(name: String) = lazy<T?> { intent.extras[name] } fun <T> Activity.intentExtras(name: String, default: T) = lazy { intent.extras[name] ?: default } fun <T> Activity.safeIntentExtras(name: String) = lazy<T> { checkNotNull(intent.extras[name]) { "No intent value for key \"$name\"" } } inline fun <reified T : Activity> startActivity(vararg params: Pair<String, Any?>) = ActivityUtils.getTopActivity().startActivity<T>(*params) inline fun <reified T : Activity> Context.startActivity(vararg params: Pair<String, Any?>) = internalStartActivity(this, T::class.java, params) inline fun <reified T : Activity> Fragment.startActivity(vararg params: Pair<String, Any?>) = internalStartActivity(requireActivity(), T::class.java, params) fun Fragment.finish() { requireActivity().finish() } fun toast(text: String) { toastCenter(text) } /** * 系统内部提示 */ fun toastCenter(text: String?) { ToastUtils.make().setBgResource(R.drawable.toast_background_black).setDurationIsLong(true) .setTextColor(Color.WHITE).setGravity(Gravity.CENTER, -1, -1).show(text) } //修改图标颜色 fun ImageView.tintDrawable(color: String) { if (drawable == null) return val wrappedDrawable = DrawableCompat.wrap(drawable) DrawableCompat.setTintList(wrappedDrawable, ColorStateList.valueOf(Color.parseColor(color))) this.setImageDrawable(wrappedDrawable) } //修改图标颜色 fun ImageView.tintDrawable(color: Int) { if (drawable == null) return val wrappedDrawable = DrawableCompat.wrap(drawable) DrawableCompat.setTintList(wrappedDrawable, ColorStateList.valueOf(color)) this.setImageDrawable(wrappedDrawable) } /** * 生成一个颜色值更深的颜色 */ fun Int.darkenColor(alpha: Float = 0.95F): Int { val hsv = FloatArray(3) Color.colorToHSV(this, hsv) hsv[2] *= alpha // 将颜色的亮度值乘以alpha,生成更深的颜色 return Color.HSVToColor(hsv) } /** * 生成一个颜色值更浅的颜色 */ fun Int.lightColor(alpha: Float = 0.95F): Int { val hsv = FloatArray(3) Color.colorToHSV(this, hsv) hsv[2] /= alpha // 将颜色的亮度值乘以alpha,生成更浅的颜色 return Color.HSVToColor(hsv) } /** * 白色状态栏 */ fun Activity.whiteStatusBar() { immersionBar { reset() fitsSystemWindows(true) statusBarDarkFont(true) statusBarColor(R.color.white) navigationBarColor(R.color.white) //导航栏颜色,不写默认黑色 init() } } /** * 灰色状态栏 */ fun Activity.grayStatusBar() { immersionBar { reset() fitsSystemWindows(true) statusBarDarkFont(true) statusBarColor(R.color.color_f5f7f7) navigationBarColor(R.color.color_f5f7f7) //导航栏颜色,不写默认黑色 init() } } fun Activity.customerStatusBar() { immersionBar { reset() statusBarColor(R.color.color_f5f7f7) navigationBarColor(R.color.color_f5f7f7) //导航栏颜色,不写默认黑色 init() } } /** * 灰色状态栏 */ fun Activity.mainStatusBar() { immersionBar { reset() fitsSystemWindows(true) statusBarDarkFont(true) statusBarColor(R.color.color_f5f7f7) navigationBarColor(R.color.white) //导航栏颜色,不写默认黑色 init() } } /** * 隐藏灰色状态栏 * */ fun Activity.hideGrayStatusBar() { immersionBar { reset() hideStatusBar() init() } } /** * 灰色状态栏 */ fun Activity.keyBoardModeStatusBar() { immersionBar { reset() fitsSystemWindows(true) statusBarDarkFont(true) statusBarColor(R.color.color_f5f7f7) keyboardEnable(true) keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) init() } } fun File.requestBody(): MultipartBody.Part { return MultipartBody.Part.createFormData( "file", this.name, this.asRequestBody("multipart/binary".toMediaType()) ) } /** * 横向滑动 */ fun RecyclerView.horizontal() { this.layoutManager = LinearLayoutManager(this.context, RecyclerView.HORIZONTAL, false) } /** * 横向滑动 */ fun RecyclerView.gridLayout(spanCount: Int) { this.layoutManager = GridLayoutManager(this.context, spanCount) } /** * 初始化刷新和加载更多控件 */ fun SmartRefreshLayout.initRefreshLoadMoreLayout(context: Context) { setRefreshHeader(ClassicsHeader(context)) setRefreshFooter(ClassicsFooter(context)) } /** * @return true 代表已经获取相关权限 */ fun checkPermission(permission: String): Boolean { return PermissionUtils.isGranted(permission) } /** * 权限检查 Array<String> */ fun permissionCheck(permission: Array<String>, fn: () -> Unit) { if (PermissionUtils.isGranted(*permission)) { fn.invoke() } else { PermissionUtils.permission(*permission) .callback { isAllGranted, granted, deniedForever, denied -> if (isAllGranted) { fn.invoke() } }.request() } } /** * 权限检查 String */ fun permissionCheck(permission: String, fn: () -> Unit) { if (PermissionUtils.isGranted(permission)) { fn.invoke() } else { PermissionUtils.permission(permission).apply { request() callback { isAllGranted, _, _, _ -> if (isAllGranted) fn.invoke() } } } } /** * 输入字符格式限制 */ fun AppCompatEditText.resetFilter() { // val filters = arrayOf<InputFilter>(NumberInputFilter()) // setFilters(filters) addTextChangedListener(object : DefaultTextWatcher() { override fun afterTextChanged(s: Editable?) { if (s.toString().startsWith("0")) { setText("") } } }) } /** * 时间格式化 */ fun Long.timeFormat(): String { val hour: Long = this / 3600 val min: Long = (this % 3600) / 60 val second: Long = ((this % 3600) % 60) return "${hour.toHourString()}${min.toUnHourString()}:${second.toUnHourString()}" } /** * 时分秒位数格式化 */ fun Long.toHourString(): String { return when (this) { in 1 until 10 -> "0$this:" in 10 until 25 -> "$this:" else -> "" } } /** * 时分秒位数格式化 */ fun Long.toUnHourString(): String { return when (this) { in 1 until 10 -> "0$this" in 10 until 61 -> "$this" else -> "00" } } fun getLanguage(): String { val systemLanguage: String = LanguageUtils.getSystemLanguage().language val defaultLanguage = SPUtils.getInstance().getString("languageLocale") if (defaultLanguage.isNullOrEmpty()) { return if (systemLanguage != "zh" && systemLanguage != "en" && systemLanguage != "de" && systemLanguage != "fr" && systemLanguage != "es" && systemLanguage != "pt" && systemLanguage != "it") { "en" } else { systemLanguage } } return defaultLanguage } fun getLanguageConfig(): Int { return when (getLanguage()) { "en" -> 2 "zh" -> 0 "fr" -> 5 "de" -> 4 "es" -> 8 "pt" -> LanguageConfig.PORTUGAL else -> 2 } } fun getAppKey(): String { when (getLanguage()) { "en" -> return "69356d615c4b49dca6da917c5feac757" "zh" -> return "926ba12b5569482daa9efe42ae59eda3" "fr" -> return "69356d615c4b49dca6da917c5feac757" "de" -> return "69356d615c4b49dca6da917c5feac757" "es" -> return "69356d615c4b49dca6da917c5feac757" } return "69356d615c4b49dca6da917c5feac757" } fun timePeriodOf(startTime: String, endTime: String, pattern: String): String { val startDateTime = startTime.toLocalDateTime(pattern) val endDateTime = endTime.toLocalDateTime(pattern) val isSameYear = startDateTime.year == endDateTime.year val isSameDay = startDateTime.toLocalDate() == endDateTime.toLocalDate() val isThisYear = LocalDate.now().year == startDateTime.year return when { isSameDay && isThisYear -> { val start = startDateTime.format("MM/dd HH:mm") val end = startDateTime.format("HH:mm") ActivityUtils.getTopActivity().getString(R.string.common_time_period, start, end) } isSameDay && !isThisYear -> { val start = startDateTime.format("MM/dd/yyyy HH:mm") val end = startDateTime.format("HH:mm") ActivityUtils.getTopActivity().getString(R.string.common_time_period, start, end) } isSameYear && isThisYear -> { val start = startDateTime.format("MM/dd HH:mm") val end = startDateTime.format("MM/dd HH:mm") ActivityUtils.getTopActivity().getString(R.string.common_time_period, start, end) } else -> { val start = startDateTime.format("MM/dd/yyyy HH:mm") val end = startDateTime.format("MM/dd/yyyy HH:mm") ActivityUtils.getTopActivity().getString(R.string.common_time_period, start, end) } } }