diff options
author | Allan Wang <me@allanwang.ca> | 2017-07-18 20:16:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-18 20:16:23 -0700 |
commit | 8f2b5ac043f47cc44f43c3788d1377083fb339a2 (patch) | |
tree | 8f91042414de211cbfe67a76298300884f46a765 /core | |
parent | 4eee8d59c21b2061b9f5fd0e805ca60ab84c3585 (diff) | |
download | kau-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')
26 files changed, 384 insertions, 194 deletions
diff --git a/core/README.md b/core/README.md index db602b6..63313ac 100644 --- a/core/README.md +++ b/core/README.md @@ -86,6 +86,23 @@ There is an optional `customize` argument to modify the builder before showing t As mentioned, blank items will be ignored, so feel free to create a bunch of empty lines to facilitate updating the items in the future. +Here is a template xml changelog file: + +```xml +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <!-- + <version title="v"/> + <item text="" /> + --> + + <version title="v0.1" /> + <item text="Initial Changelog" /> + <item text="" /> +</resources> +``` + <a name="ripple-canvas"></a> ## Ripple Canvas 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 |