说实话这个我是最近才知道的 虽然学习kotlin还没有多长时间 但是我已经深深的被他吸引了 进入正题
IntentExt
/**
* 跳转Activity
*/
inline fun <reified T : Activity> Context.startActivity(vararg params: Pair<String, Any?>) =
internalStartActivity(this, T::class.java, params)
/**
* 跳转Activity并且请求结果
*/
inline fun <reified T : Activity> Activity.startActivityForResult(vararg params: Pair<String, Any?>, requestCode: Int) =
internalStartActivityForResult(this, T::class.java, params, requestCode)
/**
* 关闭当前Activity并且附带结果
*/
fun Activity.finishActivityWithResult(vararg params: Pair<String, Any?>) {
val intent = Intent()
fillIntentArguments(intent, params)
setResult(RESULT_OK, intent)
finish()
}
/**
* 跳转Activity
*/
inline fun <reified T : Activity> Fragment.startActivity(vararg params: Pair<String, Any?>) =
internalStartActivity(activity!!, T::class.java, params)
/**
* 跳转Activity并且请求结果
*/
inline fun <reified T : Activity> Fragment.startActivityForResult(vararg params: Pair<String, Any?>, requestCode: Int) =
internalStartActivityForResult(this, T::class.java, params, requestCode)
// ---------------------------------------- 一般来说不要使用下面的方法,可以对下面的方法进行一次封装来使用 ----------------------------------------
fun internalStartActivity(context: Context, activity: Class<out Activity>, params: Array<out Pair<String, Any?>>) =
context.startActivity(createIntent(context, activity, params))
fun internalStartActivityForResult(
activity: Activity,
clazz: Class<out Activity>,
params: Array<out Pair<String, Any?>>,
requestCode: Int
) =
activity.startActivityForResult(createIntent(activity, clazz, params), requestCode)
fun internalStartActivityForResult(
fragment: Fragment,
clazz: Class<out Activity>,
params: Array<out Pair<String, Any?>>,
requestCode: Int
) =
fragment.startActivityForResult(createIntent(fragment.activity!!, clazz, params), requestCode)
fun <T> createIntent(context: Context, clazz: Class<out T>, params: Array<out Pair<String, Any?>>): Intent {
val intent = Intent(context, clazz)
if (params.isNotEmpty()) fillIntentArguments(intent, params)
return intent
}
fun fillIntentArguments(intent: Intent, params: Array<out Pair<String, Any?>>) {
params.forEach {
when (val value = it.second) {
null -> intent.putExtra(it.first, null as Serializable?)
is Int -> intent.putExtra(it.first, value)
is Long -> intent.putExtra(it.first, value)
is CharSequence -> intent.putExtra(it.first, value)
is String -> intent.putExtra(it.first, value)
is Float -> intent.putExtra(it.first, value)
is Double -> intent.putExtra(it.first, value)
is Char -> intent.putExtra(it.first, value)
is Short -> intent.putExtra(it.first, value)
is Boolean -> intent.putExtra(it.first, value)
is Serializable -> intent.putExtra(it.first, value)
is Bundle -> intent.putExtra(it.first, value)
is Parcelable -> intent.putExtra(it.first, value)
is Array<*> -> when {
value.isArrayOf<CharSequence>() -> intent.putExtra(it.first, value)
value.isArrayOf<String>() -> intent.putExtra(it.first, value)
value.isArrayOf<Parcelable>() -> intent.putExtra(it.first, value)
}
is IntArray -> intent.putExtra(it.first, value)
is LongArray -> intent.putExtra(it.first, value)
is FloatArray -> intent.putExtra(it.first, value)
is DoubleArray -> intent.putExtra(it.first, value)
is CharArray -> intent.putExtra(it.first, value)
is ShortArray -> intent.putExtra(it.first, value)
is BooleanArray -> intent.putExtra(it.first, value)
}
return@forEach
}
}
ResourceExt
/**
* 从Context中获取资源
*/
fun color(id: Int): Int = ContextCompat.getColor(BaseApp.app.applicationContext, id)
fun string(id: Int): String = BaseApp.app.applicationContext.resources.getString(id)
fun stringArray(id: Int): Array<String> =
BaseApp.app.applicationContext.resources.getStringArray(id)
fun drawable(id: Int) = ContextCompat.getDrawable(BaseApp.app.applicationContext, id)
fun dimen(id: Int) = BaseApp.app.applicationContext.resources.getDimension(id)
fun dp2px(dp: Float): Int =
(dp * BaseApp.app.applicationContext.resources.displayMetrics.density + 0.5f).toInt()
fun px2dp(px: Float): Int =
(px / BaseApp.app.applicationContext.resources.displayMetrics.density + 0.5f).toInt()
fun sp2px(sp: Float): Int =
(sp * BaseApp.app.applicationContext.resources.displayMetrics.scaledDensity + 0.5f).toInt()
fun px2sp(px: Float): Int =
(px / BaseApp.app.applicationContext.resources.displayMetrics.scaledDensity + 0.5f).toInt()
fun Context.inflaterView(@LayoutRes layoutRes: Int, parent: ViewGroup? = null): View =
View.inflate(this, layoutRes, parent)
fun Fragment.inflaterView(@LayoutRes layoutRes: Int, parent: ViewGroup? = null): View =
View.inflate(context, layoutRes, parent)
fun Dialog.inflaterView(@LayoutRes layoutRes: Int, parent: ViewGroup? = null): View =
View.inflate(context, layoutRes, parent)
fun View.inflaterView(@LayoutRes layoutRes: Int, parent: ViewGroup? = null): View =
View.inflate(context, layoutRes, parent)
fun RecyclerView.ViewHolder.inflaterView(@LayoutRes layoutRes: Int, parent: ViewGroup? = null): View =
View.inflate(itemView.context, layoutRes, parent)
SharedPreferencesExt
fun sp(): SharedPreferences =
BaseApp.app.applicationContext.getSharedPreferences(
AppUtils.getAppName(),
Context.MODE_PRIVATE
)
/**
* 批处理
*/
fun SharedPreferences.edit(action: SharedPreferences.Editor.() -> Unit) {
edit().apply { action() }.apply()
}
fun SharedPreferences.put(key: String, value: String) {
edit().putString(key, value).apply()
}
fun SharedPreferences.put(key: String, value: Int) {
edit().putInt(key, value).apply()
}
fun SharedPreferences.put(key: String, value: Boolean) {
edit().putBoolean(key, value).apply()
}
fun SharedPreferences.put(key: String, value: Float) {
edit().putFloat(key, value).apply()
}
fun SharedPreferences.put(key: String, value: Long) {
edit().putLong(key, value).apply()
}
fun SharedPreferences.put(key: String, value: MutableSet<String>) {
edit().putStringSet(key, value).apply()
}
fun SharedPreferences.clear() {
edit { clear() }
}
StringExt
/**
* 是否是手机号
* 1+后面10位
*/
fun String.isPhone(): Boolean = "1\\d{10}$".toRegex().matches(this)
/**
* 是否是邮箱地址
*/
fun String.isEmail(): Boolean = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?".toRegex().matches(this)
/**
* 是否是身份证号码
*/
fun String.isIDCard(): Boolean = "[1-9]\\d{16}[a-zA-Z0-9]".toRegex().matches(this)
/**
* 是否是中文字符
*/
fun String.isChinese(): Boolean = "^[\u4E00-\u9FA5]+$".toRegex().matches(this)
/**
* 获取当前字符串的md5
*/
fun String.md5(): String = EncryptUtils.encryptMD5ToString(this)
/**
* 判断字符串是否为空或者是null的任意变化
* 曾经出现过后台返回"Null" 然后判断isNullOrEmpty()通过 显示在界面上的时候悲剧了
*/
fun String?.isNull() = isNullOrEmpty() || this!!.toLowerCase(Locale.getDefault()).trim() == "null"
TimeExt
/**
* 2018-4-6 11:11:11转为毫秒
* @param format 时间的格式,默认是按照yyyy-MM-dd HH:mm:ss来转换
*/
fun String.toMills(format: String = "yyyy-MM-dd HH:mm:ss"): Long =
SimpleDateFormat(format, Locale.getDefault()).parse(this).time
/**
* Long类型时间戳转为字符串的日期格式
* @param format 时间的格式,默认是按照yyyy-MM-dd HH:mm:ss来转换
*/
fun Long.toDate(format: String = "yyyy-MM-dd HH:mm:ss"): String =
SimpleDateFormat(format, Locale.getDefault()).format(Date(this))
/**
* 到秒
*/
fun Long.toDateUntilSec(): String = toDate("yyyy-MM-dd HH:mm:ss")
/**
* 到分
*/
fun Long.toDateUntilMin(): String = toDate("yyyy-MM-dd HH:mm")
/**
* 到日
*/
fun Long.toDateUntilDay(): String = toDate("yyyy-MM-dd")
/**
* 获取友好时间描述
*/
@SuppressLint("SimpleDateFormat")
fun Long.toTimeDescribe(): String {
val now = System.currentTimeMillis()
val span = now - this
return when {
span < TimeConstants.MIN -> "刚刚"
span < TimeConstants.HOUR -> String.format(Locale.getDefault(), "%d分钟前", span / TimeConstants.MIN)
span < TimeConstants.DAY -> String.format(Locale.getDefault(), "%d小时前", span / TimeConstants.HOUR)
span < 2 * TimeConstants.DAY -> String.format("昨天 %tR", this)
span < 3 * TimeConstants.DAY -> String.format("前天 %tR", this)
else -> SimpleDateFormat("MM - dd").format(Date(this))
}
}
/**
* 获取友好时间描述
*/
@SuppressLint("SimpleDateFormat")
fun String.toTimeDescribe(format: String = "yyyy-MM-dd HH:mm:ss"): String {
return this.toMills(format).toTimeDescribe()
}
ViewExt
/**
* 设置View的高度
* @param height 设置的高度
*/
fun View.height(height: Int): View {
val params = layoutParams
params.height = height
layoutParams = params
return this
}
/**
* 设置View的宽度
* @param width 设置的宽度
*/
fun View.width(width: Int): View {
val params = layoutParams
params.width = width
layoutParams = params
return this
}
/**
* 设置View的宽度和高度
* @param width 要设置的宽度
* @param height 要设置的高度
*/
fun View.widthAndHeight(width: Int, height: Int): View {
val params: ViewGroup.LayoutParams? = layoutParams
if (params == null) {
layoutParams = ViewGroup.LayoutParams(width, height)
} else {
params.width = width
params.height = height
layoutParams = params
}
return this
}
/**
* 设置背景颜色
* @param color Int
* @return View
*/
fun View.backgroundColor(@ColorInt color: Int): View {
setBackgroundColor(color)
return this
}
/**
* 设置View的margin 默认保留原设置
* @param leftMargin 距离左的距离
* @param topMargin 距离上的距离
* @param rightMargin 距离右的距离
* @param bottomMargin 距离下的距离
*/
fun View.margin(
leftMargin: Int = Int.MAX_VALUE,
topMargin: Int = Int.MAX_VALUE,
rightMargin: Int = Int.MAX_VALUE,
bottomMargin: Int = Int.MAX_VALUE
): View {
val params = layoutParams as ViewGroup.MarginLayoutParams
if (leftMargin != Int.MAX_VALUE)
params.leftMargin = leftMargin
if (topMargin != Int.MAX_VALUE)
params.topMargin = topMargin
if (rightMargin != Int.MAX_VALUE)
params.rightMargin = rightMargin
if (bottomMargin != Int.MAX_VALUE)
params.bottomMargin = bottomMargin
layoutParams = params
return this
}
/**
* 设置控件Visible
*/
fun View.visible() {
visibility = View.VISIBLE
}
/**
* 设置控件Gone
*/
fun View.gone() {
visibility = View.GONE
}
/**
* 设置控件Invisible
*/
fun View.invisible() {
visibility = View.INVISIBLE
}
/**
* 设置控件Visible
*/
fun visible(vararg views: View?) {
for (view in views) {
view?.visible()
}
}
/**
* 设置控件Invisible
*/
fun invisible(vararg views: View?) {
for (view in views) {
view?.invisible()
}
}
/**
* 设置控件Gone
*/
fun gone(vararg views: View?) {
for (view in views) {
view?.gone()
}
}
/**
* 设置是否可见
* @param visibleOrGone true - Visible false - Gone
*/
fun View.setVisible(visibleOrGone: Boolean) {
visibility = if (visibleOrGone) View.VISIBLE else View.GONE
}
/**
* 判断控件是否为Gone
*/
val View.isGone: Boolean
get() {
return visibility == View.GONE
}
/**
* 判断控件是否为Visible
*/
val View.isVisible: Boolean
get() {
return visibility == View.VISIBLE
}
/**
* 判断控件是否为InVisible
*/
val View.isInvisible: Boolean
get() {
return visibility == View.INVISIBLE
}
/**
* 获取View的Bitmap
* 支持RecyclerView ScrollView 基础控件 不支持ListView了
* 注意:使用这个方法的时候必须要在View测量完毕之后才能进行
*/
fun View.toBitmap(): Bitmap {
if (measuredWidth == 0 || measuredHeight == 0) {
throw RuntimeException("警告⚠️警告⚠️ 这个时候View还没有测量完毕")
}
return when (this) {
is RecyclerView -> {
this.scrollToPosition(0)
this.measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
)
val screenshot = Bitmap.createBitmap(width, measuredHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(screenshot)
if (background != null) {
background.setBounds(0, 0, width, measuredHeight)
background.draw(canvas)
} else {
canvas.drawColor(Color.WHITE)
}
this.draw(canvas)
this.measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST)
)
screenshot
}
is ScrollView -> {
var totalHeight = 0
for (i in 0 until this.childCount) {
totalHeight += this.getChildAt(i).height
}
val screenshot =
Bitmap.createBitmap(this.getWidth(), totalHeight, Bitmap.Config.ARGB_4444)
val canvas = Canvas(screenshot)
this.draw(canvas)
screenshot
}
else -> {
val screenshot =
Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_4444)
val canvas = Canvas(screenshot)
if (background != null) {
background.setBounds(0, 0, width, measuredHeight)
background.draw(canvas)
} else {
canvas.drawColor(Color.WHITE)
}
draw(canvas)
screenshot
}
}
}
/**
* 设置控件的点击时间
* @param method 点击事件
*/
fun View.onClick(method: (view: View) -> Unit) {
setOnClickListener {
if (ClickHelper.isNotFastClick) {
method(it)
}
}
}
/**
* 对控件设置点击事件
* @receiver View
* @param listener OnNotFastClickListener
*/
fun View.onClick(listener: OnNotFastClickListener) {
setOnClickListener(listener)
}
/**
* 对多个控件设置点击事件
* @param views 控件列表
* @param onClick 点击方法
*/
fun onViewsClickListener(vararg views: View, onClick: (View) -> Unit) {
val listener = View.OnClickListener {
if (ClickHelper.isNotFastClick) {
onClick(it)
}
}
for (view in views) {
view.setOnClickListener(listener)
}
}
/**
* 防止过快点击监听
*/
interface OnNotFastClickListener : View.OnClickListener {
fun onNotFastClick(view: View)
override fun onClick(v: View) {
if (ClickHelper.isNotFastClick) {
onNotFastClick(v)
}
}
}
/**
* 控件在多少秒之后可用
* @param second 秒 3秒 10秒 60秒
*/
@SuppressLint("CheckResult")
fun View.enableAfter(second: Long) {
Observable.interval(0, 1, TimeUnit.SECONDS)
.take(second + 1)
.map { second - it }
.compose(RxHelper.io2Main())
.bindToLifecycle(this)
.doOnSubscribe { isEnabled = false }
.subscribe({}, {}, { isEnabled = true })
}
/**
* 重新发送验证码
* @param second 默认60秒
*/
@SuppressLint("SetTextI18n", "CheckResult")
fun TextView.resendVerificationCodeAfter(second: Long = 60) {
Observable.interval(0, 1, TimeUnit.SECONDS)
.take(second + 1)
.map { second - it }
.compose(RxHelper.io2Main())
.bindToLifecycle(this)
.doOnSubscribe { isEnabled = false }
.subscribe({
text = "(${it}秒)"
setTextColor(color(R.color.color_F5F5F5))
}, {}) {
isEnabled = true
text = "发送验证码"
setTextColor(color(R.color.color_666666))
}
}
// ---------------------------------------- TextView ----------------------------------------
/**
* 安全的设置控件文字
* @param content 内容文字可以为空
*/
fun TextView.setSafeText(content: CharSequence?) {
text = content ?: ""
}