• Stars
    star
    450
  • Rank 97,143 (Top 2 %)
  • Language
    Java
  • License
    Other
  • Created about 8 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Material Chips for Android

Nachos for Android

Table of Contents

What is Nachos?

Nachos is a library for Android that provides a custom TextView allowing users to enter text and create material chips in the text field.

Nachos is not directly coupled to any data source so it allows for much more extensive customization.

Key Features

  • Uses an EditText in combination with spans to avoid any overhead associated with inflating layouts for views
  • Full control over when chips are created
    • Create chips when certain characters are typed
    • Create chips when suggestions are selected
    • Manually (programmatically) create chips
  • Matches the material specification created by Google
    • You can also fully customize the appearance of the chips
  • Show a dropdown of suggestions that will create chips when they are selected
  • Offers the ability to edit chips on touch (in place or by moving them to the end of the text field)
  • Chips are ellipsized when they are longer than the width of the TextView
  • Optionally display an icon within the chips
  • Handles copying and pasting

Installation

Add this line to your project level build.gradle:

buildscript {
  repositories {
    jcenter()
  }

Add this line to your module level build.gradle:

dependencies {
    implementation "com.hootsuite.android:nachos:1.1.1"
}

Basic Usage

Include a NachoTextView in your xml layout as follows:

<com.hootsuite.nachos.NachoTextView
    android:id="@+id/nacho_text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

Customizing the UI

NachoTextView offers several custom attributes that allow you to control the appearance of the chips it creates:

  • chipHorizontalSpacing - The horizontal space between chips
  • chipBackground - The background color of the chip, can be a ColorStateList to change color when the chip is clicked
  • chipCornerRadius - The corner radius of the chip background
  • chipTextColor - The color of the chip text
  • chipTextSize - The font size of the chip text
  • chipHeight - The height of a single chip
  • chipVerticalSpacing - The vertical space between chips on consecutive lines.

Note: chipVerticalSpacing can only be used if chipHeight is also set

Use these attributes as follows:

<com.hootsuite.nachos.NachoTextView
    android:id="@+id/nacho_text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:chipHorizontalSpacing="2dp"
    app:chipBackground="@color/chip_background"
    app:chipTextColor="@color/cheddar"
    app:chipTextSize="16dp"
    app:chipHeight="30dp"
    app:chipVerticalSpacing="3dp"/>

Don't forget to declare the app namespace on your root layout element:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    .../>

If you don't include any of these attributes, they will be set to default values that match the material spec.

Showing Suggestions

NachoTextView extends MultiAutoCompleteTextView which allows you to provide suggestions to the user as they are typing. The suggestions are generated based on only the text of the current token (not the contents of the entire text field).

Providing suggestions for the NachoTextView works the same way as it would for a MultiAutoCompleteTextView:

Create an adapter:

String[] suggestions = new String[]{"Tortilla Chips", "Melted Cheese", "Salsa", "Guacamole", "Mexico", "Jalapeno"};
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, suggestions);

And call setAdapter(Adapter) on the NachoTextView:

nachoTextView.setAdapter(adapter);

When a suggestion is tapped, the object from the adapter that represented that suggestion is associated with the chip that gets created. It can later be accessed through Chip.getData(). See Reading the Values of the Chips for details.

Triggering the Creation of Chips when a Character is Typed

The characters that should cause the creation of a chip when typed are referred to as chip terminators. Each chip terminator can be associated with one of three behaviors which control what will happen when that character is encountered in the text field:

BEHAVIOR_CHIPIFY_ALL:

  • When a chip terminator character is encountered in newly inserted text, all tokens in the whole text view will be chipified

In the example above, '\n' (the enter key) is a chip terminator associated with BEHAVIOR_CHIPIFY_ALL

BEHAVIOR_CHIPIFY_CURRENT_TOKEN:

  • When a chip terminator character is encountered in newly inserted text, only the current token (that in which the chip terminator character was found) will be chipified. This token may extend beyond where the chip terminator character was located.

In the example above, ';' (semicolon) is a chip terminator associated with BEHAVIOR_CHIPIFY_CURRENT_TOKEN

BEHAVIOR_CHIPIFY_TO_TERMINATOR:

  • When a chip terminator character is encountered in newly inserted text, only the range of text from the previous chip to the chip terminator character will be chipified. This may not be an entire token.

In the example above, ' ' (space) is a chip terminator associated with BEHAVIOR_CHIPIFY_TO_TERMINATOR


To associate a behavior with a particular terminator, call:

nachoTextView.addChipTerminator(character, behavior);

For example, if you want all the plain text in the text field to be chipified when the user presses enter, call:

nachoTextView.addChipTerminator('\n', ChipTerminatorHandler.BEHAVIOR_CHIPIFY_ALL);

