Initial commit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.mm20.launcher2.ktx">
|
||||
|
||||
/
|
||||
</manifest>
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.location.Address
|
||||
|
||||
fun Address.formatToString(
|
||||
): String {
|
||||
val sb = StringBuilder()
|
||||
if (locality != null) sb.append(locality).append(", ")
|
||||
if (countryCode != null) sb.append(countryCode)
|
||||
return sb.toString()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
val Context.dp: Float
|
||||
get() = resources.displayMetrics.density
|
||||
|
||||
|
||||
val Context.sp: Float
|
||||
get() = resources.displayMetrics.scaledDensity
|
||||
|
||||
fun Context.checkPermission(permission: String): Boolean {
|
||||
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
|
||||
fun Context.tryStartActivity(intent: Intent, bundle: Bundle? = null): Boolean {
|
||||
return try {
|
||||
startActivity(intent, bundle)
|
||||
true
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import kotlin.math.ceil
|
||||
|
||||
fun Double.ceilToInt(): Int {
|
||||
return ceil(this).toInt()
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.Px
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
|
||||
fun Drawable.toBitmapOrNull(
|
||||
@Px width: Int = intrinsicWidth,
|
||||
@Px height: Int = intrinsicHeight,
|
||||
config: Bitmap.Config? = null
|
||||
): Bitmap? {
|
||||
if (this is BitmapDrawable && bitmap == null) return null
|
||||
return toBitmap(width, height, config)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
import org.json.JSONObject
|
||||
|
||||
fun jsonObjectOf(vararg pairs: Pair<String, Any?>): JSONObject {
|
||||
val json = JSONObject()
|
||||
for ((k, v) in pairs) {
|
||||
when (v) {
|
||||
is Float -> json.put(k, v.toDouble())
|
||||
is Double -> json.put(k, v)
|
||||
is Int -> json.put(k, v)
|
||||
is Long -> json.put(k, v)
|
||||
is Boolean -> json.put(k, v)
|
||||
is String -> json.put(k, v)
|
||||
else -> json.put(k, v)
|
||||
}
|
||||
}
|
||||
return json
|
||||
}
|
||||
|
||||
@ChecksSdkIntAtLeast(parameter = 0)
|
||||
fun isAtLeastApiLevel(apiLevel: Int): Boolean {
|
||||
return Build.VERSION.SDK_INT >= apiLevel
|
||||
}
|
||||
|
||||
inline fun <reified T> Any?.castTo(): T {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this as T
|
||||
}
|
||||
|
||||
inline fun <reified T> Any?.castToOrNull(): T? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this as? T
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import kotlin.math.ceil
|
||||
|
||||
fun Float.ceilToInt(): Int {
|
||||
return ceil(this).toInt()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
val Fragment.dp: Float
|
||||
get() = context?.dp ?: 0f
|
||||
|
||||
val Fragment.sp: Float
|
||||
get() = context?.sp ?: 0f
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import java.io.InputStream
|
||||
|
||||
fun InputStream.asBitmap(options : BitmapFactory.Options? = null): Bitmap? {
|
||||
return BitmapFactory.decodeStream(this, null, options)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
|
||||
fun Int.isBrightColor(): Boolean {
|
||||
val darkness = 1 - (0.299 * red + 0.587 * green + 0.114 * blue) / 255
|
||||
return darkness < 0.5
|
||||
}
|
||||
|
||||
val Int.sat : Float
|
||||
get() {
|
||||
FloatArray(3).also {
|
||||
ColorUtils.RGBToHSL(red, green, blue, it)
|
||||
return it[1]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun <T> List<T>.randomElement(): T {
|
||||
if (isEmpty()) throw IndexOutOfBoundsException("List is empty")
|
||||
return get(Random().nextInt(size))
|
||||
}
|
||||
|
||||
fun <T> List<T>.randomElementOrNull(): T? {
|
||||
if (isEmpty()) return null
|
||||
return get(Random().nextInt(size))
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
fun Notification.getBadgeIcon(context: Context, packageName: String): Drawable? {
|
||||
return smallIcon.loadDrawable(context)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
|
||||
fun Rect.translate(x: Int, y: Int): Rect {
|
||||
top += y
|
||||
bottom += y
|
||||
left += x
|
||||
right += x
|
||||
return this
|
||||
}
|
||||
|
||||
fun Rect.toRectF(other: RectF) {
|
||||
other.left = left.toFloat()
|
||||
other.bottom = bottom.toFloat()
|
||||
other.right = right.toFloat()
|
||||
other.top = top.toFloat()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.graphics.RectF
|
||||
|
||||
fun RectF.scale(factor: Float) {
|
||||
val newWidth = width() * factor
|
||||
val newHeight = height() * factor
|
||||
bottom += newHeight - height()
|
||||
right += newWidth - width()
|
||||
}
|
||||
|
||||
fun RectF.translate(x: Float, y: Float): RectF {
|
||||
top += y
|
||||
bottom += y
|
||||
left += x
|
||||
right += x
|
||||
return this
|
||||
}
|
||||
|
||||
infix fun RectF.copyTo(other: RectF) {
|
||||
other.top = top
|
||||
other.left = left
|
||||
other.right = right
|
||||
other.bottom = bottom
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
fun Resources.getIntArrayOrNull(id: Int): IntArray? {
|
||||
return try {
|
||||
getIntArray(id)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun Resources.getDrawableOrNull(id: Int, theme: Resources.Theme? = null): Drawable? {
|
||||
return try {
|
||||
getDrawable(id, theme)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun Resources.obtainTypedArrayOrNull(id: Int): TypedArray? {
|
||||
return try {
|
||||
obtainTypedArray(id)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.content.SharedPreferences
|
||||
|
||||
fun SharedPreferences.Editor.putDouble(key: String, value: Double) {
|
||||
putLong(key, value.toBits())
|
||||
}
|
||||
|
||||
fun SharedPreferences.getDouble(key: String): Double? {
|
||||
if (contains(key)) return Double.fromBits(getLong(key, 0))
|
||||
return null
|
||||
}
|
||||
|
||||
fun SharedPreferences.getDouble(key: String, defValue: Double): Double {
|
||||
if (contains(key)) return Double.fromBits(getLong(key, 0))
|
||||
return defValue
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import java.net.URLDecoder
|
||||
|
||||
fun String.decodeUrl(charset: String): String? {
|
||||
return URLDecoder.decode(this, charset)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
|
||||
fun TextView.setStartCompoundDrawable(drawable: Drawable?) {
|
||||
setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
|
||||
}
|
||||
|
||||
fun TextView.setStartCompoundDrawable(@DrawableRes drawableRes: Int) {
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(drawableRes, 0, 0, 0)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Process
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
|
||||
fun UserHandle.getSerialNumber(context: Context): Long {
|
||||
if (this == Process.myUserHandle()) return 0L
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
return userManager.getSerialNumberForUser(this)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
val View.dp: Float
|
||||
get() = context.dp
|
||||
|
||||
val View.sp: Float
|
||||
get() = context.sp
|
||||
|
||||
fun View.asViewGroup(): ViewGroup? {
|
||||
return this as? ViewGroup
|
||||
}
|
||||
|
||||
val View.lifecycleScope
|
||||
get() = (context as LifecycleOwner).lifecycleScope
|
||||
|
||||
fun View.setPadding(vertical: Int, horizontal: Int) {
|
||||
setPadding(vertical, horizontal, vertical, horizontal)
|
||||
}
|
||||
Reference in New Issue
Block a user