Giter VIP home page Giter VIP logo

spanomatic's Introduction

Spanomatic

Spanomatic is an Android library that allows you to automatically add spans to text from resources strings.

Getting Started

Dependencies

Add Jitpack in your root build.gradle:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Spanomatic uses the ViewPump library, that provides an API for pre/post-inflation interceptors.
Add these dependencies to your app module's build.gradle file:

dependencies {
    ...
    implementation 'com.github.grivos:Spanomatic:1.2.1'
    implementation 'io.github.inflationx:viewpump:2.0.3'
}

Initialization

Init ViewPump and add the SpanomaticInterceptor in your app class:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        ViewPump.init(
            ViewPump.builder()
                .addInterceptor(
                    SpanomaticInterceptor()
                )
                .build()
        )
    }
    
}

Wrap your activities context:

class BaseActivity : AppCompatActivity() {

    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
    }

}

String Resources Annotations

In order for Spanomatic to translate string resources annotations into spans, you need to wrap your strings in special annotations. The mechanic is like so:

<string name="annotated_string">This part isn\'t annotated,  <annotation key="value">but this part is</annotation>.</string>

Spanomatic parses the string resource, looks for these annotations, and depending on the key and value, it adds the appropriate spans. You can also nest annotations like so:

<string name="nested_annotations">This part isn\'t annotated,  <annotation key1="value1"><annotation key2="value2">but this part has two annotations</annotation></annotation>.</string>

Spanomatic supports several annotation keys out of the box, but you can also register handlers for custom annotation keys.

Supported Annotation Keys

fgColor

Description: Adds a ForegroundSpan.
Possible Values: Either a literal color hex ("#9C27B0") or a color reference ("@color/material_purple").
Example:

<string name="fg_color_hex">This text has <annotation fgColor="#9C27B0">purple foreground</annotation></string>

example_fg

bgColor

Description: Adds a BackgroundSpan.
Possible Values: Either a literal color hex or a color reference.
Example:

<string name="bg_color_hex">This text has <annotation bgColor="@color/material_green">green background</annotation></string>

example_bg

relativeTextSize

Description: Adds a RelativeSizeSpan.
Possible Values: The size multiplier.
Example:

<string name="relative_size">This text is two times <annotation relativeTextSize="2">bigger</annotation></string>

example_relative_size

absoluteTextSize

Description: Adds an AbsoluteSizeSpan.
Possible Values: A size identifier. Either a literal (18dp, 16sp, etc.) or a reference ("@dimen/big_text_size").
Example:

<string name="absolute_size">This text size is <annotation absoluteTextSize="20dp">20dp</annotation></string>

example_absolute_size

drawable

Description: Adds an ImageSpan.
Possible Values: A drawable reference and an optional alignment (either baseline or bottom). If the alignment is missing, the default is baseline.
The optional alignment is separated from the drawable reference using the pipe character (|).
Example:

<string name="drawable_with_alignment">This is a <annotation drawable="@drawable/ic_cake_16dp|bottom">cake</annotation> drawable span.</string>

example_drawable

format

Description: Adds one of StrikethroughSpan, StyleSpan, SuperscriptSpan, SubscriptSpan, UnderlineSpan.
Possible Values:

Value Span
strikethrough StrikethroughSpan()
bold StyleSpan(Typeface.BOLD)
italic StyleSpan(Typeface.ITALIC)
boldItalic StyleSpan(Typeface.BOLD_ITALIC)
superscript SuperscriptSpa()
subscript SubscriptSpan()
underline UnderlineSpan()

Example:

<string name="format_string">Spanomatic supports <annotation format="strikethrough">strikethrough</annotation>, <annotation format="bold">bold</annotation>, <annotation format="italic">italic</annotation>, <annotation format="boldItalic">bold italic</annotation>, <annotation format="superscript">superscript</annotation>, <annotation format="subscript">subscript</annotation> and <annotation format="underline">underline</annotation> spans.</string>

example_format

quote

Description: Adds a QuoteSpan.
Possible Values: Either empty or an optional literal color hex or a color reference.
Example:

<string name="quote"><annotation quote="">This is a quote</annotation></string>
<string name="quote_with_color"><annotation quote="#D81B60">This is a quote</annotation></string>

example_quote

bullet

Description: Adds a BulletSpan.
Possible Values: Either empty or an optional gap width (literal dimension or a dimension reference), and an optional literal color hex or a color reference.
Example:

<string name="bullet"><annotation bullet="">This is a bullet</annotation></string>
<string name="bullet_with_gap"><annotation bullet="16dp">This is a bullet</annotation></string>
<string name="bullet_with_gap_and_color"><annotation bullet="16dp|#00574B">This is a bullet</annotation></string>