And, if you want just the text from the previous chip (or beginning) up to the cursor to be chipified when the user presses space, call:

nachoTextView.addChipTerminator(' ', ChipTerminatorHandler.BEHAVIOR_CHIPIFY_TO_TERMINATOR);

Editing Chips

NachoTextView supports editing chips on touch. To enable this behavior call:

nachoTextView.enableEditChipOnTouch(moveChipToEnd, chipifyUnterminatedTokens);

If moveChipToEnd is true, the chip will be moved to the end of the text field when it is tapped. It will then be unchipified and the user will be able to edit it.

If moveChipToEnd is false, the chip will be unchipified in place allowing the user to edit it right where it is.

If chipifyUnterminatedTokens is true, all plain text (tokens) in the text field will be chipified before the chip to be edited is unchipified. Otherwise the chip to be edited will simply be unchipified without affecting the other text.

Listening for when a Chip is Touched

If you want to perform any custom actions when a chip is clicked you can attach an OnChipClickListener to the NachoTextView:

nachoTextView.setOnChipClickListener(new NachoTextView.OnChipClickListener() {
    @Override
    public void onChipClick(Chip chip, MotionEvent motionEvent) {
        // Do something
    }
});

In addition to any action you perform in an OnChipClickListener the following will happen when a chip is touched:

  • The chip's state will be set to pressed and selected
    • (chip.setState(View.PRESSED_SELECTED_STATE_SET))
  • The chip will be put in edit mode if enableEditChipOnTouch(...) was called and disableEditChipOnTouch() hasn't been called since

Preventing the User from Typing Characters

If you want to prevent the user from typing certain characters, you can call:

nachoTextView.setIllegalCharacters(illegalCharacter1, illegalCharacter2, ...);

setIllegalCharacters(...) accepts a varargs list of characters so you can make as many characters as you want illegal. These characters, when typed, will be immediately deleted from the text. If the user pastes text into the NachoTextView, any illegal characters will be removed from the text before it is entered.

Reading the Values of the Chips

NachoTextView exposes several methods to read the contents of the text view:

  • getAllChips()
    • Returns the actual Chip objects contained in the text view
    • Chip is an interface that represents a chip and declares methods to access the text (getText()), data (getData()), and ui attributes of the chip
  • getChipValues()
    • Returns a List of the string values of all the chips in the text
  • getTokenValues()
    • Returns a List of the string values of all the tokens (unchipped text) in the text
  • getChipAndTokenValues()
    • Returns a combination of the chip values and token values in the text.
    • Effectively a concatenation of the previous two methods (getChipValues() and getTokenValues())

Example:

// Iterate over all of the chips in the NachoTextView
for (Chip chip : nachoTextView.getAllChips()) {
    // Do something with the text of each chip
    CharSequence text = chip.getText();
    // Do something with the data of each chip (this data will be set if the chip was created by tapping a suggestion)
    Object data = chip.getData();
}

Advanced Usage

This section will often refer to the terms "token" and "chip".

  • Token means plain, unchipped text
  • Chip means chipped text

Validating the Contents of the TextView

NachoTextView supports the use of a NachoValidator. When validation occurs is controlled by AutoCompleteTextView; however, it usually occurs in scenarios such as losing focus. Nachos includes an implementation of NachoValidator: ChipifyingNachoValidator. This implementation considers text to be invalid if it contains tokens and validates the text by chipifying all tokens.

To attach a NachoValidator, call setNachoValidator(...):

// Example
nachoTextView.setNachoValidator(new ChipifyingNachoValidator());

To disable validation, call:

nachoTextView.setNachoValidator(null);

Customizing the Creation/Identification of Chips/Tokens

The creation and identification of chips in a NachoTextView is centered around the ChipTokenizer interface. This interface defines methods to:

  • Identify tokens
  • Identify chips
  • Convert between chips and tokens
  • Remove chips

The default implementation of ChipTokenizer used by NachoTextView is SpanChipTokenizer. This implementation attaches spans to the text in order to display a chip. It also surrounds the text in marker characters to allow easy identification of chips and tokens (unchipped text).

If you would like to customize the way the NachoTextView creates and identifies its chips you can write your own implementation of ChipTokenizer and tell the NachoTextView to use it by calling:

nachoTextView.setChipTokenizer(new MyChipTokenizer());

Note: Do NOT call setTokenizer(...) on NachoTextView unless you absolutely know what you are doing. setTokenizer(...) is a method defined in MultiAutoCompleteTextView that sets the Tokenizer to be used to provide suggestions for the current token. This method gets called automatically by setChipTokenizer(...) so calling setChipTokenizer(...) alone should be enough.

Note #2: If you want to disable all chipping behavior in the NachoTextView, you can call:

