Android--常用的Kotlin扩展方法

一、Context

1、获取颜色
fun Context.getColorCompat(color: Int) = ContextCompat.getColor(this, color)
2、获取屏幕宽/高(px)
val Context.screenWidthPx: Int
    get() = resources.displayMetrics.widthPixels
    
val Context.screenHeightPx: Int
    get() = resources.displayMetrics.heightPixels    
    
3、获取屏幕宽/高(dp)

val View.screenWidthDp: Int
    get() = screenWidthPx.px2dp()

val View.screenHeightDp: Int
    get() = screenHeightPx.px2dp()
    
4、inflater
val Context.inflater: LayoutInflater
    get() = LayoutInflater.from(this)
    
    
fun Context.inflateLayout(@LayoutRes layoutId: Int, parent: ViewGroup? = null, attachToRoot: Boolean = false) = inflater.inflate(layoutId, parent, attachToRoot)   
    
5、startActivity/startService
fun <reified T : Activity> Context?.startActivity() = this?.startActivity(Intent(this, T::class.java))


fun <reified T : Service> Context?.startService() = this?.startService(Intent(this, T::class.java))
7、startActivityWithAnimation
inline fun <reified T : Activity> Context.startActivityWithAnimation(enterResId: Int = 0, exitResId: Int = 0) {
    val intent = Intent(this, T::class.java)
    val bundle = ActivityOptionsCompat.makeCustomAnimation(this, enterResId, exitResId).toBundle()
    ContextCompat.startActivity(this, intent, bundle)
}


inline fun <reified T : Activity> Context.startActivityWithAnimation(enterResId: Int = 0, exitResId: Int = 0, intentBody: Intent.() -> Unit) {
    val intent = Intent(this, T::class.java)
    intent.intentBody()
    val bundle = ActivityOptionsCompat.makeCustomAnimation(this, enterResId, exitResId).toBundle()
    ContextCompat.startActivity(this, intent, bundle)
}
6、toast
fun Context?.toast(text: CharSequence, duration: Int = Toast.LENGTH_LONG) = this?.let { Toast.makeText(it, text, duration).show() }

fun Context?.toast(@StringRes textId: Int, duration: Int = Toast.LENGTH_LONG) = this?.let { Toast.makeText(it, textId, duration).show() }
7、获取资源

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

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

fun Context.getInteger(@IntegerRes id: Int) = resources.getInteger(id)

fun Context.getBoolean(@BoolRes id: Int) = resources.getBoolean(id)

8、获取各种系统Manager
val Context.inputManager: InputMethodManager?
    get() = getSystemService(INPUT_METHOD_SERVICE) as? InputMethodManager

val Context.notificationManager: NotificationManager?
    get() = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager

val Context.keyguardManager: KeyguardManager?
    get() = getSystemService(KEYGUARD_SERVICE) as? KeyguardManager
9、跳转到拨号界面
fun Context.makeCall(number: String): Boolean {
    try {
        val intent = Intent(ACTION_CALL, Uri.parse("tel:$number"))
        startActivity(intent)
        return true
    } catch (e: Exception) {
        return false
    }
}
10、是否开启通知
fun  Context.isNotificationOpen():Boolean{
    var isOpened: Boolean
    try {
        isOpened = NotificationManagerCompat.from(this).areNotificationsEnabled()
    } catch (e: Exception) {
        e.printStackTrace()
        isOpened = false
    }
    return isOpened
}

二、Activity

1、隐藏键盘
fun Activity.hideSoftKeyboard(focusView: View? = null) {
    val focusV = focusView ?: currentFocus
    focusV?.apply {
        val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
    }
}
2、弹起键盘
fun Activity.showSoftKeyboard(editText: EditText) {
    editText.postDelayed({
        editText.requestFocus()
        val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_FORCED)
    }, 30)
}
3、获取ContentView
fun Activity.getContentView(): ViewGroup {
    return this.findViewById(android.R.id.content) as ViewGroup
}
4、设备Window背景
fun AppCompatActivity.setWindowBackGround(@ColorRes colorRes: Int) {
    window.getDecorView().setBackgroundResource(colorRes)
}


5、添加fragment到Activity
fun AppCompatActivity.addFragmentToActivity(fragment: Fragment, tag: String) {
    supportFragmentManager.transact {
        add(fragment, tag)
    }
}

三、Fragment

1、Toast
fun Fragment?.toast(text: CharSequence, duration: Int = Toast.LENGTH_LONG) = this?.let { activity.toast(text, duration) }


fun Fragment?.toast(@StringRes textId: Int, duration: Int = Toast.LENGTH_LONG) = this?.let { activity.toast(textId, duration) }
2、键盘弹起/隐藏
fun Fragment.hideSoftKeyboard() {
    activity?.hideSoftKeyboard()
}

