-
Notifications
You must be signed in to change notification settings - Fork 6
Utility extensions for master-koin #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4cb1f4b
b258ec0
cb0f2bd
ec49c7c
2f345a7
9b71ae8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.rootstrap.android.ui.custom | ||
|
|
||
| import android.graphics.Paint | ||
| import android.graphics.Typeface | ||
| import android.text.TextPaint | ||
| import android.text.style.TypefaceSpan | ||
|
|
||
| /** | ||
| * Allows to apply a custom font in an spannableString | ||
| * | ||
| * Taken from https://stackoverflow.com/questions/10675070/multiple-typeface-in-single-textview | ||
| * with slightly modifications | ||
| */ | ||
| class CustomTypefaceSpan(private val newType: Typeface) : TypefaceSpan("") { | ||
|
|
||
| override fun updateDrawState(ds: TextPaint) { | ||
| applyCustomTypeFace(ds, newType) | ||
| } | ||
|
|
||
| override fun updateMeasureState(paint: TextPaint) { | ||
| applyCustomTypeFace(paint, newType) | ||
| } | ||
|
|
||
| companion object { | ||
|
|
||
| private const val ITALIC_SKEW_FACTOR = -0.25F | ||
|
|
||
| private fun applyCustomTypeFace(paint: Paint, tf: Typeface) { | ||
| val oldStyle: Int | ||
| val old = paint.typeface | ||
| oldStyle = old?.style ?: 0 | ||
| val fake = oldStyle and tf.style.inv() | ||
| if (fake and Typeface.BOLD != 0) { | ||
| paint.isFakeBoldText = true | ||
| } | ||
| if (fake and Typeface.ITALIC != 0) { | ||
| paint.textSkewX = ITALIC_SKEW_FACTOR | ||
| } | ||
| paint.typeface = tf | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.rootstrap.android.util.extensions | ||
|
|
||
| import androidx.fragment.app.Fragment | ||
| import androidx.lifecycle.Lifecycle | ||
| import androidx.lifecycle.lifecycleScope | ||
| import androidx.lifecycle.repeatOnLifecycle | ||
| import kotlinx.coroutines.flow.Flow | ||
| import kotlinx.coroutines.launch | ||
|
|
||
| /** | ||
| * Allows the collection of an unlimited amount of flows in an inline style without needing to | ||
| * add boilerplate indentations. | ||
| * | ||
| * The flows are all collected inside the same lifecycleState but it can be customized. By default | ||
| * it is Lifecycle.State.STARTED. | ||
| * | ||
| * This extension can be called as many times as needed without problems, | ||
| * but generally you will only require to call it once thanks to the vararg operator. | ||
| * | ||
| * If called with a single Flow Pair the type of the flow is inferred automatically, otherwise | ||
| * you will need to cast the flow values when needed. | ||
| * | ||
| * Example of use : <br> | ||
| * - Single flow collection : | ||
| * > `collectOnLifeCycle(Pair(viewModel.eventsFlow) { it.collect { event -> onEvents(event) } })` | ||
| * - Multi flow collection : | ||
| * > Just appending a trailing "," and adding a new Pair allows you to collect an additional | ||
| * flow per pair | ||
| */ | ||
| fun <T> Fragment.collectOnLifeCycle( | ||
| vararg flowPairs: Pair<Flow<T>, suspend (Flow<T>) -> Unit>, | ||
| lifecycleState: Lifecycle.State = Lifecycle.State.STARTED | ||
| ) { | ||
| lifecycleScope.launch { | ||
| repeatOnLifecycle(lifecycleState) { | ||
| flowPairs.forEach { | ||
| launch { | ||
| it.second(it.first) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.rootstrap.android.util.extensions | ||
|
|
||
| import android.animation.Animator | ||
| import android.animation.ObjectAnimator | ||
| import android.view.animation.DecelerateInterpolator | ||
| import android.widget.ProgressBar | ||
| import androidx.core.animation.addListener | ||
|
|
||
| private const val DEFAULT_ANIMATION_TIME = 500L | ||
|
|
||
| /** | ||
| * Smoothly animates the progress of the progress bar to the specified value | ||
| */ | ||
| fun ProgressBar.progressTo( | ||
| newlyProgress: Int, | ||
| timeInMillis: Long = DEFAULT_ANIMATION_TIME, | ||
| onEndListener: ((Animator) -> Unit)? = null | ||
| ) { | ||
| ObjectAnimator.ofInt(this, "progress", progress, newlyProgress).apply { | ||
| duration = timeInMillis | ||
| interpolator = DecelerateInterpolator() | ||
| setAutoCancel(true) | ||
| onEndListener?.let { | ||
| addListener(onEnd = it) | ||
| } | ||
| }.start() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package com.rootstrap.android.util.extensions | ||
|
|
||
| import android.graphics.Typeface | ||
| import android.text.SpannableStringBuilder | ||
| import android.text.Spanned | ||
| import android.text.TextPaint | ||
| import android.text.method.LinkMovementMethod | ||
| import android.text.style.CharacterStyle | ||
| import android.text.style.ClickableSpan | ||
| import android.view.View | ||
| import android.widget.TextView | ||
| import androidx.annotation.ColorRes | ||
| import androidx.core.content.ContextCompat | ||
| import com.rootstrap.android.R | ||
| import com.rootstrap.android.ui.custom.CustomTypefaceSpan | ||
|
|
||
| /** | ||
| * Sets the first occurrence of the keyword string in this TextView's text as clickable and attach the | ||
| * given OnClickListener function to it. | ||
| * | ||
| * Additionally, it tints the keyword using the app's colorPrimary color and adds an underline to it | ||
| * so it looks and behaves like an Hyperlink. | ||
| * | ||
| * This behavior can be customized with the keywordColor and underline params and you can also change | ||
| * the keyword's typeFace with the typeFace param, allowing you to make it bold or apply | ||
| * other kinds of effects. | ||
| * | ||
| * You can add multiple clickable keywords by just calling this method as many times as you need in | ||
| * the same textview. | ||
| * | ||
| * The next example illustrates how to add a link to open a web browser: | ||
| *``` | ||
| * mySuggestionText.text = "For more information go to the admin web" | ||
| * mySuggestionText.setClickableKeyword("admin web") { | ||
| * // Get admin url and open the admin web via an intent | ||
| * } | ||
| *``` | ||
| */ | ||
| fun TextView.setClickableKeyword( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a comment description here. //** ...... *//
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a KDoc with an example usage 👍🏼 |
||
| keyword: String, | ||
| onClickListener: () -> Unit, | ||
| @ColorRes keywordColor: Int = R.color.colorPrimary, | ||
| underline: Boolean = true, | ||
| typeFace: Typeface? = null | ||
| ) { | ||
| val span: SpannableStringBuilder = getTextAsSpannable() | ||
|
|
||
| val start = text.indexOf(keyword, 0) | ||
|
|
||
| val clickableSpan = object : ClickableSpan() { | ||
| override fun onClick(widget: View) = onClickListener() | ||
| override fun updateDrawState(ds: TextPaint) { | ||
| ds.color = ContextCompat.getColor(context, keywordColor) | ||
| ds.isUnderlineText = underline | ||
| } | ||
| } | ||
|
|
||
| typeFace?.let { | ||
| span.setSpan(CustomTypefaceSpan(typeFace), start, start + keyword.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) | ||
| } | ||
| span.setSpan(clickableSpan, start, start + keyword.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) | ||
|
|
||
| if (movementMethod !is LinkMovementMethod) { | ||
| movementMethod = LinkMovementMethod.getInstance() | ||
| } | ||
|
|
||
| text = span | ||
| } | ||
|
|
||
| /** | ||
| * changes the color of the first occurrence of the keyword string in this TextView's text. | ||
| * | ||
| * It accept a color resource as a second parameter and by default it uses the app's colorPrimary color. | ||
| */ | ||
| fun TextView.setColoredKeyword( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a KDoc here too. Thanks! 👍🏼 |
||
| keyword: String, | ||
| @ColorRes keywordColor: Int = R.color.colorPrimary | ||
| ) { | ||
| val span: SpannableStringBuilder = getTextAsSpannable() | ||
| val start = text.indexOf(keyword, 0) | ||
| val coloredSpan = object : CharacterStyle() { | ||
| override fun updateDrawState(ds: TextPaint) { | ||
| ds.color = ContextCompat.getColor(context, keywordColor) | ||
| } | ||
| } | ||
| span.setSpan(coloredSpan, start, start + keyword.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) | ||
| text = span | ||
| } | ||
|
|
||
| private fun TextView.getTextAsSpannable() = | ||
| if (text is SpannableStringBuilder) text as SpannableStringBuilder | ||
| else SpannableStringBuilder(text) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/classes/kotlin/main/Libs.class:/Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/classes/kotlin/main/Versions.class |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| 1 | ||
| 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| implementation-classpath=/Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/classes/java/main\:/Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/classes/groovy/main\:/Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/classes/kotlin/main\:/Users/rodrigosoria/Documents/Rootstrap/projects/Android-base/repos/android-base/buildSrc/build/resources/main |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| src/main/resources | ||
| src/main/java | ||
| src/main/groovy | ||
| src/main/kotlin | ||
| src/test/resources | ||
| src/test/java | ||
| src/test/groovy | ||
| src/test/kotlin |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Manifest-Version: 1.0 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! :D It simplifies a lot the fragment's code haha