扩展函数工具类篇(Kotlin)

引言:本文仅记录自己项目中使用到的扩展类、则需使用!(均为kt文件)

一、ActivityExpand

/**
 * 启动Activity
 */
fun AppCompatActivity.startPager(actClass: Class<*>) {
    startActivity(Intent(this, actClass))
}

/**
 * 启动Activity
 */
fun Context.startPager(actClass: Class<*>) {
    startActivity(Intent(this, actClass))
}

/**
 * 传递intent,启动Activity
 */
fun Context.startPager(intents: Intent, actClass: Class<*>) {
    intents.setClass(this, actClass)
    startActivity(intents)
}

/**
 * 待餐传递
 */
fun Activity.startPager(intents: Intent, actClass: Class<*>) {
    intents.setClass(this, actClass)
    startActivity(intents)
}

使用:扩展函数工具类篇(Kotlin)_第1张图片

 


二、ContextExand(兼容6.0 及一下老设备写法)

fun Context.getColors(@ColorRes id: Int) = ContextCompat.getColor(this, id)

fun Context.getDrawables(@DrawableRes id: Int) = ContextCompat.getDrawable(this, id)

三、DecimalExpand

fun String.fenToYuanByString() = BigDecimal(this).fenToYuanByNumber()

fun Int.fenToYuanByString() = BigDecimal(this).fenToYuanByNumber()

fun String.fenToYuanByStringNoZero(): String {
    return try {
        val result = BigDecimal(this).fenToYuanByNumber().toString()
        result.subSequence(0, result.indexOf(".")).toString()
    } catch (e: Exception) {
        BigDecimal(this).fenToYuanByNumber().toString()
    }
}

fun Int.fenToYuanByStringNoZero(): String {
    return try {
        val result = BigDecimal(this).fenToYuanByNumber().toString()
        result.subSequence(0, result.indexOf(".")).toString()
    } catch (e: Exception) {
        BigDecimal(this).fenToYuanByNumber().toString()
    }
}


fun BigDecimal.fenToYuanByNumber(): BigDecimal =
    this.divide(BigDecimal(100), 2, RoundingMode.HALF_UP)

格式化money 保留2位数


四、FloatExpand(dp、sp像素转换)

fun Float.dp2Px() = ConvertUtils.dp2px(this).toFloat()

fun Float.px2Dp() = ConvertUtils.px2dp(this).toFloat()

fun Float.sp2Px() = ConvertUtils.sp2px(this).toFloat()

用到了第三方库(当然也可以不用、懒得折腾了):

implementation 'com.blankj:utilcodex:1.31.1'

使用: 

 扩展函数工具类篇(Kotlin)_第2张图片

 


五、LongExpand

//格式化时间
fun Long.formatDate(format: String) = SimpleDateFormat(format, Locale.CHINA).format(Date(this))

/**
 * this ==单位秒
 * 返回对应的秒数 eg 1s 2s
 */
fun Long.formatSeconds(): String = when {
    this <= 0 -> {
        "00:00"
    }
    this < 60 -> {
        format(Locale.getDefault(), "00:%02d", this % 60)
    }
    this < 3600 -> {
        format(
            Locale.getDefault(),
            "%02d:%02d",
            this / 60,
            this % 60
        )
    }
    else -> {
        format(
            Locale.getDefault(),
            "%02d:%02d:%02d",
            this / 3600,
            this % 3600 / 60,
            this % 60
        )
    }
}


六、ObjectExpand(对象转json字符串)

fun Any.toJson(): String {
    return try {
        GsonUtils.toJson(this)
    } catch (e: Exception) {
        ""
    }
}

七、StringExpand

/**
 * 是否包含英文字母与数字
 */
fun String.isLetter(): Boolean {
    val regex = "^[a-z0-9A-Z].*"
    return this.matches(Regex(regex))
}

/**
 * 是否包含英文字符
 */
fun String.isContainLetter(): Boolean {
    val regex = ".*[a-zA-Z]+.*"
    return Pattern.compile(regex, Pattern.CASE_INSENSITIVE or Pattern.DOTALL).matcher(this)
        .matches()
}

/**
 * 全部为英文字母?
 */
fun String.isAllLetter(): Boolean {
    val regex = "[a-zA-Z]+"
    return this.matches(Regex(regex))
}

/**
 * 判断是否包含.0 .00的数据类型
 * 整数
 */
fun String.convertInteger(): String {
    val subs = splitToMutableList(".")
    return if (subs.last() == "0") {
        removeSuffix(".0")
    } else if (subs.last() == "00") {
        removeSuffix(".00")
    } else {
        this
    }
}

/**
 * 隐藏中间的手机号 188****7502
 */
fun String.hideMiddlePhone(): String {
    val msg = replaceRange(3..6, "")
    return StringBuilder(msg).apply {
        for (index in 0..length) {
            if (index == 3) {
                insert(index, "****")
            }
        }
    }.toString()
}

/**
 * 隐藏身份证、
 */
fun String.hideIcCard(): String {
    val last = this.length - 4
    val msg = replaceRange(4..last, "")
    return StringBuilder(msg).apply {
        for (index in 0..length) {
            if (index == 4) {
                insert(index, "******")
            }
        }
    }.toString()
}



//截取 根据表达式
fun String.splitToMutableList(regex: String) = split(regex).toMutableList()

/**
 * 转为实体类对象
 */
fun  String.toJsonObject(type: Class): T? {
    return try {
        GsonUtils.fromJson(this, type)
    } catch (e: Exception) {
        null
    }
}

/**
 * 转为list实体类对象
 */
fun  String.toJsonListObject(type: Class): List? {
    return try {
        GsonUtils.fromJson?>(this, GsonUtils.getListType(type))
    } catch (e: Exception) {
        null
    }
}

八、RecycleViewExpand

/**
 * 是否滚动到底部
 */
fun RecyclerView.isSlideToBottom(): Boolean {
    return this.computeVerticalScrollExtent() + this.computeVerticalScrollOffset() >= this.computeVerticalScrollRange()
}

fun RecyclerView.isSlideToTop(): Boolean {
    return if (layoutManager is LinearLayoutManager) {
        val firstItemPosition =
            (layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
        firstItemPosition == 0
    } else false
}

九、ViewExpand(包含了EditText、ScrollView、ImageView等)

fun View.showAnim(duration: Long, listener: AnimatorListenerAdapter?) {
    ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).run {
        this.duration = duration
        addListener(listener)
        start()
    }
}

/**
 * 隐藏动画
 */
fun View.hideAnim(duration: Long, listener: AnimatorListenerAdapter?): Animator {
    return ObjectAnimator.ofFloat(this, "alpha", 1f, 0f).apply {
        this.duration = duration
        if (listener != null) {
            addListener(listener)
        }
        start()
    }
}

fun View.hideAnimate(duration: Long = 500, alpha: Float = 0f, listener: AnimatorListenerAdapter) {
    this.animate().alpha(alpha).setDuration(duration).setListener(listener).start()
}

/**
 * 扩大点击作用域
 * @param expandTouch 扩大的点击区域
 */
fun View.setTouchDelegate(expandTouch: Int) {
    try {
        val parentView = this.parent as View
        parentView.post {
            val rect = Rect()
            this.getHitRect(rect)
            rect.top -= expandTouch
            rect.bottom += expandTouch
            rect.left -= expandTouch
            rect.right += expandTouch
            parentView.touchDelegate = TouchDelegate(rect, this)
        }
    } catch (e: Exception) {
    }
}


/**
 * 点击放大  
 *   implementation 'com.github.SherlockGougou:BigImageViewPager:androidx-6.2.0'
 */
fun ImageView.clickBigger(uri: String, showDownBt: Boolean = true) {
    setOnClickListener {
        ImagePreview.getInstance().setContext(this.context).setImage(uri)// 图片
            .setShowCloseButton(true)// 是否显示关闭按钮
            .setShowDownButton(showDownBt)// 是否显示下载按钮
            .setFolderName(
                this.context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString()
            )// 设置下载到的文件夹名(保存到根目录)
            .start()
    }
}

/**
 * 点击放大
 */
fun ImageView.clickBigger(
    listUri: List, defaultIndex: Int = 0, showDownBt: Boolean = true
) {
    setOnClickListener {
        ImagePreview.getInstance().setContext(this.context).setImageList(listUri)// 图片
            .setIndex(defaultIndex).setShowCloseButton(true)// 是否显示关闭按钮
            .setShowDownButton(showDownBt)// 是否显示下载按钮
            .setFolderName(
                this.context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString()
            )// 设置下载到的文件夹名(保存到根目录)
            .start()
    }
}

/**
 * 清除点击放大逻辑
 */
fun ImageView.clearClickBigger() {
    setOnClickListener(null)
}


fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.INVISIBLE
}

fun View.goneHide() {
    visibility = View.GONE
}