fun DialogFragment.hideSoftKeyboard() {
    val  dialog = getDialog()
    activity?.hideSoftKeyboard(dialog?.currentFocus)
}


3、commit
inline fun FragmentManager.transact(action: FragmentTransaction.() -> Unit) {
    beginTransaction().apply { action() }.commit()
}

四、View

1、设置padding
fun View.updatePadding(
    paddingStart: Int = getPaddingStart(),
    paddingTop: Int = getPaddingTop(),
    paddingEnd: Int = getPaddingEnd(),
    paddingBottom: Int = getPaddingBottom()
) {
    setPaddingRelative(paddingStart, paddingTop, paddingEnd, paddingBottom)
}



fun View.setPaddingLeft(value: Int) = setPadding(value, paddingTop, paddingRight, paddingBottom)

fun View.setPaddingRight(value: Int) = setPadding(paddingLeft, paddingTop, value, paddingBottom)

fun View.setPaddingTop(value: Int) = setPaddingRelative(paddingStart, value, paddingEnd, paddingBottom)

fun View.setPaddingBottom(value: Int) = setPaddingRelative(paddingStart, paddingTop, paddingEnd, value)


2、改变大小
fun View.resize(width: Int, height: Int) {
    if (width < 0 || height < 0) return
    val lp = layoutParams
    lp?.let {
        lp.width = width
        lp.height = height
        layoutParams = lp
    }
}


fun View.updateHeight(value: Int) {
    if (value < 0) return
    val lp = layoutParams
    lp?.let {
        lp.height = value
        layoutParams = lp
    }
}

fun View.updateWidth(value: Int) {
    if (value < 0) return
    val lp = layoutParams
    lp?.let {
        lp.width = value
        layoutParams = lp
    }
}

3、获取子View集合
val ViewGroup.children: List<View>
    get() = (0 until childCount).map { getChildAt(it) }
4、点击
fun <T : View> T.click(block: (T) -> Unit) = setOnClickListener { block(it as T) }

fun <T : View> T.singleClick(block: (T) -> Unit) = setOnClickListener(object : SingleClickListener() {
    override fun onSingleClick(v: View) {
        block(v as T)
    }
})


fun <T : View> T.longClick(block: (T) -> Boolean) = setOnLongClickListener {
    block(it as T)
}


5、把当前View生成Bitmap
fun View.getBitmap(): Bitmap {
    val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bmp)
    draw(canvas)
    canvas.save()
    return bmp
}
6、获取在屏幕上的坐标
fun View.getLOnScreen(): IntArray {
    val locations = IntArray(2)
    getLocationOnScreen(locations)
    return locations
}



fun View.getLocationXOnScreen(): Int {
    return getLOnScreen()[0]
}

fun View.getLocationYOnScreen(): Int {
    return getLOnScreen()[1]
}

7、获取在窗口上的坐标
fun View.getLInWindow(): IntArray {
    val locations = IntArray(2)
    getLocationInWindow(locations)
    return locations
}


fun View.getLocationXInWindow(): Int {
    return getLInWindow()[0]
}

fun View.getLocationYInWindow(): Int {
    return getLInWindow()[1]
}

五、TextView

1、设置颜色
fun TextView.setTColor(@ColorRes colorId: Int) = setTextColor(context.getCompatColor(colorId))
2、设置部分文本字体颜色高亮
fun TextView.setColorOfSubstring(substring: String, color: Int) {
    try {
        val spannable = android.text.SpannableString(text)
        val start = text.indexOf(substring)
        spannable.setSpan(ForegroundColorSpan(ContextCompat.getColor(context, color)), start, start + substring.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        text = spannable
    } catch (e: Exception) {
        Log.d("ViewExtensions", "exception in setColorOfSubstring, text=$text, substring=$substring", e)
    }
}
3、设置Drawable
fun TextView.setDrawableLeft(drawable: Int) {
    this.setCompoundDrawablesWithIntrinsicBounds(drawable, 0, 0, 0)
}

fun TextView.setDrawableTop(drawable: Int) {
    this.setCompoundDrawablesWithIntrinsicBounds(0, drawable, 0, 0)
}


fun TextView.setDrawableRight(drawable: Int) {
    this.setCompoundDrawablesWithIntrinsicBounds(0, 0, drawable, 0)
}

fun TextView.setDrawableBottom(drawable: Int) {
    this.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0,drawable)
}

4、简写addTextChangedListener
private val beforeTextChangedDefault: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit = {  _,_, _, _ -> }
private val onTextChangedDefault: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit = { _, _, _, _ -> }
private val afterTextChangedDefault: (s: Editable?) -> Unit = {}


fun TextView.addTextChangedListener(
    beforeTextChanged: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit = beforeTextChangedDefault,
    onTextChanged: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit = onTextChangedDefault,
    afterTextChanged: (s: Editable?) -> Unit = afterTextChangedDefault
) =
        this.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                afterTextChanged.invoke(s)
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                beforeTextChanged.invoke(s, start, count, after)
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                onTextChanged.invoke(s, start, before, count)
            }
        })

六、ViewPager

1、简写addOnPageChangeListener

fun ViewPager.addSubscribePageChange(observable: ViewPageChangeObservable.() -> Unit) {
    observable.invoke(ViewPageChangeObservable(this))
}

class ViewPageChangeObservable(viewPager: ViewPager) {

    private var mPageChanged: ((state: Int) -> Unit)? = null
    private var mPageScrolled: ((position: Int, positionOffset: Float, positionOffsetPixels: Int) -> Unit)? = null
    private var mPageSelected: ((position: Int) -> Unit)? = null

    fun onPageScrollStateChanged(pageChanged: (Int) -> Unit) {
        mPageChanged = pageChanged
    }


    fun onPageScrolled(pageScrolled: (Int, Float, Int) -> Unit) {
        mPageScrolled = pageScrolled
    }

    fun onPageSelected(pageSelected: (Int) -> Unit) {
        mPageSelected = pageSelected
    }


    init {
        viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            //“0”表示什么都不做,“1”表示开始滑动,“2”表示结束滑动
            override fun onPageScrollStateChanged(state: Int) {
                mPageChanged?.invoke(state)
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                mPageScrolled?.invoke(position, positionOffset, positionOffsetPixels)
            }

            override fun onPageSelected(position: Int) {
                mPageSelected?.invoke(position)
            }

        })

    }

}

七、ViewListenerExtension

1、OnClickListener

fun View.OnClickListener.setViews(vararg views: View) {
    for (view in views) {
        view.setOnClickListener(this)
    }
}
2、单击
fun SingleClickListener.setViews(vararg views: View) {
    for (view in views) {
        view.setOnClickListener(this)
    }
}


abstract class SingleClickListener : View.OnClickListener {

    companion object {
        const val MIN_CLICK_DELAY_TIME = 500
    }

    private var lastClickTime: Long = 0L

    override fun onClick(v: View) {
        val currentTime = Calendar.getInstance().getTimeInMillis()
        if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
            lastClickTime = currentTime;
            onSingleClick(v);
        }
    }

    abstract fun onSingleClick(v: View)

}

3、CheckedChangeListener
fun CompoundButton.OnCheckedChangeListener.setViews(vararg views: CompoundButton) {
    for (view in views) {
        view.setOnCheckedChangeListener(this)
    }
}

八、NumberExtension

fun Float.dp2px() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)


fun Int.dp2px() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()


//根据手机的分辨率从 px(像素) 的单位 转成为 dp
fun Int.px2dp(): Int {
    val scale = BaseApplication.getAppContext().resources.displayMetrics.density
    return (this / scale + 0.5f).toInt()
}


九、BooleanExtension

**
 *  实现:  Boolean.yes{}.otherwise{}
 */
sealed class BooleanExt1<out T>起桥梁作用的中间类,定义成协变

object Otherwise : BooleanExt1<Nothing>()//Nothing是所有类型的子类型,协变的类继承关系和泛型参数类型继承关系一致

class TransferData1<T>(val data: T) : BooleanExt1<T>()//data只涉及到了只读的操作

//声明成inline函数
inline fun <T> Boolean.yes(block: () -> T): BooleanExt1<T> = when {
    this -> {
        TransferData1(block.invoke())
    }
    else -> Otherwise
}

inline fun <T> BooleanExt1<T>.otherwise(block: () -> T): T = when (this) {
    is Otherwise ->
        block()
    is TransferData1 ->
        this.data
}


/**
 * 实现:  Boolean.otherwise{}.yes{}
 */
sealed class BooleanExt2<out T>起桥梁作用的中间类,定义成协变

object Yes : BooleanExt2<Nothing>()//Nothing是所有类型的子类型,协变的类继承关系和泛型参数类型继承关系一致

class TransferData2<T>(val data: T) : BooleanExt2<T>()//data只涉及到了只读的操作

//声明成inline函数
inline fun <T> Boolean.otherwise(block: () -> T): BooleanExt2<T> = when {
    !this -> {
        TransferData2(block.invoke())
    }
    else -> Yes
}

inline fun <T> BooleanExt2<T>.yes(block: () -> T): T = when (this) {
    is Yes ->
        block()
    is TransferData2 ->
        this.data
}

你可能感兴趣的:(编码技巧)