Skip to content

Instantly share code, notes, and snippets.

@ErikHellman
Created July 24, 2013 09:56
Show Gist options
  • Save ErikHellman/6069322 to your computer and use it in GitHub Desktop.
Save ErikHellman/6069322 to your computer and use it in GitHub Desktop.
A very simple example of using multi-touch on Android to build a custom View for finger painting. This example uses the Path class from the android.graphics package. Feel free to use this code as you wish for your own multi-touch apps.
public class PaintView extends View {
public static final int MAX_FINGERS = 5;
private Path[] mFingerPaths = new Path[MAX_FINGERS];
private Paint mFingerPaint;
private ArrayList<Path> mCompletedPaths;
private RectF mPathBounds = new RectF();
public PaintView(Context context) {
super(context);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PaintView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mCompletedPaths = new ArrayList<Path>();
mFingerPaint = new Paint();
mFingerPaint.setAntiAlias(true);
mFingerPaint.setColor(Color.BLACK);
mFingerPaint.setStyle(Paint.Style.STROKE);
mFingerPaint.setStrokeWidth(6);
mFingerPaint.setStrokeCap(Paint.Cap.BUTT);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Path completedPath : mCompletedPaths) {
canvas.drawPath(completedPath, mFingerPaint);
}
for (Path fingerPath : mFingerPaths) {
if (fingerPath != null) {
canvas.drawPath(fingerPath, mFingerPaint);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int pointerCount = event.getPointerCount();
int cappedPointerCount = pointerCount > MAX_FINGERS ? MAX_FINGERS : pointerCount;
int actionIndex = event.getActionIndex();
int action = event.getActionMasked();
int id = event.getPointerId(actionIndex);
if ((action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) && id < MAX_FINGERS) {
mFingerPaths[id] = new Path();
mFingerPaths[id].moveTo(event.getX(actionIndex), event.getY(actionIndex));
} else if ((action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP) && id < MAX_FINGERS) {
mFingerPaths[id].setLastPoint(event.getX(actionIndex), event.getY(actionIndex));
mCompletedPaths.add(mFingerPaths[id]);
mFingerPaths[id].computeBounds(mPathBounds, true);
invalidate((int) mPathBounds.left, (int) mPathBounds.top,
(int) mPathBounds.right, (int) mPathBounds.bottom);
mFingerPaths[id] = null;
}
for(int i = 0; i < cappedPointerCount; i++) {
if(mFingerPaths[i] != null) {
int index = event.findPointerIndex(i);
mFingerPaths[i].lineTo(event.getX(index), event.getY(index));
mFingerPaths[i].computeBounds(mPathBounds, true);
invalidate((int) mPathBounds.left, (int) mPathBounds.top,
(int) mPathBounds.right, (int) mPathBounds.bottom);
}
}
return true;
}
}
@Sebpt55
Copy link

Sebpt55 commented May 3, 2022

Wow this code looks great, thanks for the amazing response, please don't be sorry for being late when your reply is of this quality. I have a few questions I hope you don't mind. You comment on initGrid saying call this code in onCreate so would it look something like this?
I've added a timer as I want the results to appear after 10 seconds of intense drawing. I know its not this simple but I hope I am getting the right idea.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initGrid();
        setGridTile();
        
        final Handler handler = new Handler(Looper.getMainLooper());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, getFilledPercentages(), Toast.LENGTH_LONG).show();
            }
        }, 10000);

Thanks again.

@TypeSafeSchwalbe
Copy link

You are correct. initGrid is supposed to be called inside of onCreate, like you wrote. If you want to empty the grid (to start the game again), you can call initGrid again. setGridTile can then be called in your onTouchEvent-method, where you pass the ID of the finger (or color) and the position.

@Cfas7983
Copy link

If i want to draw a circle graphic by using canvas.drawCircle
how can I do

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment