When you’re developing application, there is often a need to create your own controls/widgets/classes or to extend already available ones. And in most cases, you want this control/widget to be as flexible as possible. In order to achieve this, you have to create special events, which can be handled outside of your widget.
Some of the popular examples are
Next, we clean up some of the code from
Our application doesn’t receive any onKey events yet, because we haven’t registered the listener with the
As always, there is the full source of the files (click on expand to make it visible)
OnClickListener and OnKeyListener. But sometimes you need Events/Listener which aren’t predefined by the Java or Android SDK. In this case, you have to create your own Listener interface.
In the last post, I’ve shown three different way on how to implement Listeners in your application. Now I’ll show you how to implement your own Listeners.
To demonstrate this, we’ll use our LoginExample activity and modify it slightly to act as a RegisterExample, where you can enter a username + password to create an account.
Our goal is to create an application which will allow user to register/create a new account and while the user type his name in the user field, to check “live” if the username is already in use or not.
After creating a new project, we’ll copy the main.xml and LoginExample.java file into their respective directories. The LoginExample.java will be renamed RegisterExample.java.
First, we do some changes to the main.xml, in order to add a second password field and an TextView, which show us if the username is available or not, as well as changing some labels/texts. The final XML can be seen below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Please enter your desired username"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Login:"
/>
<EditText
android:id="@+id/username"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/userstatus"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Password:"
/>
<EditText
android:id="@+id/password"
android:password="true"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Repeat your password:"
/>
<EditText
android:id="@+id/password2"
android:password="true"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/register_button"
android:text="Register"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/cancel_button"
android:text="Cancel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
If you now start the application, it should look like on the picture below.
LoginExample and remove unnecessary code as well as refactoring some variable names. The final code should look something like
package com.tseng.examples;
import com.tseng.examples.CheckUsernameEditText.OnUsernameAvailableListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class RegisterExample extends Activity {
// Declare our Views, so we can access them later
private EditText etUsername;
private EditText etPassword;
private EditText etPassword2;
private Button btnRegister;
private Button btnCancel;
private TextView lblUserStatus;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set Activity Layout
setContentView(R.layout.main);
// Get the EditText and Button References
etUsername = (EditText)findViewById(R.id.username);
etPassword = (EditText)findViewById(R.id.password);
etPassword2 = (EditText)findViewById(R.id.password2);
btnRegister = (Button)findViewById(R.id.register_button);
btnCancel = (Button)findViewById(R.id.cancel_button);
lblUserStatus = (TextView)findViewById(R.id.userstatus);
// Set Click Listener
btnRegister.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// create Account
}
});
btnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Close the application
finish();
}
});
}
}
So far, it looks like our LoginExample. Now the real work can begin. Our goal is to extend the EditText widget for user field and our own code to it, which will check if the username is already in use or not. First, we have to create a new class. We’ll call it CheckUsernameEditText. Once you create the application and it’s default supper class constructors, our first step is to create our own interface.
// Define our custom Listener interface
public interface OnUsernameAvailableListener {
public abstract void onAvailableChecked(String username, boolean available);
}
Our OnUsernameAvailableListener interface is quite simple and only has defined one abstract method. This method will be called, every time the username was checked and notify the user of the widget if the name was available or not. Now that we have defined the interface, we have to create a variable which will hold the listener by adding this line to top of our CheckUsernameEditText class.
OnUsernameAvailableListener onUsernameAvailableListener = null;Next one, we a setter to allow others to listen to this event.
// Allows the user to set an Listener and react to the event
public void setOnUsernameAvailableListener(OnUsernameAvailableListener listener) {
onUsernameAvailableListener = listener;
}
And last step is to add a small function which we will call every time to trigger the event (and we don’t have to repeat the checking code inside it every time)
// This function is called after the check was complete
private void OnUserChecked(String username, boolean available){
// Check if the Listener was set, otherwise we'll get an Exception when we try to call it
if(onUsernameAvailableListener!=null) {
// Only trigger the event, when we have a username
if(!TextUtils.isEmpty(username)){
onUsernameAvailableListener.onAvailableChecked(username, available);
}
}
}
So, that was the most important code in creating your own listeners. When ever you want to trigger this event, simply call OnUserChecked(username, available); Currently however, it’s never called. So we need to listen to user input and check the file. We’ll do this, by implementing the OnKeyListener interface to our CheckUserEditText class by changing the class definition to
public class CheckUsernameEditText extends EditText implements OnKeyListener {
Next we have to implement the onKey method, which will be called every time the user presses a key.
@Override
public boolean onKey(View v, int keycode, KeyEvent keyevent) {
// We only want to handle ACTION_UP events, when user releases a key
if(keyevent.getAction()==KeyEvent.ACTION_DOWN)
return false;
boolean available = true;
// Whenever a user press a key, check if the username is available
String username = getText().toString().toLowerCase();
if(!TextUtils.isEmpty(username)){
// Only perform check, if we have anything inside the EditText box
for(int i=0; i<registeredUsers.length; i++) {
if(registeredUsers[i].equals(username)){
available = false;
// Finish the loop, as the name is already taken
break;
}
}
// Trigger the Event and notify the user of our widget
OnUserChecked(username, available);
return false;
}
return false;
}
This will check the entered text if the entered username is already available inside our registeredUsers array and set the available variables value to false if the name is already registered, otherwise leave it at it’s standard value of true. Lastly it will call OnUserChecked method, passing by username and it’s status to the listening function.
This will cause an error, because we haven’t defined
registeredUsers yet. registeredUsers in our example is a simple String[] array, which will contain a few already registered names. final private static String[] registeredUsers = new String[] {
// This is just a fixed List for tutorial purposes
// in a real application you'd check this server sided or inside the database
"tseng",
"admin",
"root",
"joedoe",
"john"
};
In your real application you want to get this data from a remote server, an preferences file or from an sqlite database
TextView’s onKeyListener. So we have to add this line in every of the 3 super class constructors
//Set KeyListener to ourself this.setOnKeyListener(this);Now our CheckUsernameEditText widget is done. How ever, if we start the application we won’t notice a difference, because we haven’t replaced the username’s EditText widget with our own one. We need to change line 17 of our main.xml into
<com.tseng.examples.CheckUsernameEditTextas well as change
RegisterExample.java
private EditText etUsername; // change into private CheckUsernameEditText etUsername;and
etUsername = (EditText)findViewById(R.id.username);
// change into
etUsername = (CheckUsernameEditText)findViewById(R.id.username);
last but not least, we have to set and define the listener to our new CheckUsernameEditText widget.
// Set our new Listener to the Username EditText view
etUsername.setOnUsernameAvailableListener(new OnUsernameAvailableListener(){
@Override
public void onAvailableChecked(String username, boolean available) {
// Handle the event here
if(!available){
etUsername.setTextColor(Color.RED);
lblUserStatus.setText(username + " is already taken. Please choose another login name.");
} else {
etUsername.setTextColor(Color.GREEN);
lblUserStatus.setText(username + " is available.");
}
}
});
The onAvailableChecked will be called every time after the check was done. We can put our code here to handle the outcome. The above’s example is pretty easy and will just change the text color of the CheckUsernameTextEdit field and update the lblUserStatus label wo notify the user his desired name is available or not.
That’s all. Congratulation to your first own listener implementation.
Now we can run our application. If everything worked well, it should look like the screen shots below.
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Please enter your desired username"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Login:"
/>
<com.tseng.examples.CheckUsernameEditText
android:id="@+id/username"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/userstatus"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Password:"
/>
<EditText
android:id="@+id/password"
android:password="true"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Repeat your password:"
/>
<EditText
android:id="@+id/password2"
android:password="true"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/register_button"
android:text="Register"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/cancel_button"
android:text="Cancel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
CheckUsernameEditText.java
package com.tseng.examples;
import com.tseng.examples.CheckUsernameEditText.OnUsernameAvailableListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class RegisterExample extends Activity {
// Declare our Views, so we can access them later
private CheckUsernameEditText etUsername;
private EditText etPassword;
private EditText etPassword2;
private Button btnRegister;
private Button btnCancel;
private TextView lblUserStatus;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set Activity Layout
setContentView(R.layout.main);
// Get the EditText and Button References
etUsername = (CheckUsernameEditText)findViewById(R.id.username);
etPassword = (EditText)findViewById(R.id.password);
etPassword2 = (EditText)findViewById(R.id.password2);
btnRegister = (Button)findViewById(R.id.register_button);
btnCancel = (Button)findViewById(R.id.cancel_button);
lblUserStatus = (TextView)findViewById(R.id.userstatus);
// Set our new Listener to the Username EditText view
etUsername.setOnUsernameAvailableListener(new OnUsernameAvailableListener(){
@Override
public void onAvailableChecked(String username, boolean available) {
// Handle the event here
if(!available){
etUsername.setTextColor(Color.RED);
lblUserStatus.setText(username + " is already taken. Please choose another login name.");
} else {
etUsername.setTextColor(Color.GREEN);
lblUserStatus.setText(username + " is available.");
}
}
});
// Set Click Listener
btnRegister.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// create Account
}
});
btnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Close the application
finish();
}
});
}
}
RegisterExample.java
package com.tseng.examples;
import java.lang.reflect.Array;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.EditText;
import android.widget.TextView;
public class CheckUsernameEditText extends EditText implements OnKeyListener {
OnUsernameAvailableListener onUsernameAvailableListener = null;
final private static String[] registeredUsers = new String[] {
// This is just a fixed List for tutorial purposes
// in a real application you'd check this server sided or inside the database
"tseng",
"admin",
"root",
"joedoe",
"john"
};
public CheckUsernameEditText(Context context) {
super(context);
// Set KeyListener to ourself
this.setOnKeyListener(this);
}
public CheckUsernameEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Set KeyListener to ourself
this.setOnKeyListener(this);
}
public CheckUsernameEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// Set KeyListener to ourself
this.setOnKeyListener(this);
}
// Allows the user to set an Listener and react to the event
public void setOnUsernameAvailableListener(OnUsernameAvailableListener listener) {
onUsernameAvailableListener = listener;
}
// This function is called after the check was complete
private void OnUserChecked(String username, boolean available){
// Check if the Listener was set, otherwise we'll get an Exception when we try to call it
if(onUsernameAvailableListener!=null) {
// Only trigger the event, when we have a username
if(!TextUtils.isEmpty(username)){
onUsernameAvailableListener.onAvailableChecked(username, available);
}
}
}
@Override
public boolean onKey(View v, int keycode, KeyEvent keyevent) {
// We only want to handle ACTION_UP events, when user releases a key
if(keyevent.getAction()==KeyEvent.ACTION_DOWN)
return false;
boolean available = true;
// Whenever a user press a key, check if the username is available
String username = getText().toString().toLowerCase();
if(!TextUtils.isEmpty(username)){
// Only perform check, if we have anything inside the EditText box
for(int i=0; i<registeredUsers.length; i++) {
if(registeredUsers[i].equals(username)){
available = false;
// Finish the loop, as the name is already taken
break;
}
}
// Trigger the Event and notify the user of our widget
OnUserChecked(username, available);
return false;
}
return false;
}
// Define our custom Listener interface
public interface OnUsernameAvailableListener {
public abstract void onAvailableChecked(String username, boolean available);
}
}
That’s all. I hope you enjoyed it. If you have any questions, post it in the comments.No related posts.






