Guiding user input on EditText

Soumya Kanti Kar
wwdablu
Published in
4 min readSep 15, 2021
Photo by Brett Jordan on Unsplash

We have all used EditText as is or an extended class of it, like AppCompatEditText in our Android application. In several scenarios, we had a requirement wherein the text provided by the user has to follow certain rules, for example, the length of the input string must of a certain characters in length. To address this need of guiding the user to follow a set of rule and providing the information, GuidedEditText is created.

Gradle declaration

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

dependencies {
implementation 'com.github.wwdablu:GuidedEditText:Tag'
}

You can check the latest version of the release from the GitHub page.

So even before we proceed, let us see how the view looks like after it is attached with an EditText view.

GuidedEditText in action

The approach is that the developer needs to design some rules which is needed to be adhered by the user when providing the information. Hence, a rule definition has to be present. Likewise, the first thing that needs to be done is that an implementation of the RuleDefinition is required to be created.

interface RuleDefinition {
fun follows(input: String, rule: Rule) : State
fun text(state: State) : SpannableString
}

Now before we proceed with that those methods need to implement we need to understand that a Rule can be in one of these allowed states

enum class State {
Satisfied,
Unsatisfied,
PartiallySatisfied,
PendingValidation
}

Satisfied — This means that the rule requirement has been met

Unsatisfied — This means that the rule requirement has not been met

PartiallySatisfied — This wherein a portion of the requirement is met

PendingValidation — This signifies that some asynchronous task needs to be performed before it can be said whether the rule has been met or not. This puts the rule validation in a pending state.

Now, the method follows, will be called when the library wants to validate whether the input string meets the requirement.

The method text, needs to provide what text is needed to be displayed to the current state of the rule. Let us see this with an example:

class UserNameIsEmail : RuleDefinition {
override fun follows(input: String, rule: Rule): State {
return if(Patterns.EMAIL_ADDRESS.matcher(input).matches())
State.Satisfied
else
State.Unsatisfied
}

override fun text(state: State): SpannableString {
return if(state == State.Satisfied)
SpannableString("Username is acceptable")
else
SpannableString("Username must be an email address")
}
}

So in the above example we can see that we have defined a rule wherein we say that the input to the EditText must conform it being an email address. If the input string matches then we say State.Satisfied, otherwise State.Unsatisfied. Similar to this we can make any number of rules that needs to be handled.

Once the RuleDefinition has been written, we need to create a Rule from it. We can also set the notify mechanism for the rule. The sample code to create a rule from a RuleDefinition is provided below:

val userNameIsEmail = Rule(UserNameIsEmail())
.setNotifyOn(RuleDefinition.Notify.Change)
.setStateText(State.Satisfied, Color.parseColor("#f4f4f2"))
.setStateText(State.Unsatisfied, Color.parseColor("#f4f4f2"))

We can set colour for the text for each of the corresponding states. Now let us understand the notify mechanism.

enum class Notify {
Change,
Debounce
}

Change — This means that the RuleDefinition needs to be notified as soon as there is a change in the EditText content.

Debounce — This means that the RuleDefinition will be notified after a certain period of time, once the user has stopped entering text. This value can be modified while calling setNotifyOn. The default value is 600ms.

We will create the layout wherein we will link the EditText view with the GuidedEditText component.

<EditText
android:id="@+id/et_user_name"
android:layout_width="match_parent"
android:layout_height="36dp"
android:background="@drawable/rounded_corner"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
/>

<com.wwdablu.guidededittext.GuidedEditText
android:id="@+id/get_user_name_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:guideAnimate="true"
app:guideTextSize="6sp"
app:guideBackgroundImage="@drawable/guide_background_sample"
app:guideLinkedWith="@id/et_user_name"
/>

We can see the property guideLinkedWith, which then specifies the reference to the EditText view. Finally, we need to just add the rule to the GuidedEditText component.

mBinding.userNameInput.addRule(userNameIsEmail)

Wasn't it easy and fun? This would make the code much cleaner with separation of logic and view. Also it would guide the user to ensure that the requirements are matched.

As always the library source code is open. Please feel free to report issues and open feature tickets.

--

--

Soumya Kanti Kar
wwdablu
Editor for

Android developer. Interested in working on open source Android libraries and applications.