Android Adventures - Basic Controls And Events
Written by Mike James   
Wednesday, 17 July 2013
Article Index
Android Adventures - Basic Controls And Events
Basic Input Controls
Checkboxes
Switches and Toggle Buttons

Working with Android Studio makes building the UI easy with an interactive editor, but you still need to find out how to handle the things it isn't quite so good at. In this chapter of our ebook on Android the easy way we look at the basic UI components and general event handling - i.e beyond onClick. 

IMPORTANT NOTE: This chapter is currently being live updated - sorry for any formating and other minor problems.

 

Android Adventures With Android Studio

Contents

  1. Getting Started With Android Studio
  2. The Activity And The UI
  3. Building The UI and a Calculator App
  4. Lifecycle and State
  5. Basic Controls And Events
  6. Spinners
  7. Pickers
  8. UI Graphics A Deep Dive
  9. ListView And Adapters
  10. Introducing Fragments
  11. Fragments and XML
  12. Fragment And Activity Working Together
  13. Managing Fragments
  14. Custom dialogs using DialogFragment
  15. Dialog Classes In DialogFragment
  16. A NumberPicker DialogFragment Project
  17. ViewPager

If you are interested in creating custom template also see:

Custom Projects In Android Studio

Androidgears

 

 

 


 

We have looked at the general principles of building a UI but now we have to spend some time looking at the most basic components that can be used to build an application.

We also need to find out how to work with any event and not just onClick. Even though most controls can be used very successfully using just the onClick event - there are other types of event that cannot be handled simply by setting an onEvent property in the Property Window. In this chapter we look in depth at Android event handling.

As before the emphasis will be on using Android Studio and the Layout editor to get as much of the work done as possible. 

Let's start with the problem of how to write an event handler. 

The General Android Event Handler

If you have used languages other than Java you might expect event handlers to simply be functions that are passed to controls to register them as event listeners - i.e. functions that are called when an event occurs. You might even have used an IDE that adds event handlers automatically for you but Android Studio doesn't currently do this - you have to add code to handle and event. It does however help with the automatic generation of this code. 

Events in Java are slightly more complicated because you cannot pass a function as an argument like you can in JavaScript, C# and many other languages - you can in the latest version of Java but it will be sometime before UI frameworks and Android catchup if they ever do. In Java functions can only exist as methods of objects so if you want to pass a function you have to pass an object that has the function as a method.

As a result what has to be passed to register an event listener is more complicated in Java than in many other languages. The way that it all works was invented in the early Java UI frameworks such as GWT and later refined in Swing. Android uses the same approach.

As already mentioned you can't pass a function you have to pass an object which contains a function that can handle the event. Clearly the event handling function has to be capable of handling the event and hence it is defined depending on the type of the event.

For example an onClick event needs a handler that returns void and accepts a View object, which is the object the event occurred on. 

To make sure that an event listener has the right sort of event handling function events are defined using an Interface. 

If you recall an interface is like a class but it simply defines the functions that a class has to support. If a class inherits or implements an interface then you have to write code for each function defined in the interface. 

For example the onClickListener is an interface that defines a single function 

void onClick(View v)

any class that implements onClickListener has to have an onClick function of this type. 

To create an event handler for the onClick event you have to do the following things:

  1. Create a new class that implements onClickListener
  2. Define your custom onClick event handler within the class
  3. create an instance of the new class within the Activity
  4. use the button's setOnClickListener method to add the listener object created in step 3 to the event. 

Sounds complicated - well it is and there are ways of simplifying it but first let's see how it is done exactly as described. 

This is not the best way to do the job but it is how it all works in principle and it is important to understand what is going on. 

This is as much an exercise for Java beginners as it is an explanation of event handling. If your Java is good feel free to skip ahead. 

To implement an event handler for the onClick event first we need to add a new class to the project. Right click on the folder under the Java folder and select New, Java Class and call it MyOnClickListener. 

Note: For users of other languages it is worth pointing out that Java has an almost unbreakable convention that each class is stored in its own file of the the same name. 

Next edit MyOnClickListener to read:

import android.view.View;
public class MyOnClickListener 
            implements View.OnClickListener {
 
 public void onClick(View v){
   //process event
 }
}

Notice we have now created a class with a single method which is our event handler. In a real case you would write lots of code in place of the single remark that did something when the event occurred.

That is step one completed. Next we mover to the Activity and first retrieve the Button object:

Button button=(Button)findViewById(R.id.button);

Next we create an instance of our event listener:

MyOnClickListener Listener=
                        new MyOnClickListener();

and finally we use the button's setOnClickEventListener method to connect its onClick event to our new listener object:

button.setOnClickListener(Listener);

That is putting it all together:

@Override
protected void onCreate(
                  Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Button  button=(Button)findViewById(R.id.button);
 MyOnClickListener Listener=new 
                        MyOnClickListener();
 button.setOnClickListener(Listener);
}

Now if you run the program you will find that the onClick function in the MyOnClickListener instance is called when the button is clicked. 

The same overall method works for any event. You simply have to discover the name of the event listener interface, create a class that implements it, create an instance of the class and register the listener with the component that generates the event.

This isn't very practical because you are going to need to create a new class for every event you want to handle and in addition these classes are going to contain one method and be instantiated just once. 

There has to be a better way! 

Now that you have seen the fundamentals of Java event handling we can example the two ways that it tends to be done in practice.

Two Ways To Handle An Event

To avoid the overheads you can use one of two possible methods -

  • use an anonymous class
    or
  • implement the interface in the activity. 

Anonymous class

Java has anonymous classes for just the situation we are trying to solve. You can take an interface and implement it as a class and create an instance in one go. This is just shorthand, syntactic sugar if you like for what we did in the previous section. It creates a class and from it an instance of the class in one economic step. 

For example:

MyInterface instance=new MyInterface{
  functions which are needed to 
  implement MyInterface
} 

This creates an instance of the implementation of MyInterface that is contained within the braces. No need to define a class to get an instance - but notice you can only get one instance.

So for our onClick event handler using an anonymous class makes things much easier because we don't need a separate file to hold the new class and in fact we don't even need the new class just:

View.OnClickListener Listener=
                      new View.OnClickListener(){
 @Override
 public void onClick(View view) {
  //Implement event handling
 }
}

and the instance of our custom listener complete with our onClick event handler is ready to be used as before:

button.setOnClickListener(Listener);

Of course you can save a variable and simply use the annoymous class in the setOnClickListener as in:

button.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {

  //Implement event handling
 }
});

We no long have to use the Listener variable but the cost is that we need to be careful to remember to close the function call with a right parenthesis. 

The really good news is that Android Studio will help you create the annoymous class. If you start to type in OnClickListener it will provide you with options to complete the name and you can select OnClickListener - it will then generate dummy functions for all of the methods defined in the interface. All you have to do is provide the code in the body of each of the functions that does what you want. 

Implement the interface in the activity

The alternative way of doing things is to simply use the MainActivity class to implement the event listener interface. This seems a little strange when you first see it but it is the closest approach to the way other languages do the job.

For example, to handle the onClick event we need to add the "implements" for the interface to the Activity: 

public class MainActivity extends Activity
  implements View.OnClickListener {

Now all that has to happen is that the Activity class has to implement the onClick event handler:

@Override
public void onClick(View view) {
//Handle Event
}

All that remains is to add the event listener using setOnClickEventListener but what is the instance?

If you recall what happens is that the system creates an instance of the MainActivity class to get your app running and the current instance of a class is always "this". So we need to add to the onCreate method:

button.setOnClickListener(this);

In many ways this last way of doing things is the simplest. It has the disadvantage that you have to add an "implements" for each event you are going to handle but this could be an advantage in that it enables you to see what events are being used. Also notice that using this method you set all of the event handlers using

somecontrol.setOnSomeEvent(this);

This also implies that you will be using the same event handler for an event irrespective of which control generated the event. If you want to use multiple event handlers - one for each control then you need to use the anonymous class approach.

Which Approach To Event Handlers Should You Use?

In practice the annonymous class approach seems to be the simplest and it is the one used in the rest of this book. If you want to use the XML or implement the interface in the activity approach then this should cause no problems. 



Last Updated ( Monday, 02 March 2015 )
 
 

   
Copyright © 2015 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.