[TUT] Click item in a ListView to show YouTube Video

Following on from the popular ‘Show YouTube Feed for a Users Videos in a ListView’ someone requested that when you click on one of the individual videos in the list that it links off to the YouTube video.

This in itself this is quite simple, but getting the architecture right and having the data you need in the right place takes a little bit of thought.

Using an interface it’s possible to do all the logic within the custom ListView we have written but still allow the Activity to receive the callback and do whatever it wants with the video i.e. start a video viewing Intent.

This blog post is going to brush over the basics of populating the ListView (as this is done in the previously mentioned tutorial) and just talk about how you can add a custom listener to your ListView that sends back to the activity the data for each row.

The whole source code is linked at the bottom of the post and I am just going to talk about the relevant code for the click listener here.

Firstly we need to define an Interface, interfaces allow you to declare that your class can do something but it leaves the implementation up to the class. i.e. if you had an Interface called “Move” and a method called “useLegs()” you could add this interface to your Activity. The activity can now be called by other classes that want to “Move” and they will call the useLegs method. The powerful thing is, it’s up to your activity what happens in the useLegs() method! It could have robot legs .. four legs … run or hop, it doesn’t matter its up to you!

If you don’t quite get that take a look at this. Here is the interface we have made for a special video listener:


package com.blundell.tut.ui;

import com.blundell.tut.domain.Video;

public interface VideoClickListener {

	public void onVideoClicked(Video video);
	
}

It’s declaring it is a VideoClickListener and wants you to implement a method called onVideoClicked. So that means if you implement this interface you will have to react to some type of video being clicked and you get passed the video.
(This sounds great if we were passed the video that was clicked from the list 😉 ).

Now that we have the interface there are two things we need to do. The activity needs to implement the interface (to receive calls to the onVideoClicked method) and also something needs to send those calls.

Let’s send the calls first. In our custom ListView we create a reference to this interface then when the list is clicked we simply call the method. It makes much more sense in practice, look:

package com.blundell.tut.ui.widget;

import java.util.List;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.blundell.tut.domain.Video;
import com.blundell.tut.ui.VideoClickListener;
import com.blundell.tut.ui.adapter.VideosAdapter;

/**
 * @author paul.blundell
 */
public class VideosListView extends ListView implements android.widget.AdapterView.OnItemClickListener {

	private List<Video> videos;
	private VideoClickListener videoClickListener;

	public VideosListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public VideosListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public VideosListView(Context context) {
		super(context);
	}

	public void setVideos(List<Video> videos){
		this.videos = videos;
		VideosAdapter adapter = new VideosAdapter(getContext(), videos);
		setAdapter(adapter);
		// When the videos are set we also set an item click listener to the list
		// this will callback to our custom list whenever an item it pressed
		// it will tell us what position in the list is pressed
		setOnItemClickListener(this);
	}
	
	// Calling this method sets a listener to the list
	// Whatever class is passed in will be notified when the list is pressed
	// (The class that is passed in just has to 'implement VideoClickListener'
	// meaning is has the methods available we want to call)
	public void setOnVideoClickListener(VideoClickListener l) {
		videoClickListener = l;
	}
	
	@Override
	public void setAdapter(ListAdapter adapter) {
		super.setAdapter(adapter);
	}

	// When we receive a notification that a list item was pressed
	// we check to see if a video listener has been set
	// if it has we can then tell the listener 'hey a video has just been clicked' also passing the video
	@Override
	public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
		if(videoClickListener != null){
			videoClickListener.onVideoClicked(videos.get(position));
		}
	}
}

So thats it when your ListView is clicked it will tell whatever is listening that it has been clicked and pass the video! However nothing is listening yet we need to update our activity:

package com.blundell.tut.ui.phone;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;

import com.blundell.tut.R;
import com.blundell.tut.domain.Library;
import com.blundell.tut.domain.Video;
import com.blundell.tut.service.task.GetYouTubeUserVideosTask;
import com.blundell.tut.ui.VideoClickListener;
import com.blundell.tut.ui.widget.VideosListView;

/**
 * The Activity can retrieve Videos for a specific username from YouTube</br>
 * It then displays them into a list including the Thumbnail preview and the title</br>
 * There is a reference to each video on YouTube as well but this isn't used in this tutorial</br>
 * </br>
 * <b>Note<b/> orientation change isn't covered in this tutorial, you will want to override
 * onSaveInstanceState() and onRestoreInstanceState() when you come to this
 * </br>
 * @author paul.blundell
 */
public class MainActivity extends Activity implements VideoClickListener {
    // A reference to our list that will hold the video details
	private VideosListView listView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        listView = (VideosListView) findViewById(R.id.videosListView);
        // Here we are adding this activity as a listener for when any row in the List is 'clicked'
        // The activity will be sent back the video that has been pressed to do whatever it wants with
        // in this case we will retrieve the URL of the video and fire off an intent to view it
        listView.setOnVideoClickListener(this);
    }

    public void getUserYouTubeFeed(View v){
    	new Thread(new GetYouTubeUserVideosTask(responseHandler, "blundellp")).start();
    }
   
	Handler responseHandler = new Handler() {
		public void handleMessage(Message msg) {
			populateListWithVideos(msg);
		};
	};

	private void populateListWithVideos(Message msg) {
		Library lib = (Library) msg.getData().get(GetYouTubeUserVideosTask.LIBRARY);
		listView.setVideos(lib.getVideos());
	}
	
	@Override
	protected void onStop() {
		responseHandler = null;
		super.onStop();
	}

	// This is the interface method that is called when a video in the listview is clicked!
	// The interface is a contract between this activity and the listview
	@Override
	public void onVideoClicked(Video video) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(video.getUrl()));
		startActivity(intent);
	}
}

Hope I’ve made it clear enough. Now when the list is clicked our activity knows about it. Not only does it know though, it also is passed the video that has been clicked letting us act upon it.

All source code has been commented to help you out!

Enjoy!

Eclipse Source Project – User Feed YouTube Click Through Tut

30 thoughts on “[TUT] Click item in a ListView to show YouTube Video

  1. Very nice tutorial. http://www.itcuties.com has youtube player for single video if u have the video id. This opens the video in app. Is there anyway u can direct me on how to merge the class from itcuties with this code inorder for app video not to open with browser when clicked

    1. Sure MainActivity line 69, this is what you would need to change. The Video object has video.getUrl() which you could use with itcuties

  2. best code in the whole internet about fetching youtube videos from their server

Comments are closed.