aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-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
-rw-r--r--core/src/main/res/transition/kau_enter_slide_bottom.xml16
-rw-r--r--core/src/main/res/transition/kau_enter_slide_top.xml16
-rw-r--r--core/src/main/res/transition/kau_exit_slide_bottom.xml23
-rw-r--r--core/src/main/res/transition/kau_exit_slide_top.xml23
-rw-r--r--core/src/main/res/values/attr.xml11
-rw-r--r--core/src/main/res/values/dimens.xml1
-rw-r--r--core/src/main/res/values/ids.xml36
-rw-r--r--core/src/main/res/values/strings.xml14
-rw-r--r--core/src/main/res/values/strings_commons.xml27
-rw-r--r--core/src/main/res/values/styles_animations.xml35
-rw-r--r--core/src/main/res/xml/kau_changelog.xml14
25 files changed, 367 insertions, 194 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
diff --git a/core/src/main/res/transition/kau_enter_slide_bottom.xml b/core/src/main/res/transition/kau_enter_slide_bottom.xml
index 7eb2097..575e189 100644
--- a/core/src/main/res/transition/kau_enter_slide_bottom.xml
+++ b/core/src/main/res/transition/kau_enter_slide_bottom.xml
@@ -1,20 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 2015 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="together"
diff --git a/core/src/main/res/transition/kau_enter_slide_top.xml b/core/src/main/res/transition/kau_enter_slide_top.xml
index 0089b84..8cf613b 100644
--- a/core/src/main/res/transition/kau_enter_slide_top.xml
+++ b/core/src/main/res/transition/kau_enter_slide_top.xml
@@ -1,20 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 2015 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="together"
diff --git a/core/src/main/res/transition/kau_exit_slide_bottom.xml b/core/src/main/res/transition/kau_exit_slide_bottom.xml
new file mode 100644
index 0000000..e0967ec
--- /dev/null
+++ b/core/src/main/res/transition/kau_exit_slide_bottom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<transitionSet
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionOrdering="together"
+ android:interpolator="@android:interpolator/fast_out_linear_in">
+
+ <slide
+ android:slideEdge="bottom"
+ android:duration="400">
+ <targets>
+ <target android:excludeId="@android:id/navigationBarBackground" />
+ <target android:excludeId="@android:id/statusBarBackground" />
+ </targets>
+ </slide>
+
+ <fade android:duration="400">
+ <targets>
+ <target android:targetId="@android:id/navigationBarBackground" />
+ <target android:targetId="@android:id/statusBarBackground" />
+ </targets>
+ </fade>
+
+</transitionSet>
diff --git a/core/src/main/res/transition/kau_exit_slide_top.xml b/core/src/main/res/transition/kau_exit_slide_top.xml
new file mode 100644
index 0000000..a9849c0
--- /dev/null
+++ b/core/src/main/res/transition/kau_exit_slide_top.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<transitionSet
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionOrdering="together"
+ android:interpolator="@android:interpolator/fast_out_linear_in">
+
+ <slide
+ android:slideEdge="top"
+ android:duration="400">
+ <targets>
+ <target android:excludeId="@android:id/navigationBarBackground" />
+ <target android:excludeId="@android:id/statusBarBackground" />
+ </targets>
+ </slide>
+
+ <fade android:duration="400">
+ <targets>
+ <target android:targetId="@android:id/navigationBarBackground" />
+ <target android:targetId="@android:id/statusBarBackground" />
+ </targets>
+ </fade>
+
+</transitionSet>
diff --git a/core/src/main/res/values/attr.xml b/core/src/main/res/values/attr.xml
new file mode 100644
index 0000000..f02c219
--- /dev/null
+++ b/core/src/main/res/values/attr.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName">
+ <declare-styleable name="MeasureSpecDelegate">
+ <attr format="float" name="relativeWidth"/>
+ <attr format="float" name="relativeWidthToParent"/>
+ <attr format="float" name="postRelativeWidth"/>
+ <attr format="float" name="relativeHeight"/>
+ <attr format="float" name="relativeHeightToParent"/>
+ <attr format="float" name="postRelativeHeight"/>
+ </declare-styleable>
+</resources>
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index a459443..b7c237a 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -13,6 +13,7 @@
<dimen name="kau_status_bar_height">24dp</dimen>
<dimen name="kau_drag_dismiss_distance">112dp</dimen> <!-- 2 * ?android:actionBarSize -->
+ <dimen name="kau_drag_dismiss_distance_large">168dp</dimen> <!-- 3 * ?android:actionBarSize -->
<dimen name="kau_spacing_normal">8dp</dimen>
<dimen name="kau_spacing_micro">4dp</dimen>
diff --git a/core/src/main/res/values/ids.xml b/core/src/main/res/values/ids.xml
index 0b4322c..003e8a7 100644
--- a/core/src/main/res/values/ids.xml
+++ b/core/src/main/res/values/ids.xml
@@ -1,19 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
- <item name="kau_item_account" type="id" />
- <item name="kau_item_pref_header" type="id" />
- <item name="kau_item_pref_text" type="id" />
- <item name="kau_item_pref_checkbox" type="id" />
- <item name="kau_item_pref_seekbar" type="id" />
- <item name="kau_item_pref_color_picker" type="id" />
- <item name="kau_item_pref_sub_item" type="id" />
- <item name="kau_item_pref_plain_text" type="id" />
- <item name="kau_item_search" type="id" />
- <item name="kau_item_cutout" type="id" />
- <item name="kau_item_header_big_margin_top" type="id" />
- <item name="kau_item_card" type="id" />
- <item name="kau_item_library" type="id" />
- <item name="kau_item_about_main" type="id" />
- <item name="kau_pref_inner_content" type="id" />
- <item name="kau_pref_lower_content" type="id" />
-</resources> \ No newline at end of file
+ <item name="kau_item_about_main" type="id"/>
+ <item name="kau_item_account" type="id"/>
+ <item name="kau_item_card" type="id"/>
+ <item name="kau_item_cutout" type="id"/>
+ <item name="kau_item_header_big_margin_top" type="id"/>
+ <item name="kau_item_library" type="id"/>
+ <item name="kau_item_pref_checkbox" type="id"/>
+ <item name="kau_item_pref_color_picker" type="id"/>
+ <item name="kau_item_pref_header" type="id"/>
+ <item name="kau_item_pref_plain_text" type="id"/>
+ <item name="kau_item_pref_seekbar" type="id"/>
+ <item name="kau_item_pref_sub_item" type="id"/>
+ <item name="kau_item_pref_text" type="id"/>
+ <item name="kau_item_search" type="id"/>
+ <item name="kau_pref_inner_content" type="id"/>
+ <item name="kau_pref_lower_content" type="id"/>
+</resources>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 5ea5a23..7ad6e38 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -1,15 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
- <string name="kau_u2022">•</string>
+ <string name="kau_about_libraries_intro">This app would not be possible without the following great libraries.</string>
<string name="kau_color_picker">Color Picker</string>
-
+ <string name="kau_dependencies_used">Dependencies Used</string>
+ <string name="kau_kpref_title_placeholder">Title Placeholder</string>
+ <string name="kau_md_color_palette">Color Palette</string>
<!--Color Picker-->
<string name="kau_md_custom">Custom</string>
<string name="kau_md_presets">Presets</string>
- <string name="kau_md_color_palette">Color Palette</string>
-
- <string name="kau_kpref_title_placeholder">Title Placeholder</string>
<string name="kau_pref_icon">Pref Icon</string>
-
- <string name="kau_about_libraries_intro">This app would not be possible without the following great libraries.</string>
- <string name="kau_dependencies_used">Dependencies Used</string>
+ <string name="kau_u2022">•</string>
</resources>
diff --git a/core/src/main/res/values/strings_commons.xml b/core/src/main/res/values/strings_commons.xml
index 389b8a2..560a478 100644
--- a/core/src/main/res/values/strings_commons.xml
+++ b/core/src/main/res/values/strings_commons.xml
@@ -1,8 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
A collection of common string values
Most resources are verbatim and x represents a formatted item
-->
-
<resources>
<string name="kau_about_app">About App</string>
<string name="kau_about_x">About %s</string>
@@ -13,6 +13,7 @@ Most resources are verbatim and x represents a formatted item
<string name="kau_changelog">Changelog</string>
<string name="kau_close">Close</string>
<string name="kau_contact_us">Contact Us</string>
+ <string name="kau_copy">Copy</string>
<string name="kau_custom">Custom</string>
<string name="kau_dark">Dark</string>
<string name="kau_default">Default</string>
@@ -38,8 +39,6 @@ Most resources are verbatim and x represents a formatted item
<string name="kau_no_results_found">No Results Found</string>
<string name="kau_none">None</string>
<string name="kau_ok">@android:string/ok</string>
- <string name="kau_one_day">1 day</string>
- <string name="kau_one_hour">1 hour</string>
<string name="kau_play_store">Play Store</string>
<string name="kau_rate">Rate</string>
<string name="kau_report_bug">Report A Bug</string>
@@ -48,13 +47,25 @@ Most resources are verbatim and x represents a formatted item
<string name="kau_send_via">Send via</string>
<string name="kau_settings">Settings</string>
<string name="kau_share">Share</string>
+ <string name="kau_text_copied">Text copied to clipboard.</string>
<string name="kau_thank_you">Thank You</string>
<string name="kau_uh_oh">Uh Oh</string>
<string name="kau_warning">Warning</string>
- <string name="kau_x_days">%d days</string>
- <string name="kau_x_hours">%d hours</string>
- <string name="kau_x_minutes">%d minutes</string>
+ <plurals name="kau_x_days">
+ <item quantity="one">%d day</item>
+ <item quantity="other">%d days</item>
+ </plurals>
+ <plurals name="kau_x_hours">
+ <item quantity="one">%d hour</item>
+ <item quantity="other">%d hours</item>
+ </plurals>
+ <plurals name="kau_x_minutes">
+ <item quantity="one">%d minute</item>
+ <item quantity="other">%d minutes</item>
+ </plurals>
+ <plurals name="kau_x_seconds">
+ <item quantity="one">%d second</item>
+ <item quantity="other">%d seconds</item>
+ </plurals>
<string name="kau_yes">Yes</string>
- <string name="kau_text_copied">Text copied to clipboard.</string>
- <string name="kau_copy">Copy</string>
</resources>
diff --git a/core/src/main/res/values/styles_animations.xml b/core/src/main/res/values/styles_animations.xml
index a991132..fc872bd 100644
--- a/core/src/main/res/values/styles_animations.xml
+++ b/core/src/main/res/values/styles_animations.xml
@@ -1,4 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
+ <style name="KauFadeIn" parent="@android:style/Animation.Activity">
+ <item name="android:activityOpenEnterAnimation">@anim/kau_fade_in</item>
+ <item name="android:activityCloseEnterAnimation">@anim/kau_fade_in</item>
+ <item name="android:taskOpenEnterAnimation">@anim/kau_fade_in</item>
+ <item name="android:taskCloseEnterAnimation">@anim/kau_fade_in</item>
+ <item name="android:taskToFrontEnterAnimation">@anim/kau_fade_in</item>
+ <item name="android:windowEnterAnimation">@anim/kau_fade_in</item>
+ </style>
+
+ <style name="KauFadeInFadeOut" parent="@style/KauFadeIn">
+ <item name="android:activityOpenExitAnimation">@anim/kau_fade_out</item>
+ <item name="android:activityCloseExitAnimation">@anim/kau_fade_out</item>
+ <item name="android:taskOpenExitAnimation">@anim/kau_fade_out</item>
+ <item name="android:taskCloseExitAnimation">@anim/kau_fade_out</item>
+ <item name="android:taskToFrontExitAnimation">@anim/kau_fade_out</item>
+ <item name="android:windowExitAnimation">@anim/kau_fade_out</item>
+ </style>
<style name="KauSlideIn" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/kau_slide_in_right</item>
@@ -9,15 +27,6 @@
<item name="android:windowEnterAnimation">@anim/kau_slide_in_right</item>
</style>
- <style name="KauSlideInSlideOut" parent="@style/KauSlideIn">
- <item name="android:activityOpenExitAnimation">@anim/kau_slide_out_right</item>
- <item name="android:activityCloseExitAnimation">@anim/kau_slide_out_right</item>
- <item name="android:taskOpenExitAnimation">@anim/kau_slide_out_right</item>
- <item name="android:taskCloseExitAnimation">@anim/kau_slide_out_right</item>
- <item name="android:taskToFrontExitAnimation">@anim/kau_slide_out_right</item>
- <item name="android:windowExitAnimation">@anim/kau_slide_out_right</item>
- </style>
-
<style name="KauSlideInFadeOut" parent="@style/KauSlideIn">
<item name="android:activityOpenExitAnimation">@anim/kau_fade_out</item>
<item name="android:activityCloseExitAnimation">@anim/kau_fade_out</item>
@@ -27,4 +36,12 @@
<item name="android:windowExitAnimation">@anim/kau_fade_out</item>
</style>
+ <style name="KauSlideInSlideOut" parent="@style/KauSlideIn">
+ <item name="android:activityOpenExitAnimation">@anim/kau_slide_out_right</item>
+ <item name="android:activityCloseExitAnimation">@anim/kau_slide_out_right</item>
+ <item name="android:taskOpenExitAnimation">@anim/kau_slide_out_right</item>
+ <item name="android:taskCloseExitAnimation">@anim/kau_slide_out_right</item>
+ <item name="android:taskToFrontExitAnimation">@anim/kau_slide_out_right</item>
+ <item name="android:windowExitAnimation">@anim/kau_slide_out_right</item>
+ </style>
</resources>
diff --git a/core/src/main/res/xml/kau_changelog.xml b/core/src/main/res/xml/kau_changelog.xml
deleted file mode 100644
index e570995..0000000
--- a/core/src/main/res/xml/kau_changelog.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <!--This is a template-->
-
- <!--
- <version title="v"/>
- <item text="" />
- -->
-
- <version title="v0.1" />
- <item text="Initial Changelog" />
- <item text="" />
-</resources> \ No newline at end of file