Android--常用的Kotlin扩展方法

    技术2022-07-13  86

    一、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 }
    Processed: 0.016, SQL: 9