//
you're reading...
HCI, Tech

Extending Android View to Create Clickable Drawables

Adroid API has a poor design of Drawable, not allowing them to establish a parent-children relationship with the app’s view, but requiring the view to redraw them on-the-fly where those drawn Drawables are just their dead non-interactive portraits.

To make drawable interactive, or more specifically, clickable, I choose to bypass the class Drawable; instead I extend View (which is clickable) and then draw the Drawables in it. The view-extending class provides overridable onTouchEvent wherein I can determine the spatial relationship between the touch and the drawn Drawables (though, in a mathematical way) so as to make them (appear) clickable.

Below is an simple example. To use this code, you need to setContentView it in your onCreate method where it will show an oval that changes its color when clicked. To make it simple, the code does not take care of everything and might contain glitches. You fix them.


package me.xiangchen.basicstuff;

import java.util.ArrayList;
import java.util.Hashtable;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

public class InteractiveDrawable extends View {

private final int radius = 100;

 private Canvas mCanvas;
 private int xTouch;
 private int yTouch;
 private Paint mPaint;

 private Hashtable mHashTable;

 public InteractiveDrawable(Context context, Paint paint) {
 super(context);
 mPaint = new Paint();
 mPaint.setColor(paint.getColor());
 mPaint.setAlpha(160);
 mPaint.setDither(true);
 mPaint.setAntiAlias(true);
 mPaint.setStyle(Paint.Style.FILL);
 mPaint.setStrokeJoin(Paint.Join.ROUND);
 mPaint.setStrokeCap(Paint.Cap.ROUND);
 mPaint.setStrokeWidth(3);
 }

 private boolean isInShape(int x, int y)
 {
 boolean result = false;
 if(Math.sqrt((x - xTouch) * (x - xTouch) + (y - yTouch) * (y - yTouch)) < radius)
 {
 result = true;
 }
 return result;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event)
 {
 int action = event.getAction();
 if(action == MotionEvent.ACTION_DOWN)
 {
 if(isInShape((int)event.getX(), (int)event.getY()))
 {
 int tmpR = (int)(Math.random() * 255);
 int tmpG = (int)(Math.random() * 255);
 int tmpB = (int)(Math.random() * 255);
 mPaint.setARGB(160, tmpR, tmpG, tmpB);
 this.invalidate();
 }
 }
 return true;
 }

@Override
 // decides the size of this view
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

 Display display = ((WindowManager)this.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
 // the view occupies the entire screen. however, this is not the only option
 setMeasuredDimension(display.getWidth(), display.getHeight());
 }

 @Override
 protected void onDraw(Canvas canvas) {
 RectF tmpRectF = new RectF();
 tmpRectF.set(xTouch - radius, yTouch - radius, xTouch + radius, yTouch + radius);
 canvas.drawOval(tmpRectF, mPaint);
 }
}

Advertisements

About Xiang 'Anthony' Chen

Making an Impact in Your Life

Discussion

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Twitter Updates

%d bloggers like this: