jvlppm / android-text

Create and format text from android ViewModel

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

android-text

Create and style a text from android ViewModel, without depending on a context.

It can be easily converted to a SpannableString, providing a context, without worrying about ranges.

Simple Usage

com.jvlppm.text.Text is a class that describes a text to be displayed

Your viewModel can create a Text using either a String or a @StringRes Int, without a reference to context.

val staticText = Text("Simple Text")
val resourceText = Text(R.string.my_resource_text, style = "bold")
val concatenatedText = staticText + Text.space + resourceText

This Text can be manipulated / formatted by your view model, with text replacement methods and other facilities.

The Text can be then displayed by using this extension method provided by this library.

import com.jvlppm.text.bindings.setText

/**
 * This method will resolve the Text and construct a `SpannableString` that represents it,
 * and it will attach it to your `TextView`.
 */
@BindingAdapter("android:text")
fun TextView.setText(text: Text?)

And since this method is declared as a BindingAdapter, you can also use android:text on your xml

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@{viewModel.concatenatedText}" />

You can also create the SpannableString / String and apply it manually.

import com.jvlppm.text.extensions

/**
 * This method creates a SpannableString with the corresponding text and styles applied.
 */
fun Text.asSpannable(context: Context): SpannableString

/**
 * This method resolves the Text into a simple String with no formatting information.
 */
fun Text.toString(context: Context): String

Creating Text

A Text can be created with a String or a @StringRes Int, and it also accepts a style object that can be attached to your Text

val staticText = Text("Sample")
val resourceText = Text(R.string.my_resource_text)

val addingText = staticText + Text.space + resourceText

// Note that the final string will only be resolved later when the UI invoke toString(context)

val concatenated = Text.concatenated(
    staticText,
    Text.space,
    resourceText
)

val spaced = Text.spaced(
    staticText,
    resourceText
)

val multiline = Text.lines(
    Text("First line"),
    Text("Second line", style = null),
)

A text can also be formatted in the same way String.format works

val text = Text("You %s %d times")
    .formatString("clicked", 5)

val text = Text(R.string.hello_user)
    .formatString("Friend")

val text = Text("Hello %s, you clicked %d times")
    .formatString(
        "Friend" to "color:green",
        5 to "scale:3;bold"
    )

A text can also be manipulated with a replace method

val text = Text("Good morning")
    .replaceAll("morning" to Text("night"))

val text = Text("%s %s")
    .replaceOnce(
        "%s" to Text("Good"),
        "%s" to Text("morning"),
    )

Styling Text

A Text can hold a style object that represents how it should be styled, this can be a String or any other object.

val text1 = Text("Static text", style = "bold")
val text2 = Text(R.string.my_sample_text, style = myCustomStyleObject)

Later when the Text gets displayed it will then try to decode your style object using com.jvlppm.text.TextManager.

TextManager is responsible to reading the style object, "bold" in this example, and converting it to a StyleSpan(Typeface.BOLD) which will be used by your interface.

TextManager already has a few style decoders by default, those can be extended and configured.

Default Styles

"underline" // Resolves to a UnderlineSpan()
"strike" // Resolves to a StrikethroughSpan()
"italic" // Resolves to a StyleSpan(Typeface.ITALIC)
"bold" // Resolves to a StyleSpan(Typeface.BOLD)
"strong" // Resolves to a StyleSpan(Typeface.BOLD)
"font:*" // Resolves to a MetricAffectingSpan that changes the typeface
"font-family:*" // Resolves to a TypefaceSpan
"color:*" // Resolves to a ForegroundColorSpan
"scale:*" // Resolves to a RelativeSizeSpan

Some styles accept parameters, like scale for example, and can be used as

Text("Scale sample", style = "scale:1.5")

There is also a default style resolver that converts a ()->Unit into a ClickableSpan

Text("My clickable string", style = { onClickText() } )

Custom Styles

A custom style can be registered with

TextManager.styles["test"] = { context -> UnderlineSpan() }

A style that accepts a parameter can be registered with

// This will replace the default styles
TextManager.styles["scale"] = { context, value: Float -> RelativeSizeSpan(value) }
TextManager.styles["font"] = { context, value: String -> MyCustomFontSpan(value) }

Colors

A color style can be constructed in a few ways

// Using a direct color
Text("Red string", style = "color:${R.color.red}")
Text("Red string", style = "color:red") // same as above

// Using a theme attr
Text("Theme colored string", style = "color:?${android.R.attr.textColorPrimary}")
Text("Theme colored string", style = "color:?textColorPrimary") // same as above

A question mark indicates it is an attr value, and the value itself can be an Int or a name,

this behavior can be replaced by your custom attribute reader.

Fonts

The default font attribute reader uses the same syntax as the colors described above

Text("Red string", style = "font:${R.font.poppins_black}")
Text("Red string", style = "font:poppins_black")

There is also an extension that replaces simple html tags to a string with an attached style, example:

import com.jvlppm.text.extensions.decodeStyleTags

// Creates a text that styles the word "string" with "bold" and "styles" with "italic"
val text = Text("My simple <b>string</b> with <i>styles</i>")
    .decodeStyleTags()

Setup with Gradle KTS

settings.gradle.kts

dependencyResolutionManagement {
    ...
    repositories {
        ...
        maven { setUrl("https://jitpack.io") }
    }
}

build.gradle.kts (:app)

dependencies {
    ...
    implementation("com.github.jvlppm:android-text:v0.6")
}

Setup with older projects

Step 1. Add the JitPack repository to your build file

Add jitpack.io as a repository on your settings.gradle

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Older projects had the repositories defined inside build.gradle instead

buildscript {
    repositories {
        jcenter()
        // DO NOT ADD IT HERE!!!
    }
    ...
}

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        // ADD IT HERE
        maven { url "https://jitpack.io" }
    }
}

Step 2. Add the dependency to your app's build.gradle Check the releases page on github to see what is the latest version available

dependencies {
	implementation 'com.github.jvlppm:android-text:v0.6'
}

About

Create and format text from android ViewModel

License:MIT License


Languages

Language:Kotlin 100.0%