Could’nt you please provide the source code? I’m trying to create my own Listener for an TextEdit widget myself, but can’t get it to work. I think the full source can help me.
Thanks
nice post, thanks
[...] This post was mentioned on Twitter by Shoaib Shaikh. Shoaib Shaikh said: your very own listeners [Droid] http://tseng-blog.nge-web.net/blog/2009/02/17/how-implement-your-own-listener-android-java/ [...]
Thanks, this helped me a lot
I am new to mobile development and have enjoyed going over how to implement listeners but when I tried implementing how to create my own listener, somehow the code did not work. can you please post the whole source code to see where I went wrong.
thanx,
-Zak
This tutorial is great for understanding how a listener works. The problem is that this method is not actually usable in real life apps as it opens listeners on the main thread of their containing class. Doing so defeats the purpose of using listeners altogether, as they are almost always used for asynchronous operations callbacks from the class that invokes them.
[...] How to implement your own Listener in Android/Java [...]
Benedict, it is a great post thanks for posting it!
Thanks for this post, but I m sorry it doesn’t work, I tried it, the process is stopped.
can you give us more details if possible,
thank you again
Please note that at the very end of the article, the source code for RegisterExample.java and CheckUsernameEditText.java is reversed.
Thank you a lot. It is most full information how to create custom listener for Android in custom View i found even before.
VoIP trunk to Ukraine mobile operator – Voip trunk to Ukraine mobile operator http://voiptrunk.at.ua/
Good post.. i need to know about URL listener in android would you help me in this regard
Fastest Free Image Hosting. Porsche Boxter 2023 New Model
Nice post, thanks!
Btw, is there any way to avoid “accidentally” double clicking on btnRegister, for example?
I mean, if i click too fast on that screen button, the program fires twice the action defined in the onClick().
Thanks in advance!
Thanks! Extremely useful!
FYI..
The titles of
RegisterExample.java
CheckUsernameEditText.java
switched . though not a problem just informing u. Nice post..
are there any other problems with the source code?(other then the switch )
i try to do this step by step and all so copy paste
this not working for me
useing eclipse
and i get errors on all the @Override still even after removeing them sens they dont really do any thing
this not working
geting :
fatal exception: main
03-10 23:13:04.156: E/AndroidRuntime(539): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.tseng.examples/com.tseng.examples.RegisterExampleActivity}: java.lang.ClassNotFoundException: com.tseng.examples.RegisterExampleActivity
??
Why do we need so many Constructers for CheckUserNameEditText???