aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-07-18 20:16:23 -0700
committerGitHub <noreply@github.com>2017-07-18 20:16:23 -0700
commit8f2b5ac043f47cc44f43c3788d1377083fb339a2 (patch)
tree8f91042414de211cbfe67a76298300884f46a765 /core/src/main/kotlin
parent4eee8d59c21b2061b9f5fd0e805ca60ab84c3585 (diff)
downloadkau-8f2b5ac043f47cc44f43c3788d1377083fb339a2.tar.gz
kau-8f2b5ac043f47cc44f43c3788d1377083fb339a2.tar.bz2
kau-8f2b5ac043f47cc44f43c3788d1377083fb339a2.zip
Dev 2.1 (#8)
* Rewrite animation interfaces * Update changelog * Add scale factor for slide * Remove margins in iitems and replace with decorators * Remove mutable list * Switch cardiitem to use lambdas for click * status * Utils update and imagepicker fixes * Remove stringholder * Add fade in fade out * Increment about version * Rename fromedge to direction in javadocs * More logging * Add logging and docs * Make card icons visible * Update email builder and icon padding * Create elastic recycler activity * Fix card iitem * Add lint check and plurals * Inline all the things * Format and sort xml * Update dependencies and increment version
Diffstat (limited to 'core/src/main/kotlin')
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt6
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt5
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt6
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt107
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt6
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt2
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt23
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Either.kt32
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt16
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt18
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt25
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/StringHolder.kt22
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt16
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt61
14 files changed, 240 insertions, 105 deletions
diff --git a/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt b/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt
index b03a620..88a0945 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt
@@ -40,9 +40,9 @@ class EmailBuilder(val email: String, val subject: String) {
if (deviceDetails) {
val deviceItems = mutableMapOf(
"OS Version" to "${System.getProperty("os.version")} (${Build.VERSION.INCREMENTAL})",
- "OS API Level" to Build.DEVICE,
- "Manufacturer" to Build.MANUFACTURER,
- "Model (and Product)" to "${Build.MODEL} (${Build.PRODUCT})",
+ "OS SDK" to Build.VERSION.SDK_INT,
+ "Device (Manufacturer)" to "${Build.DEVICE} (${Build.MANUFACTURER})",
+ "Model (Product)" to "${Build.MODEL} (${Build.PRODUCT})",
"Package Installer" to (context.installerPackageName ?: "None")
)
if (context is Activity) {
diff --git a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
index 6f93c9f..d6e17db 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
@@ -18,7 +18,7 @@ internal object PermissionManager {
val pendingResults: MutableList<WeakReference<PermissionResult>> by lazy { mutableListOf<WeakReference<PermissionResult>>() }
operator fun invoke(context: Context, permissions: Array<out String>, callback: (granted: Boolean, deniedPerm: String?) -> Unit) {
- KL.d("Requesting permissions: ${permissions.contentToString()}")
+ KL.d("Permission manager for: ${permissions.contentToString()}")
if (!buildIsMarshmallowAndUp) return callback(true, null)
val missingPermissions = permissions.filter { !context.hasPermission(it) }
if (missingPermissions.isEmpty()) return callback(true, null)
@@ -31,10 +31,12 @@ internal object PermissionManager {
@Synchronized internal fun requestPermissions(context: Context, permissions: Array<out String>) {
val activity = (context as? Activity) ?: throw KauException("Context is not an instance of an activity; cannot request permissions")
+ KL.d("Requesting permissions ${permissions.contentToString()}")
ActivityCompat.requestPermissions(activity, permissions, 1)
}
fun onRequestPermissionsResult(context: Context, permissions: Array<out String>, grantResults: IntArray) {
+ KL.d("On permission result: pending ${pendingResults.size}")
val count = Math.min(permissions.size, grantResults.size)
val iter = pendingResults.iterator()
while (iter.hasNext()) {
@@ -53,6 +55,7 @@ internal object PermissionManager {
}
requestPermissions(context, action.permissions.toTypedArray())
}
+ KL.d("Post on permission result: pending ${pendingResults.size}")
}
} \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt b/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
index fd43102..36ad52f 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
@@ -9,6 +9,12 @@ import android.content.Context
* Created by Allan Wang on 2017-07-02.
*
* Bindings for the permission manager
+ * This is the only class you need to worry about when using KAU's manager
+ *
+ * MAKE SURE [kauOnRequestPermissionsResult] is added to your activities,
+ * and don't forget to request the permissions in your manifest.
+ * A collection of constants redirecting to the [Manifest.permission] counterparts
+ * are added for your convenience
*/
/**
diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt
new file mode 100644
index 0000000..edc1536
--- /dev/null
+++ b/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt
@@ -0,0 +1,107 @@
+package ca.allanwang.kau.ui.views
+
+import android.content.Context
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.view.View
+import ca.allanwang.kau.R
+import ca.allanwang.kau.utils.parentViewGroup
+
+/**
+ * Created by Allan Wang on 2017-07-14.
+ *
+ * Handles relative sizes for any view
+ */
+interface MeasureSpecContract {
+
+ /**
+ * Width will be calculated as a percentage of the parent
+ * This takes precedence over relativeWidth
+ */
+ var relativeWidthToParent: Float
+ /**
+ * Height will be calculated as a percentage of the parent
+ * This takes precedence over relativeHeight
+ */
+ var relativeHeightToParent: Float
+ /**
+ * Width will be calculated based on the measured height
+ */
+ var relativeWidth: Float
+ /**
+ * Height will be calculated based on the measure width
+ */
+ var relativeHeight: Float
+ /**
+ * Width will be once again calculated from the current measured height
+ * This is the last step
+ */
+ var postRelativeWidth: Float
+ /**
+ * Height will be once again calculated from the current measured width
+ * This is the last step
+ */
+ var postRelativeHeight: Float
+
+ /**
+ * Retrieves relative values from the [AttributeSet]
+ * Call this on init
+ */
+ fun initAttrs(context: Context, attrs: AttributeSet?)
+
+ /**
+ * Calculates the final measure specs
+ * Call this from [View.onMeasure] and send the Pair result as the specs
+ * The pair is of the format (width, height)
+ */
+ fun onMeasure(view: View, widthMeasureSpec: Int, heightMeasureSpec: Int): Pair<Int, Int>
+}
+
+class MeasureSpecDelegate : MeasureSpecContract {
+
+ override var relativeWidth = -1f
+ override var relativeHeight = -1f
+ override var relativeWidthToParent = -1f
+ override var relativeHeightToParent = -1f
+ override var postRelativeWidth: Float = -1f
+ override var postRelativeHeight: Float = -1f
+ private val parentFrame = Rect()
+
+ override fun initAttrs(context: Context, attrs: AttributeSet?) {
+ if (attrs == null) return
+ val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MeasureSpecDelegate)
+ relativeWidth = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeWidth, relativeWidth)
+ relativeHeight = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeHeight, relativeHeight)
+ relativeWidthToParent = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeWidthToParent, relativeWidthToParent)
+ relativeHeightToParent = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeHeightToParent, relativeHeightToParent)
+ postRelativeWidth = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_postRelativeWidth, postRelativeWidth)
+ postRelativeHeight = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_postRelativeHeight, postRelativeHeight)
+ styledAttrs.recycle()
+ }
+
+ override fun onMeasure(view: View, widthMeasureSpec: Int, heightMeasureSpec: Int): Pair<Int, Int> {
+ view.parentViewGroup.getWindowVisibleDisplayFrame(parentFrame)
+ var width = View.MeasureSpec.getSize(widthMeasureSpec).toFloat()
+ var height = View.MeasureSpec.getSize(heightMeasureSpec).toFloat()
+ //first cycle - relative to parent
+ if (relativeHeightToParent > 0)
+ height = relativeHeightToParent * parentFrame.height()
+ if (relativeWidthToParent > 0)
+ width = relativeWidthToParent * parentFrame.width()
+ //second cycle - relative to each other
+ if (relativeHeight > 0)
+ height = relativeHeight * width
+ else if (relativeWidth > 0)
+ width = relativeWidth * height
+ //third cycle - relative to each other
+ if (postRelativeHeight > 0)
+ height = postRelativeHeight * width
+ else if (postRelativeWidth > 0)
+ width = postRelativeWidth * height
+ return Pair(width.measureSpec, height.measureSpec)
+ }
+
+ private val Float.measureSpec: Int
+ get() = View.MeasureSpec.makeMeasureSpec(this.toInt(), View.MeasureSpec.EXACTLY)
+
+}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
index 3b99c46..cd6e089 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
@@ -38,19 +38,19 @@ fun Activity.finishSlideOut() {
overridePendingTransition(R.anim.kau_fade_in, R.anim.kau_slide_out_right_top)
}
-var Activity.navigationBarColor: Int
+inline var Activity.navigationBarColor: Int
get() = if (buildIsLollipopAndUp) window.navigationBarColor else Color.BLACK
set(value) {
if (buildIsLollipopAndUp) window.navigationBarColor = value
}
-var Activity.statusBarColor: Int
+inline var Activity.statusBarColor: Int
get() = if (buildIsLollipopAndUp) window.statusBarColor else Color.BLACK
set(value) {
if (buildIsLollipopAndUp) window.statusBarColor = value
}
-var Activity.statusBarLight: Boolean
+inline var Activity.statusBarLight: Boolean
@SuppressLint("InlinedApi")
get() = if (buildIsMarshmallowAndUp) window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR > 0 else false
@SuppressLint("InlinedApi")
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
index 81bf0d9..50d117c 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
@@ -65,7 +65,7 @@ fun Int.adjustAlpha(factor: Float): Int {
return Color.argb(alpha, Color.red(this), Color.green(this), Color.blue(this))
}
-val Int.isColorTransparent: Boolean
+inline val Int.isColorTransparent: Boolean
get() = Color.alpha(this) != 255
@ColorInt
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
index 3759c75..a8e0715 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
@@ -15,6 +15,7 @@ import android.support.v4.app.ActivityOptionsCompat
import android.support.v4.content.ContextCompat
import android.util.TypedValue
import android.view.View
+import android.view.animation.AnimationUtils
import android.widget.Toast
import ca.allanwang.kau.R
import ca.allanwang.kau.logging.KL
@@ -85,16 +86,18 @@ fun Context.toast(text: String, duration: Int = Toast.LENGTH_LONG) {
}
//Resource retrievers
-fun Context.string(@StringRes id: Int): String = getString(id)
-
-fun Context.string(@StringRes id: Int, fallback: String?): String? = if (id > 0) string(id) else fallback
-fun Context.string(holder: StringHolder?): String? = holder?.getString(this)
-fun Context.color(@ColorRes id: Int): Int = ContextCompat.getColor(this, id)
-fun Context.integer(@IntegerRes id: Int): Int = resources.getInteger(id)
-fun Context.dimen(@DimenRes id: Int): Float = resources.getDimension(id)
-fun Context.dimenPixelSize(@DimenRes id: Int): Int = resources.getDimensionPixelSize(id)
-fun Context.drawable(@DrawableRes id: Int): Drawable = ContextCompat.getDrawable(this, id)
-fun Context.drawable(@DrawableRes id: Int, fallback: Drawable?): Drawable? = if (id > 0) drawable(id) else fallback
+inline fun Context.string(@StringRes id: Int): String = getString(id)
+
+inline fun Context.string(@StringRes id: Int, fallback: String?): String? = if (id > 0) string(id) else fallback
+inline fun Context.color(@ColorRes id: Int): Int = ContextCompat.getColor(this, id)
+inline fun Context.integer(@IntegerRes id: Int): Int = resources.getInteger(id)
+inline fun Context.dimen(@DimenRes id: Int): Float = resources.getDimension(id)
+inline fun Context.dimenPixelSize(@DimenRes id: Int): Int = resources.getDimensionPixelSize(id)
+inline fun Context.drawable(@DrawableRes id: Int): Drawable = ContextCompat.getDrawable(this, id)
+inline fun Context.drawable(@DrawableRes id: Int, fallback: Drawable?): Drawable? = if (id > 0) drawable(id) else fallback
+inline fun Context.interpolator(@InterpolatorRes id: Int) = AnimationUtils.loadInterpolator(this, id)
+inline fun Context.animation(@AnimRes id: Int) = AnimationUtils.loadAnimation(this, id)
+inline fun Context.plural(@PluralsRes id: Int, quantity: Number) = resources.getQuantityString(id, quantity.toInt())
//Attr retrievers
fun Context.resolveColor(@AttrRes attr: Int, fallback: Int = 0): Int {
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Either.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Either.kt
deleted file mode 100644
index dab5810..0000000
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Either.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package ca.allanwang.kau.utils
-
-/**
- * Created by Allan Wang on 2017-06-17.
- *
- * Courtesy of adelnizamutdinov
- *
- * https://github.com/adelnizamutdinov/kotlin-either
- */
-@Suppress("unused")
-sealed class Either<out L, out R>
-
-data class Left<out T>(val value: T) : Either<T, Nothing>()
-data class Right<out T>(val value: T) : Either<Nothing, T>()
-
-inline fun <L, R, T> Either<L, R>.fold(left: (L) -> T, right: (R) -> T): T =
- when (this) {
- is Left -> left(value)
- is Right -> right(value)
- }
-
-inline fun <L, R, T> Either<L, R>.flatMap(f: (R) -> Either<L, T>): Either<L, T> =
- fold({ this as Left }, f)
-
-inline fun <L, R, T> Either<L, R>.map(f: (R) -> T): Either<L, T> =
- flatMap { Right(f(it)) }
-
-val <T> Either<T, *>.isLeft: Boolean
- get() = this is Left<T>
-
-val <T> Either<*, T>.isRight: Boolean
- get() = this is Right<T> \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
index 247bbc7..3783931 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt
@@ -114,21 +114,21 @@ fun <V : View> android.support.v4.app.Fragment.bindOptionalViews(vararg ids: Int
fun <V : View> ViewHolder.bindOptionalViews(vararg ids: Int)
: ReadOnlyProperty<ViewHolder, List<V>> = optional(ids, viewFinder)
-private val View.viewFinder: View.(Int) -> View?
+private inline val View.viewFinder: View.(Int) -> View?
get() = { findViewById(it) }
-private val Activity.viewFinder: Activity.(Int) -> View?
+private inline val Activity.viewFinder: Activity.(Int) -> View?
get() = { findViewById(it) }
-private val Dialog.viewFinder: Dialog.(Int) -> View?
+private inline val Dialog.viewFinder: Dialog.(Int) -> View?
get() = { findViewById(it) }
-private val DialogFragment.viewFinder: DialogFragment.(Int) -> View?
+private inline val DialogFragment.viewFinder: DialogFragment.(Int) -> View?
get() = { dialog.findViewById(it) }
-private val android.support.v4.app.DialogFragment.viewFinder: android.support.v4.app.DialogFragment.(Int) -> View?
+private inline val android.support.v4.app.DialogFragment.viewFinder: android.support.v4.app.DialogFragment.(Int) -> View?
get() = { dialog.findViewById(it) }
-private val Fragment.viewFinder: Fragment.(Int) -> View?
+private inline val Fragment.viewFinder: Fragment.(Int) -> View?
get() = { view.findViewById(it) }
-private val android.support.v4.app.Fragment.viewFinder: android.support.v4.app.Fragment.(Int) -> View?
+private inline val android.support.v4.app.Fragment.viewFinder: android.support.v4.app.Fragment.(Int) -> View?
get() = { view!!.findViewById(it) }
-private val ViewHolder.viewFinder: ViewHolder.(Int) -> View?
+private inline val ViewHolder.viewFinder: ViewHolder.(Int) -> View?
get() = { itemView.findViewById(it) }
private fun viewNotFound(id: Int, desc: KProperty<*>): Nothing =
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
index d04538c..89d64e5 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
@@ -22,22 +22,30 @@ import android.os.Build
}
}
-val buildIsLollipopAndUp: Boolean
+@KauUtils fun Context.isAppEnabled(packageName: String): Boolean {
+ try {
+ return packageManager.getApplicationInfo(packageName, 0).enabled
+ } catch (e: Exception) {
+ return false
+ }
+}
+
+inline val buildIsLollipopAndUp: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
-val buildIsMarshmallowAndUp: Boolean
+inline val buildIsMarshmallowAndUp: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
-val buildIsNougatAndUp: Boolean
+inline val buildIsNougatAndUp: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
const val INSTALLER_GOOGLE_PLAY_VENDING = "com.android.vending"
const val INSTALLER_GOOGLE_PLAY_FEEDBACK = "com.google.android.feedback"
-val Context.installerPackageName: String?
+inline val Context.installerPackageName: String?
get() = packageManager.getInstallerPackageName(packageName)
-val Context.isFromGooglePlay: Boolean
+inline val Context.isFromGooglePlay: Boolean
get() {
val installer = installerPackageName
return arrayOf(INSTALLER_GOOGLE_PLAY_FEEDBACK, INSTALLER_GOOGLE_PLAY_VENDING).any { it == installer }
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt
new file mode 100644
index 0000000..f80c85e
--- /dev/null
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt
@@ -0,0 +1,25 @@
+package ca.allanwang.kau.utils
+
+import android.graphics.Rect
+import android.support.v7.widget.RecyclerView
+import android.view.View
+
+/**
+ * Created by Allan Wang on 2017-07-11.
+ */
+fun RecyclerView.withMarginDecoration(sizeDp: Int, edgeFlags: Int) {
+ addItemDecoration(MarginItemDecoration(sizeDp, edgeFlags))
+}
+
+class MarginItemDecoration(sizeDp: Int, val edgeFlags: Int) : RecyclerView.ItemDecoration() {
+
+ val sizePx = sizeDp.dpToPx
+
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ super.getItemOffsets(outRect, view, parent, state)
+ if (edgeFlags and KAU_LEFT > 0) outRect.left += sizePx
+ if (edgeFlags and KAU_TOP > 0) outRect.top += sizePx
+ if (edgeFlags and KAU_RIGHT > 0) outRect.right += sizePx
+ if (edgeFlags and KAU_BOTTOM > 0) outRect.bottom += sizePx
+ }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/StringHolder.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/StringHolder.kt
deleted file mode 100644
index e70a2d1..0000000
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/StringHolder.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package ca.allanwang.kau.utils
-
-import android.content.Context
-import android.support.annotation.StringRes
-
-/**
- * Created by Allan Wang on 2017-06-08.
- */
-class StringHolder {
- var text: String? = null
- var textRes: Int = 0
-
- constructor(@StringRes textRes: Int) {
- this.textRes = textRes
- }
-
- constructor(text: String) {
- this.text = text
- }
-
- fun getString(context: Context) = context.string(textRes, text)
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
index a2043db..e8f385a 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
@@ -26,16 +26,16 @@ import java.text.DecimalFormat
@DslMarker
annotation class KauUtils
-@KauUtils val Float.dpToPx: Float
+@KauUtils inline val Float.dpToPx: Float
get() = this * Resources.getSystem().displayMetrics.density
-@KauUtils val Int.dpToPx: Int
+@KauUtils inline val Int.dpToPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
-@KauUtils val Float.pxToDp: Float
+@KauUtils inline val Float.pxToDp: Float
get() = this / Resources.getSystem().displayMetrics.density
-@KauUtils val Int.pxToDp: Int
+@KauUtils inline val Int.pxToDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
/**
@@ -52,11 +52,9 @@ annotation class KauUtils
*/
@KauUtils fun Context.minuteToText(minutes: Long): String = with(minutes) {
if (this < 0L) string(R.string.kau_none)
- else if (this == 60L) string(R.string.kau_one_hour)
- else if (this == 1440L) string(R.string.kau_one_day)
- else if (this % 1440L == 0L) String.format(string(R.string.kau_x_days), this / 1440L)
- else if (this % 60L == 0L) String.format(string(R.string.kau_x_hours), this / 60L)
- else String.format(string(R.string.kau_x_minutes), this)
+ else if (this % 1440L == 0L) plural(R.plurals.kau_x_days, this / 1440L)
+ else if (this % 60L == 0L) plural(R.plurals.kau_x_hours, this / 60L)
+ else plural(R.plurals.kau_x_minutes, this)
}
@KauUtils fun Number.round(@IntRange(from = 1L) decimalCount: Int): String {
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
index 53d6d05..59ae204 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
@@ -1,9 +1,12 @@
+@file:Suppress("NOTHING_TO_INLINE")
+
package ca.allanwang.kau.utils
+import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
-import android.graphics.Rect
import android.support.annotation.ColorInt
+import android.support.annotation.ColorRes
import android.support.annotation.StringRes
import android.support.annotation.TransitionRes
import android.support.design.widget.FloatingActionButton
@@ -58,6 +61,8 @@ import com.mikepenz.iconics.typeface.IIcon
@KauUtils inline val View.isGone: Boolean get() = visibility == View.GONE
+@KauUtils inline fun View.setBackgroundColorRes(@ColorRes color: Int) = setBackgroundColor(context.color(color))
+
fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: Snackbar.() -> Unit = {}): Snackbar {
val snackbar = Snackbar.make(this, text, duration)
snackbar.builder()
@@ -85,12 +90,24 @@ fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show()
@KauUtils fun ViewGroup.inflate(layoutId: Int, attachToRoot: Boolean = false): View = LayoutInflater.from(context).inflate(layoutId, this, attachToRoot)
+/**
+ * Set left margin to a value in px
+ */
@KauUtils fun View.updateLeftMargin(margin: Int) = updateMargins(margin, KAU_LEFT)
+/**
+ * Set top margin to a value in px
+ */
@KauUtils fun View.updateTopMargin(margin: Int) = updateMargins(margin, KAU_TOP)
+/**
+ * Set right margin to a value in px
+ */
@KauUtils fun View.updateRightMargin(margin: Int) = updateMargins(margin, KAU_RIGHT)
+/**
+ * Set bottom margin to a value in px
+ */
@KauUtils fun View.updateBottomMargin(margin: Int) = updateMargins(margin, KAU_BOTTOM)
@KauUtils private fun View.updateMargins(margin: Int, flag: Int) {
@@ -130,18 +147,11 @@ fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show()
background = createSimpleRippleDrawable(foregroundColor, backgroundColor)
}
-@KauUtils val View.parentViewGroup: ViewGroup get() = parent as ViewGroup
-
-@KauUtils val View.parentVisibleHeight: Int
- get() {
- val r = Rect()
- parentViewGroup.getWindowVisibleDisplayFrame(r)
- return r.height()
- }
+@KauUtils inline val View.parentViewGroup: ViewGroup get() = parent as ViewGroup
-val EditText.value: String get() = text.toString().trim()
+inline val EditText.value: String get() = text.toString().trim()
-val TextInputEditText.value: String get() = text.toString().trim()
+inline val TextInputEditText.value: String get() = text.toString().trim()
/**
* Generates a recycler view with match parent and a linearlayoutmanager, since it's so commonly used
@@ -153,4 +163,33 @@ fun Context.fullLinearRecycler(rvAdapter: RecyclerView.Adapter<*>? = null, confi
if (rvAdapter != null) adapter = rvAdapter
configs()
}
+}
+
+/**
+ * Animate a transition for a FloatinActionButton
+ * If it is not shown, the action will be invoked directly and the fab will be shown
+ * If it is already shown, scaling and alpha animations will be added to the action
+ */
+inline fun FloatingActionButton.transition(crossinline action: FloatingActionButton.() -> Unit) {
+ if (isHidden) {
+ action()
+ show()
+ } else {
+ var transitioned = false
+ ValueAnimator.ofFloat(1.0f, 0.0f, 1.0f).apply {
+ duration = 500L
+ addUpdateListener {
+ val x = it.animatedValue as Float
+ val scale = x * 0.3f + 0.7f
+ scaleX = scale
+ scaleY = scale
+ imageAlpha = (x * 255).toInt()
+ if (it.animatedFraction > 0.5f && !transitioned) {
+ transitioned = true
+ action()
+ }
+ }
+ start()
+ }
+ }
} \ No newline at end of file