/**
 * 禁止输入空格 禁止后xml中的限制将失效。
 * @param limitLength 限制文本输入长度
 */
fun EditText.noSpace(limitLength: Int = 1000) {
    filters = arrayOf(object : InputFilter {
        override fun filter(
            source: CharSequence?, p1: Int, p2: Int, p3: Spanned?, p4: Int, p5: Int
        ): CharSequence? {
            return when {
                source.isNullOrBlank() -> ""
                source.contains("\\n") -> {
                    source.toString().replace("\\n", "")
                }
                source.contains("\\b") -> {
                    source.toString().replace("\\b", "")
                }
                else -> null
            }
        }
    }, InputFilter.LengthFilter(limitLength))
}

//禁止\n \b 符号
fun EditText.noSymbol(limitLength: Int = 1000) {
    filters = arrayOf(object : InputFilter {
        override fun filter(
            source: CharSequence?, p1: Int, p2: Int, p3: Spanned?, p4: Int, p5: Int
        ): CharSequence? {
            return when {
                source?.contains("\\n") == true -> {
                    source.toString().replace("\\n", "")
                }
                source?.contains("\\b") == true -> {
                    source.toString().replace("\\b", "")
                }
                else -> null
            }
        }
    }, InputFilter.LengthFilter(limitLength))
}

//只输入中文
fun EditText.onlyCN(limitLength: Int = -1) {
    if (limitLength != -1) {
        filters = arrayOf(object : InputFilter {
            override fun filter(
                source: CharSequence?, start: Int, end: Int, p3: Spanned?, p4: Int, p5: Int
            ): CharSequence? {
                try {
                    for (index in start..end) {
                        return if (!isChinese(source?.get(index))) "" else source
                    }
                } catch (e: Exception) {
                }
                return null
            }
        }, InputFilter.LengthFilter(10))
    } else {
        filters = arrayOf(object : InputFilter {
            override fun filter(
                source: CharSequence?, start: Int, end: Int, p3: Spanned?, p4: Int, p5: Int
            ): CharSequence? {
                try {
                    for (index in start..end) {
                        return if (!isChinese(source?.get(index))) "" else source
                    }
                } catch (e: Exception) {
                }
                return null
            }
        })
    }
}

/**
 * 判定输入汉字
 *
 * @param c
 * @return
 */
fun isChinese(c: Char?): Boolean {
    if (c == null) {
        return false
    }
    val ub = Character.UnicodeBlock.of(c)
    return ub === Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub === Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub === Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub === Character.UnicodeBlock.GENERAL_PUNCTUATION || ub === Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub === Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
}

/**
 * 设置Hint字体大小
 */
fun EditText.setHintTextSize(hint: String, sizeSp: Int) {
    val sp = SpannableString(hint).apply {
        setSpan(
            AbsoluteSizeSpan(sizeSp, true), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }
    setHint(sp)
}

fun EditText.setHintTextSize(sizeSp: Int) {
    val sp = SpannableString(hint).apply {
        setSpan(
            AbsoluteSizeSpan(sizeSp, true), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }
    hint = sp
}

/**
 * 设置过滤器、一般用于提现等金额操作、
 * 保留两位小数
 */
fun EditText.formatMoney() {
    filters = arrayOf(AmountInputFilter())
}

/**
 * 限制输入小数位数
 */
fun EditText.limitInputNUm(numLimitLength:Int) {
    filters = arrayOf(AmountInputFilter(numLimitLength))
}

fun EditText.clearFilter() {
    filters = arrayOf()
}

class AmountInputFilter : InputFilter {

    constructor()

    constructor(numLimitLength: Int) {
        this.numLimitLength = numLimitLength
    }

    /**
     * 最大数字,我们取int型最大值
     */
    val MAX_VALUE = Int.MAX_VALUE

    /**
     * 小数点后的数字的位数
     */
    var numLimitLength = 2

    var p: Pattern? = null

    init {
        //除数字以外的
        p = Pattern.compile("[0-9]*")
    }

    override fun filter(
        source: CharSequence,
        start: Int,
        end: Int,
        dest: Spanned,
        dstart: Int,
        dend: Int
    ): CharSequence {
        val oldtext = dest.toString()
        //第一个输入.或者0,返回
        if (dest.toString() == "" && source.isNotEmpty() && (source[0].toString() == "." || source[0].toString() == "0")) return ""
        // 验证删除等按键 排除首字符.
        if (TextUtils.isEmpty(source)
            || (TextUtils.isEmpty(oldtext)
                    && source[0].toString() == ".")
        ) {
            return ""
        }
        // 验证非数字或者小数点的情况
        val m = p!!.matcher(source)
        if (oldtext.contains(".")) {
            // 已经存在小数点的情况下,只能输入数字
            if (!m.matches()) {
                return ""
            }
        } else {
            // 未输入小数点的情况下,可以输入小数点和数字
            if (!m.matches() && source != ".") {
                return ""
            }
        }
        // 验证输入金额的大小
        if (source.toString() != "") {
            val dold = (oldtext + source.toString()).toDouble()
            if (dold > MAX_VALUE) {
                return dest.subSequence(dstart, dend)
            } else if (dold == MAX_VALUE.toDouble()) {
                if (source.toString() == ".") {
                    return dest.subSequence(dstart, dend)
                }
            }
        }
        // 验证小数位精度是否正确
        if (oldtext.contains(".")) {
            val index = oldtext.indexOf(".")
            val len = dend - index
            // 小数位只能2位
            if (len > numLimitLength) {
                return dest.subSequence(dstart, dend)
            }
        }
        return dest.subSequence(dstart, dend).toString() + source.toString()
    }
}

/**
 * 全局置灰
 * 一般我们都知道图像是由一个一个像素点组成的,而像素点是通过RGBA(红绿蓝,透明度)来控制的,这个是数字方向的。
 * 但是在我们早期的彩色电视机中,我们经常会调整彩电的色调,饱和度和亮度,其中色调就是物体的颜色,饱和度就是颜色的纯度,从0到100%来描述,亮度就是颜色的相对明暗程度。
 * 既然饱和度为0就可以变成灰色,那么我们通过设置ColorMatrix然后给到Paint画笔。
 */
fun setWindowsViewGray(view: View) {
    try {
        val paint = Paint()
        val cm = ColorMatrix()
        cm.setSaturation(0f)
        paint.colorFilter = ColorMatrixColorFilter(cm)
        view.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
    } catch (e: Exception) {
        e.printStackTrace()
    } catch (e: Error) {
        e.printStackTrace()
    }
}

/**
 * 恢复原色
 */
fun setWindowsViewPrimaryColor(view: View) {
    try {
        val paint = Paint()
        val cm = ColorMatrix()
        cm.setSaturation(1f)
        paint.colorFilter = ColorMatrixColorFilter(cm)
        view.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
    } catch (e: Exception) {
        e.printStackTrace()
    } catch (e: Error) {
        e.printStackTrace()
    }
}

/**
 * 是否到底部
 */
fun ScrollView.isBottom() = (this.getChildAt(0).height - this.height == this.scrollY)

/**
 * 是否到底部 带有误差
 */
fun ScrollView.isBottom(deviationPx: Int) =
    ((this.getChildAt(0).height - this.height) - deviationPx <= this.scrollY)

/**
 * 滚动到顶部
 */
fun ScrollView.scrollTop() = this.fullScroll(ScrollView.FOCUS_UP)

/**
 * 滚动到底部
 */
fun ScrollView.scrollBottom() = this.fullScroll(ScrollView.FOCUS_DOWN)

十、ImageView 使用Coil的扩展

依赖:

//coil 图片加载框架Kotlin 推荐
implementation("io.coil-kt:coil:1.1.1")
implementation("io.coil-kt:coil-gif:0.9.5")
//加载一个圆角为10dp的图片
/**
* corner.dp2Px() 也可以自行进行dp转换
* placeholder errorPic 、自行替换、展位图 及加载错误图
*/
fun ImageRequest.Builder.coilSet(
    corner: Float = 10f,
    @DrawableRes placeholder: Int = R.drawable.ic_qg_placeholder,
    @DrawableRes errorPic: Int = R.drawable.ic_qg_placeholder,
    scale: Scale = Scale.FILL
) {
    placeholder(placeholder)
    error(errorPic)
    transformations(RoundedCornersTransformation(corner.dp2Px()))
    scale(scale)
}

//corner.dp2Px()参考FloatExpand扩展函数

 使用:

  val test_uri1 =
        "https://img2020.cnblogs.com/blog/1289812/202005/1289812-20200509091913298-1286944090.png"

    fun test1() {

        val imageView = ImageView(this)

        //加载一个圆角为10dp的图片
        imageView.load(test_uri1) {
            coilSet()
        }

    }

你可能感兴趣的:(android,开发,kotlin,android,工具类)