Creating a User Input Text Counter in Android
NOTE: I’ve refactored this walkthrough in a subsequent blog post here
A little while back I attended an Android bootcamp in which we built a handful of apps as we learned. One of the apps we were tasked with building was a Twitter app, and one of the features I wanted to build was the almost iconic character counter for tweet composition, as they are of course limited to 140 characters. As you type each character, the gray text counts down to zero before turning red and continuing to count back up in the negative range.
Additionally, since the Twitter API will reject any tweet posted over 140 characters, we need to disable the button next to the counter to prevent the tweet from attempting to be posted.
Getting started
We’ll be using data binding, so in our build.gradle
for our app
module we’ll need to enable it.
In the layout file for the fragment, we need to expose a variable to tie logic from the fragment’s class to values
inside the layout. Data-binding layout files need to be wrapped in a layout
tag, followed by a list of variable
tags
within an opening and closing data
tag. The variable
tag we’ll add is what Android will use to tie a property in
our ComposeTweetFragment
to the fragment_compose_tweet.xml
layout.
We’ll come back to the TweetViewModel
explanation shortly. Back to our ComposeTweetFragment
class, we need to add a variable
called tweetViewModel
to tie our layout-declared variable to the fragment’s class. From the documentation,
By default, a Binding class will be generated based on the name of the layout file, converting it to Pascal case and suffixing "Binding" to it.
Therefore the variable we’ll declare will be of type FragmentComposeTweetBinding
.
In the onCreate
method, we inflate the view, assign the binding to our private variable, and set the value of our layout-defined
tweetViewModel
variable.
The tweet
variable comes from a value passed into the fragment class.
Where did the TweetViewModel come from?
Returning to the TweetViewModel
class, let’s look at part of the definition, as this is a class we’re declaring ourselves.
The notable item to point out here is the ObservableField
property, which provides a way in which data bound UI can be notified of changes.
The character count changes dynamically based off of user input, so it needs to know when to update. We also need to add a TextWatcher
to
the class to watch the EditText
field as the user types.
Finally, in our fragment_compose_tweet.xml
layout file (and only showing the properties related to the functionality we’re building), we have:
We use the @{}
syntax for interpolating our data-bound expressions, which by element type are
EditText
- text - The actual tweet body.
- addTextChangedListener - The text watcher that determines when to update the character count.
TextView
- text - The dynamic count of the number of characters remaining (the
""+
casts theInteger
to typeString
). - textColor - If the number of characters remaining is between 0 and 140, the text color will be gray, otherwise a negative count will turn the text red.
Button
- alpha - Show a partially faded button indicating that it is disabled if the user hasn’t started typing a tweet yet, or if they type more than 140 characters. The
<
needs to be escaped. - clickable - Allow the button to be clicked if the user has typed at least one character and not more than 140. The
<
and&&
need to be escaped.
Conclusion
Both data binding and observables are very powerful concepts in Android, and I encourage you to explore the vast array of ways they can be utilized in your apps. The official documentation is the best place to start, and they are plenty of other tutorials easily found on the Googles. I’ve only shown the bare minimum code for explanation of the topic at hand, but if you would like to go through the tutorial again with the full source, you can find it on my GitHub account here. If you have any questions, or suggestions for a better way to structure the code above, please don’t hesistate to comment. Good luck and thanks for reading!