Implementing callbacks

Another critical functionality from our EPG that we haven't covered yet is the ability to actually do something when clicking on a TV program. If we want to do something useful with our EPG, rather than just showing the titles of what is coming, we must implement this functionality.

This implementation is quite straightforward and will handle the logic to an external listener or callback. It would also be quite easy to modify the source code to implement some custom behavior on the EPG itself.

To begin, we create a new interface inside the EPG class with one single method:

interface EPGCallback { 
    void programClicked(Channel channel, Program program); 
} 
 

This method will be called whenever we click on a TV program, and whoever is implementing this callback will get both the Channel and the TV Program.

Now, let's modify the onTouchEvent() method to handle this new functionality:

if (event.getX() < frChNameWidth) { 
 
    ... 
     
} else { 
    clickProgram(event.getX(), event.getY()); 
} 
 

In our previous code, we were checking only if we clicked on the channel area of the screen. Now we can use the other area to detect if we have clicked inside a TV program.

Let's now implement the clickProgram() method:

private void clickProgram(float x, float y) { 
    long ts = getHorizontalPositionTime(scrollXTarget + x -
frChNameWidth); int channel = (int) ((y + frScrollY - timebarHeight) /
channelHeight); ArrayList<Program> programs = channelList[channel].getPrograms(); for (int i = 0; i < programs.size(); i++) { Program pr = programs.get(i); if (ts >= pr.getStartTime() && ts < pr.getEndTime()) { if (callback != null) { callback.programClicked(channelList[channel], pr); } break; } } }

We first convert the horizontal position where the user clicks into a timestamp, and, with the vertical position of the touch event, we can determine the channel. With the channel and the timestamp, we could check which program the user has clicked inside and call the callback with that information.

In the GitHub example, we added a dummy listener that will only log the channel and program clicked:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
 
    EPG epg = (EPG) findViewById(R.id.epg_view); 
    epg.setCallback(new EPG.EPGCallback() { 
        @Override 
        public void programClicked(Channel channel, Program program) { 
            Log.d("EPG", "program clicked: " + program.getName() + "
channel: " + channel.getName()); } }); populateDummyChannelList(epg); }

There is also a populateDummyChannelList() method in this Activity onCreate. This method will only populate random channel and TV program data and should be removed if connecting with a real EPG data provider.

The whole example can be found in the Example33-EPG folder on the GitHub repository.