example_bullet

url

Description: Adds a URLSpan.
Possible Values: A url.
Example:

<string name="url">This text has a <annotation url="https://www.google.com/">UrlSpan</annotation></string>

example_url

leadingMargin

Description: Adds a LeadingMarginSpan.
Possible Values: The size of the leading margin (either a literal dimension or a dimension reference).
Example:

<string name="leading_margin"><annotation leadingMargin="@dimen/leading_margin">This text has a leading margin</annotation></string>

example_leading_margin

typeface

Description: Adds a CustomTypefaceSpan.
Possible Values: The name of this typeface (either a literal string or a string reference).
Example:
First, you need to register a TypefaceProvider (the best place to do so is in your Application onCreate() method):

val latoRegular = ResourcesCompat.getFont(this, R.font.lato_regular)
val latoLight = ResourcesCompat.getFont(this, R.font.lato_light)
val latoBold = ResourcesCompat.getFont(this, R.font.lato_bold)
Spanomatic.typefaceProvider = object : TypefaceProvider {

    override fun getTypeface(name: String): Typeface? {
        return when (name) {
            "latoRegular" -> latoRegular
            "latoLight" -> latoLight
            "latoBold" -> latoBold
            else -> null
        }
    }

}

Then we can use these typefaces in a string resource:

<string name="typefaces">Here we have three different typefaces: <annotation typeface="latoRegular">Lato Regular</annotation>, <annotation typeface="latoLight">Lato Light</annotation> and <annotation typeface="latoBold">Lato Bold</annotation></string>

example_typeface

click

Description: Adds a ListenableClickableSpan (a custom ClickableSpan that can be registered with a click callback).
Note that this span doesn't add an UnderlineSpan, so if that's what you want, you should wrap it in another format="underline" annotation.
Possible Values: The name of this click (so we can register a callback to the span from the code).
Example:

<string name="click">This span is clickable: <annotation format="underline"><annotation click="click1">click me</annotation></annotation></string>

To catch the onClick event, you need to register a callback like so:

clickableTextView.addSpanClickListener("click1") {
    Toast.makeText(this, "Span was clicked", Toast.LENGTH_SHORT).show()
}

example_click_toast

Adding Support For Custom User Annotation Keys

You can register your own annotation span handlers like so:

Spanomatic.setAnnotationSpanHandler("myCustomKey") { annotationValue, context ->
    val myParsedValue = parseValue(annotationValue, context)
    MyCustomSpan(myParsedValue)
}

Then you can use it in your string resources:

<string name="custom">This span is <annotation myCustomKey="someValue">custom</annotation></string>

Using Spanomatic Manually

Spanomatic automatically adds spans in the layout inflation process, but you can also use it manually like so:

val spanned = addSpansFromAnnotations(R.string.annotated_string)
myTextView.text = spanned

Format Arguments

Spanomatic also supports format arguments:

<string name="annotated_string_with_parameters">This text has annotations with parameters: <annotation format="bold">%1$s</annotation>, <annotation format="italic">%2$b</annotation>, <annotation format="underline">%3$d</annotation></string>
val param1 = "text"
val param2 = false
val param3 = 5
val spanned = addSpansFromAnnotations(R.string.annotated_string_with_parameters, param1, param2, param3)
myTextView.text = spanned

Acknowledgements

Spanomatic was inspired by this blog post by Florina Muntenescu and the Rialto library by Mark Allison.

spanomatic's People

Contributors

grivos avatar janekxyz avatar jvmname avatar teobaranga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

spanomatic's Issues

Update to AndroidX?

I'm currently using v1.0.2 of Spanomatic, and I noticed that the internal Utils.kt is using android.support.v4.content.ContextCompat in a few places.

Would you be open to migrating to AndroidX - e.g. using androidx.core.content.ContextCompat?

I'd be happy to help, I've done it before:

I know folks can use Jetifier, but given that Support Libs are officially deprecated, it'd be nice to win the Jetifier Tax back in my build ๐Ÿ˜„

Let me know your thoughts!

Bintray Shutting Down May 2021 -- Host artifacts elsewhere?

Hi! Today JFrog (which owns Bintray/JCenter) announced that they're sunsetting Bintray/JCenter - the last day to access these repositories will be May 2021. jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter

I know a lot of tooling goes into artifact upload to a repository, so I wanted to throw a signal flare up now so nobody is caught by surprise on May 1.

[Question] Will Spanomatic support theme attribute?

Hi,

I really appreciate this library. It works wonderful in our project.

For enhancement

Will this library support theme attribute e.g. using ?colorPrimary in foreground color span tag something like <string name="theme_color_string"><annotation fgColor="?colorPrimary">text with color primary</annotation></string>?

Thank you in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.