Android: TouchDelegate tutorial

20 Jul 2010    

I’ve been doing quite a lot of Android development lately. Most of the time the API Specification and Dev Guide are quite complete, but sometimes information is difficult to find. An example of this is the TouchDelegate class. According to the Specification TouchDelegate is a “Helper class to handle situations where you want a view to have a larger touch area than its actual view bounds.”. That’s exactly what it does and most application developers are likely to feel the need to use it.

Since I couldn’t find an example on how to actually use it, I wrote this small tutorial. It’s rather easy, but does expect you have some very basic Android knowledge (eg. how to build and use an Activity).

First up: the simplest layout file in history: (eg. tutorial.xml)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/FrameContainer"
	android:layout_width="fill_parent" android:layout_height="fill_parent"
	xmlns:android="http://schemas.android.com/apk/res/android">
			<ImageButton android:id="@+id/tutorial"
				android:layout_width="wrap_content" android:layout_height="wrap_content"
				android:background="@null" android:src="@drawable/tutorial" />
</FrameLayout>

Put this file in res/layout/. Make sure you have a drawable (an image), called tutorial.png (or any other supported format) located in res/drawable/ The layout file only contains a FrameLayout with an ImageButton in it, which is all we need for this tutorial. I choose an ImageButton , but any View will do.

If you have questions regarding the layout file, visit the UI guide.

First thing to do, is to reference our layout file in the Activity, using

setContentView(R.layout.tutorial);

In order to have a larger touch area than the actual view bounds, we need to get a hold of the parent of our ImageButton: the FrameLayout  called FrameContainer. We post a small Runnable on the UI thread. In that Runnable we instantiate a Rect that specifies the bounds for our TouchDelegate. We then get the hit rectangle of the tutorialButton. The coordinates of the Rect are public, so we change them to what we want them to be. In the example I made the touch area of the tutorial ImageButton larger on the right side. After we have our Rect, we build a TouchDelegate with it and we set that TouchDelegate to the parent of our tutorialButton. I added a random message in onClick for testing purposes.

Code snippet:

		View mParent = findViewById(R.id.FrameContainer);
		mParent.post(new Runnable() {
			@Override
			public void run() {
				Rect bounds = new Rect();
				ImageButton mTutorialButton = (ImageButton) findViewById(R.id.tutorial);
				mTutorialButton.setEnabled(true);
				mTutorialButton.setOnClickListener(new View.OnClickListener() {
					public void onClick(View view) {
						Toast.makeText(TouchDelegateActivity.this, "Test TouchDelegate", Toast.LENGTH_SHORT).show();
					}
				});

				mTutorialButton.getHitRect(bounds);
				bounds.right += 50;
				TouchDelegate touchDelegate = new TouchDelegate(bounds, mTutorialButton);

				if (View.class.isInstance(mTutorialButton.getParent())) {
					((View) mTutorialButton.getParent()).setTouchDelegate(touchDelegate);
				}
			}
		});

That’s it. The actual bounds of your Rect might require some experimenting when used in an actual layout. Feel free to post remarks and questions.