nachoTextView.setChipTokenizer(null);

Using a Custom UI Element for the Chips

The SpanChipTokenizer implementation of ChipTokenizer provides some built-in customization support through the ChipCreator interface.

ChipCreator defines 3 methods that handle the creation and customization of the chip that gets displayed as a span by SpanChipTokenizer.

By default, NachoTextView uses a ChipSpanChipCreator which produces chips that are instances of the ChipSpan class. If you want to customize the ChipSpans that get created, you can use a custom subclass of ChipSpanChipCreator:

// Example: we want to show the launcher icon in all of our ChipSpans:
nachoTextView.setChipTokenizer(new SpanChipTokenizer<>(this, new ChipSpanChipCreator() {
    @Override
    public ChipSpan createChip(@NonNull Context context, @NonNull CharSequence text, Object data) {
        return new ChipSpan(context, text, ContextCompat.getDrawable(MainActivity.this, R.mipmap.ic_launcher), data);
    }

    @Override
    public void configureChip(@NonNull ChipSpan chip, @NonNull ChipConfiguration chipConfiguration) {
        super.configureChip(chip, chipConfiguration);
        chip.setShowIconOnLeft(true);
    }
}, ChipSpan.class));

If you want even more customization (for example if you wanted to use a span other than a ChipSpan), you can use a custom ChipCreator:

nachoTextView.setChipTokenizer(new SpanChipTokenizer<>(this, new ChipCreator<MySpan>() {
    @Override
    public MySpan createChip(@NonNull Context context, @NonNull CharSequence text, Object data) {
        return new MySpan(context, text, data);
    }
    
    @Override
    public MySpan createChip(@NonNull Context context, @NonNull MySpan existingSpan) {
        return new MySpan(context, existingSpan);
    }

    @Override
    public void configureChip(@NonNull MySpan chip, @NonNull ChipConfiguration chipConfiguration) {
        // Configure the span
    }
}, MySpan.class));

License

Nachos is released under the Apache License, Version 2.0. See LICENSE for details.

Acknowledgements

Special thanks to the author of nachos, Noah Tajwar and to the original author of our internal library, Dave Russell!

More Repositories

1

grid

Drag and drop library for two-dimensional, resizable and responsive lists
JavaScript
3,572
star
2

atlantis

Atlantis is now being maintained at https://github.com/runatlantis/atlantis
Go
614
star
3

pre-commit-php

Pre-commit scripts appropriate for any PHP project. These hooks are made as custom plugins under the pre-commit git hook framework.
Shell
177
star
4

healthchecks

A go implementation of the Health Checks API used for microservice exploration, documentation and monitoring.
Go
132
star
5

akka-persistence-redis

Akka Persistence that uses Redis as backend
Scala
117
star
6

health-checks-api

Standardize the way services and applications expose their status in a distributed application
API Blueprint
95
star
7

microservice-graph-explorer

Navigate and explore all of the microservices in your application in real time using the real application connections.
JavaScript
74
star
8

sens8

Kubernetes controller for Sensu checks
Go
42
star
9

token-ui

Text input components that allows to add 'tokens' rendered as pills.
Swift
42
star
10

hermes

Kotlin ktor application which bridges Github and Slack. Use it to automate common workflows involving those platforms
Kotlin
35
star
11

scala-circuit-breaker

A circuit breaker for Scala applications and services
Scala
35
star
12

wordpress-multisite-vagrant

JavaScript
27
star
13

sbt-swagger

SBT plugin for extracting Swagger & JAX-RS (jsr311) annotations from compiled classes into Swagger API models, which are then serialized to JSON for consumption with swagger-ui.
Scala
27
star
14

vault-ctrl-tool

Simple tool for managing authentication, secrets, and leases for services.
Go
26
star
15

backup53

AWS Route53 backup tool
Python
23
star
16

hootsuite-app-express

Sample Hootsuite app directory app using Express and Node.js
JavaScript
19
star
17

statsd-client

A lightweight library for generating statsd events from in Scala applications.
Scala
13
star
18

apis-101

Beginners-friendly introduction to APIs starter code.
JavaScript
11
star
19

maintenance-calendar-for-aws

Go
9
star
20

OwlBanners

Swift
7
star
21

emit

Simple signals library for Swift
Swift
6
star
22

udp-logger

UDP logging to logstash for logback and log4j.
Scala
6
star
23

microservice-graph-explorer-test

Runs services that implement the Health Checks API to be used when testing the Microservice Graph Explorer
Go
5
star
24

atlantis-example

A simple terraform project to use along with atlantis bootstrap mode
3
star
25

dropbox-media-library-sample

Media Library Sample App with Auth
JavaScript
1
star
26

atlantis-tests

A set of terraform projects that atlantis e2e tests run on.
HCL
1
star