Skip to content

Instantly share code, notes, and snippets.

@vahid-m
Forked from naeemdev/extension.kt
Created February 21, 2024 15:19
Show Gist options
  • Save vahid-m/7cd9178681227cfb48e595de8eec9b22 to your computer and use it in GitHub Desktop.
Save vahid-m/7cd9178681227cfb48e595de8eec9b22 to your computer and use it in GitHub Desktop.
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.FragmentTransaction
import android.app.Activity
import android.app.AlertDialog
import android.app.Fragment
import android.app.NotificationManager
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Resources
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.os.Parcelable
import android.preference.PreferenceManager
import android.provider.Settings
import android.support.annotation.IdRes
import android.support.annotation.StringRes
import android.support.design.widget.Snackbar
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.Toast
import java.io.Serializable
import java.util.regex.Pattern
// Logging
fun Any.debug(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.d("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.debug(msg: Any? = "Debug", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.d("TAG $tag", msg?.toString() ?: "null", thr)
}
fun Any.info(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.i("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.info(msg: Any? = "Info", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.i("TAG $tag", msg?.toString() ?: "null", thr)
}
fun Any.wtf(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.wtf("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.wtf(msg: Any? = "WTF", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.wtf("TAG $tag", msg?.toString() ?: "null", thr)
}
fun Any.warn(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.w("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.warn(msg: Any? = "Warn", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.w("TAG $tag", msg?.toString() ?: "null", thr)
}
fun Any.error(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.e("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.error(msg: Any? = "Error", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.e("TAG $tag", msg?.toString() ?: "null", thr)
}
fun Any.verbose(msg: () -> Any?, tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.v("TAG $tag", msg()?.toString() ?: "null", thr)
}
fun Any.verbose(msg: Any? = "Error", tag: String = this.javaClass.getTag(), thr: Throwable? = null) {
Log.v("TAG $tag", msg?.toString() ?: "null", thr)
}
private fun Class<*>.getTag(): String {
val tag = simpleName
return if (tag.length <= 19)
tag
else
tag.substring(0, 19)
}
// Toasts
fun Fragment.toast(text: String) = activity.toast(text)
fun Fragment.toast(@StringRes resId: Int) = activity.toast(resId)
fun Context.toast(text: String) = Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
fun Context.toast(@StringRes resId: Int) = Toast.makeText(this, resId, Toast.LENGTH_SHORT).show()
fun Fragment.longToast(text: String) = activity.longToast(text)
fun Fragment.longToast(@StringRes resId: Int) = activity.longToast(resId)
fun Context.longToast(text: String) = Toast.makeText(this, text, Toast.LENGTH_LONG).show()
fun Context.longToast(@StringRes resId: Int) = Toast.makeText(this, resId, Toast.LENGTH_LONG).show()
// SnackBars
inline fun Activity.snackBar(
message: String,
view: View = findViewById(android.R.id.content)
) = view.snackBar(message)
inline fun Activity.snackBar(
@StringRes resId: Int,
view: View = findViewById(android.R.id.content)
) = view.snackBar(resId)
inline fun Activity.longSnackBar(
message: String,
view: View = findViewById(android.R.id.content)
) = view.longSnackBar(message)
inline fun Activity.longSnackBar(
@StringRes resId: Int,
view: View = findViewById(android.R.id.content)
) = view.longSnackBar(resId)
inline fun Activity.snackBar(
message: String,
view: View = findViewById(android.R.id.content),
actionText: CharSequence,
noinline action: (View) -> Unit
) = view.snackBar(message, actionText, action)
inline fun Activity.snackBar(
@StringRes resId: Int,
view: View = findViewById(android.R.id.content),
actionText: CharSequence,
noinline action: (View) -> Unit
) = view.snackBar(resId, actionText, action)
inline fun Activity.CharSequence(
message: String,
view: View = findViewById(android.R.id.content),
actionText: CharSequence,
noinline action: (View) -> Unit
) = view.longSnackBar(message, actionText, action)
inline fun Activity.longSnackBar(
@StringRes resId: Int,
view: View = findViewById(android.R.id.content),
actionText: CharSequence,
noinline action: (View) -> Unit
) = view.longSnackBar(resId, actionText, action)
inline fun View.snackBar(message: String) = Snackbar.make(this, message, Snackbar.LENGTH_SHORT).show()
inline fun View.snackBar(@StringRes resId: Int) = Snackbar.make(this, resId, Snackbar.LENGTH_SHORT).show()
inline fun View.longSnackBar(message: String) = Snackbar.make(this, message, Snackbar.LENGTH_LONG).show()
inline fun View.longSnackBar(@StringRes resId: Int) = Snackbar.make(this, resId, Snackbar.LENGTH_LONG).show()
inline fun View.snackBar(
message: CharSequence,
actionText: CharSequence,
noinline action: (View) -> Unit
) = Snackbar.make(this, message, Snackbar.LENGTH_SHORT)
.setAction(actionText, action)
.show()
inline fun View.longSnackBar(
message: CharSequence,
actionText: CharSequence,
noinline action: (View) -> Unit
) = Snackbar.make(this, message, Snackbar.LENGTH_LONG)
.setAction(actionText, action)
.show()
inline fun View.snackBar(
@StringRes resId: Int,
actionText: CharSequence,
noinline action: (View) -> Unit
) = Snackbar.make(this, resId, Snackbar.LENGTH_SHORT)
.setAction(actionText, action)
.show()
inline fun View.longSnackBar(
@StringRes resId: Int,
actionText: CharSequence,
noinline action: (View) -> Unit
) = Snackbar.make(this, resId, Snackbar.LENGTH_LONG)
.setAction(actionText, action)
.show()
// Dimensions
inline fun View.setWidth(width: Int) {
val params = layoutParams
params.width = width
layoutParams = params
}
inline fun View.setHeight(height: Int) {
val params = layoutParams
params.height = height
layoutParams = params
}
inline fun View.setDimensions(width: Int, height: Int) {
val params = layoutParams
params.width = width
params.height = height
layoutParams = params
}
inline fun Activity.screenWidth(): Int {
val metrics: DisplayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
return metrics.widthPixels
}
inline fun Activity.screenHeight(): Int {
val metrics: DisplayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
return metrics.heightPixels
}
inline fun Context.screenWidth(): Int {
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val dm = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(dm)
return dm.widthPixels
}
inline fun Context.screenHeight(): Int {
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val dm = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(dm)
return dm.heightPixels
}
inline fun Context.getStatusBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
// Fragments
inline fun Activity.addFragment(
@IdRes containerViewId: Int,
fragment: Fragment,
noinline func: (FragmentTransaction.() -> FragmentTransaction)? = null
) {
fragmentManager.beginTransaction().apply {
add(containerViewId, fragment)
func?.let { func() }
}.commit()
}
inline fun Activity.addFragment(
@IdRes containerViewId: Int,
fragment: Fragment,
fragmentTag: String,
noinline func: (FragmentTransaction.() -> FragmentTransaction)? = null
) {
fragmentManager.beginTransaction().apply {
add(containerViewId, fragment, fragmentTag)
func?.let { func() }
}.commit()
}
inline fun Activity.replaceFragment(
@IdRes containerViewId: Int,
fragment: Fragment,
noinline func: (FragmentTransaction.() -> FragmentTransaction)? = null
) {
fragmentManager.beginTransaction().apply {
replace(containerViewId, fragment)
func?.let { func() }
}.commit()
}
inline fun Activity.replaceFragment(
@IdRes containerViewId: Int,
fragment: Fragment,
fragmentTag: String,
noinline func: (FragmentTransaction.() -> FragmentTransaction)? = null
) {
fragmentManager.beginTransaction().apply {
replace(containerViewId, fragment, fragmentTag)
func?.let { func() }
}.commit()
}
// Dialogs
inline fun Context.progressDialog(
title: String? = null,
message: String? = null,
indeterminate: Boolean = true,
noinline init: (ProgressDialog.() -> Unit)? = null
): ProgressDialog = ProgressDialog(this).apply {
isIndeterminate = indeterminate
if (!indeterminate) setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
title?.let { setTitle(title) }
message?.let { setMessage(message) }
init?.let { init() }
}
inline fun Context.alertDialog(
title: CharSequence? = null,
message: CharSequence? = null,
positiveText: CharSequence? = null,
noinline positiveEvent: (() -> Unit)? = null,
negativeText: CharSequence? = null,
noinline negativeEvent: (() -> Unit)? = null
): AlertDialog.Builder = AlertDialog.Builder(this).apply {
title?.let { setTitle(title) }
message?.let { setMessage(message) }
positiveText?.let {
setPositiveButton(positiveText) { _, _ ->
positiveEvent?.let { positiveEvent() }
}
}
negativeText?.let {
setNegativeButton(negativeText) { _, _ ->
negativeEvent?.let { negativeEvent() }
}
}
}
inline fun Context.selectorList(
title: CharSequence? = null,
items: Array<CharSequence>,
noinline onClick: ((Int) -> Unit)? = null
): AlertDialog.Builder = AlertDialog.Builder(this).apply {
title?.let { setTitle(title) }
setItems(items) { _, item ->
onClick?.let { onClick(item) }
}
}
inline fun Context.selectorSingle(
title: CharSequence? = null,
items: Array<CharSequence>,
checkedItem: Int = -1,
noinline onClick: ((Int) -> Unit)? = null
): AlertDialog.Builder = AlertDialog.Builder(this).apply {
title?.let { setTitle(title) }
setSingleChoiceItems(items, checkedItem) { _, item ->
onClick?.let { onClick(item) }
}
}
inline fun Context.selectorMultiple(
title: CharSequence? = null,
items: Array<CharSequence>,
checkedItems: BooleanArray,
noinline onClick: ((Int, Boolean) -> Unit)? = null
) = AlertDialog.Builder(this).apply {
title?.let { setTitle(title) }
setMultiChoiceItems(items, checkedItems) { _, item, isChecked ->
onClick?.let { onClick(item, isChecked) }
}
}
// Views visibility
inline fun View.visible() {
visibility = View.VISIBLE
}
inline fun View.invisible() {
visibility = View.INVISIBLE
}
inline fun View.gone() {
visibility = View.GONE
}
@TargetApi(21)
inline fun View.exitReveal(noinline func: (() -> Unit)? = null){
if (isLollipopOrLater()){
val cx = measuredWidth / 2
val cy = measuredHeight / 2
val initialRadius = width / 2
val anim = ViewAnimationUtils.createCircularReveal(this, cx, cy, initialRadius.toFloat(), 0f)
anim.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
if(func != null) func()
}
})
anim.start()
}
else{
if(func != null) func()
}
}
@TargetApi(21)
inline fun View.enterReveal(noinline func: (() -> Unit)? = null){
if(isLollipopOrLater()){
val cx = measuredWidth / 2
val cy = measuredHeight / 2
val finalRadius = Math.max(width, height) / 2
val anim = ViewAnimationUtils.createCircularReveal(this, cx, cy, 0f, finalRadius.toFloat())
anim.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
if(func != null) func()
}
})
visible()
anim.start()
}
else{
visible()
}
}
inline fun Context.inflate(
res: Int,
parent: ViewGroup? = null,
attachToRoot: Boolean = false)
: View = LayoutInflater.from(this).inflate(res, parent, attachToRoot)
// Keyboard utils
inline fun Activity.hideSoftInput() {
var view = currentFocus
if (view == null) view = View(this)
hideSoftInput(view)
}
inline fun Context.hideSoftInput(view: View) {
val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
inline fun Context.showSoftInput(editText: EditText? = null) {
if (editText != null){
editText.isFocusable = true
editText.isFocusableInTouchMode = true
editText.requestFocus()
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(editText, 0)
}
else {
toggleSoftInput()
}
}
inline fun Context.toggleSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
}
// Strings
inline fun String.isValidEmail(): Boolean {
val EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
val pattern = Pattern.compile(EMAIL_PATTERN)
return pattern.matcher(this).matches()
}
// Network
inline fun Context.isNetworkConnected(): Boolean {
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork = connectivityManager.activeNetworkInfo
return activeNetwork != null && activeNetwork.isConnectedOrConnecting
}
// Storage
inline fun isExternalStorageWritable(): Boolean = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
// Collections
inline fun <T> Collection<T>.showValues() {
forEach { debug(it) }
}
// Check API Version
inline fun isJellyBeanOrLater(): Boolean = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN
inline fun isLollipopOrLater(): Boolean = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP
inline fun isNougatOrLater(): Boolean = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N
// Math
inline fun Int.toAbsoluteValue() = Math.abs(this)
inline fun Float.pxToDp(): Float {
val densityDpi = Resources.getSystem().displayMetrics.densityDpi.toFloat()
return this / (densityDpi / 160f)
}
inline fun Float.dpToPx(): Int {
val density = Resources.getSystem().displayMetrics.density
return Math.round(this * density)
}
// Some other stuff
inline val Context.notificationManager: NotificationManager
get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@SuppressLint("all")
inline fun getDeviceId(context: Context)
: String = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
inline val Context.defaultSharedPreferences: SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(this)
inline val Fragment.defaultSharedPreferences: SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(activity)
inline fun <T: Fragment> T.withArguments(vararg params: Pair<String, Any>): T {
arguments = bundleOf(*params)
return this
}
inline fun bundleOf(vararg params: Pair<String, Any>): Bundle {
val b = Bundle()
for ((k, v) in params) {
when (v) {
is Boolean -> b.putBoolean(k, v)
is Byte -> b.putByte(k, v)
is Char -> b.putChar(k, v)
is Short -> b.putShort(k, v)
is Int -> b.putInt(k, v)
is Long -> b.putLong(k, v)
is Float -> b.putFloat(k, v)
is Double -> b.putDouble(k, v)
is String -> b.putString(k, v)
is CharSequence -> b.putCharSequence(k, v)
is Parcelable -> b.putParcelable(k, v)
is Serializable -> b.putSerializable(k, v)
is BooleanArray -> b.putBooleanArray(k, v)
is ByteArray -> b.putByteArray(k, v)
is CharArray -> b.putCharArray(k, v)
is DoubleArray -> b.putDoubleArray(k, v)
is FloatArray -> b.putFloatArray(k, v)
is IntArray -> b.putIntArray(k, v)
is LongArray -> b.putLongArray(k, v)
is Array<*> -> {
@Suppress("UNCHECKED_CAST")
when {
v.isArrayOf<Parcelable>() -> b.putParcelableArray(k, v as Array<out Parcelable>)
v.isArrayOf<CharSequence>() -> b.putCharSequenceArray(k, v as Array<out CharSequence>)
v.isArrayOf<String>() -> b.putStringArray(k, v as Array<out String>)
else -> Log.e("Error in bundle of", "the argument passed is not valid")
}
}
is ShortArray -> b.putShortArray(k, v)
is Bundle -> b.putBundle(k, v)
else -> Log.e("Error in bundle of", "the argument passed is not valid")
}
}
return b
}
inline fun Context.email(email: String, subject: String = "", text: String = ""): Boolean {
val intent = Intent(Intent.ACTION_SENDTO)
intent.data = Uri.parse("mailto:")
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
if (subject.isNotEmpty())
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
if (text.isNotEmpty())
intent.putExtra(Intent.EXTRA_TEXT, text)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
return true
}
return false
}
inline fun Fragment.makeCall(number: String): Boolean = activity.makeCall(number)
@SuppressLint("MissingPermission")
inline fun Context.makeCall(number: String): Boolean {
try {
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$number"))
startActivity(intent)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
inline fun Fragment.sendSMS(number: String, text: String = ""): Boolean = activity.sendSMS(number, text)
inline fun Context.sendSMS(number: String, text: String = ""): Boolean {
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("sms:$number"))
intent.putExtra("sms_body", text)
startActivity(intent)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
inline fun Fragment.browse(url: String = "about:blank", newTask: Boolean = false) = activity.browse(url, newTask)
inline fun Context.browse(url: String = "about:blank", newTask: Boolean = false): Boolean {
try {
val intent = Intent(Intent.ACTION_VIEW)
if(url!="about:blank" && (!url.contains("https://") || !url.contains("http://"))){
intent.data = Uri.parse("http://" + url)
}
else{
intent.data = Uri.parse(url)
}
if (newTask) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(intent)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
inline fun Intent.clearTask(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) }
inline fun Intent.clearTop(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) }
inline fun Intent.excludeFromRecents(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) }
inline fun Intent.multipleTask(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) }
inline fun Intent.newTask(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
inline fun Intent.noAnimation(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION) }
inline fun Intent.noHistory(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY) }
inline fun Intent.singleTop(): Intent = apply { addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) }
inline fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit) {
val editor = edit()
editor.func()
editor.apply()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment