Last active
March 26, 2018 09:22
-
-
Save dominicthomas/35483ed870cdc2fe4ec2 to your computer and use it in GitHub Desktop.
A simple activity with a drawing view and a rainbow brush. Proof of concept. Potential to be improved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.Activity; | |
import android.graphics.Bitmap; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.graphics.Path; | |
import android.os.Bundle; | |
import android.support.v7.app.ActionBarActivity; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
public class MainActivity extends ActionBarActivity { | |
DrawingView mDrawingView; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
mDrawingView = new DrawingView(this); | |
setContentView(mDrawingView); | |
} | |
public class DrawingView extends View { | |
public int width; | |
public int height; | |
private Bitmap mBitmap; | |
private Canvas mCanvas; | |
private Paint mBitmapPaint; | |
private Paint mCirclePaint; | |
private Path mCirclePath; | |
private Paint mLinePaint; | |
private Path mLinePath; | |
private float mX, mY; | |
private static final float TOUCH_TOLERANCE = 10; | |
private int mCurrentColorIndex = 0; | |
private static final int BRUSH_RADIUS = 30; | |
private final List<Integer> mColoursList; | |
public DrawingView(Activity c) { | |
super(c); | |
mColoursList = initRainbowColors(); | |
mBitmapPaint = new Paint(Paint.DITHER_FLAG); | |
mCirclePath = new Path(); | |
mCirclePaint = new Paint(); | |
mCirclePaint.setAntiAlias(true); | |
mCirclePaint.setDither(true); | |
mCirclePaint.setColor(getColorIndex()); | |
mCirclePaint.setStyle(Paint.Style.FILL); | |
mCirclePaint.setStrokeJoin(Paint.Join.ROUND); | |
mLinePath = new Path(); | |
mLinePaint = new Paint(); | |
mLinePaint.setAntiAlias(true); | |
mLinePaint.setDither(true); | |
mLinePaint.setColor(getColorIndex()); | |
mLinePaint.setStyle(Paint.Style.STROKE); | |
mLinePaint.setStrokeJoin(Paint.Join.ROUND); | |
mLinePaint.setStrokeCap(Paint.Cap.ROUND); | |
mLinePaint.setStrokeWidth(BRUSH_RADIUS * 2); | |
} | |
private List<Integer> initRainbowColors(){ | |
final List<Integer> colorsList = new ArrayList<>(); | |
for (int r = 0; r < 100; r++) colorsList.add(Color.rgb(r * 255 / 100, 255, 0)); | |
for (int g = 100; g > 0; g--) colorsList.add(Color.rgb(255, g * 255 / 100, 0)); | |
for (int b = 0; b < 100; b++) colorsList.add(Color.rgb(255, 0, b * 255 / 100)); | |
for (int r = 100; r > 0; r--) colorsList.add(Color.rgb(r * 255 / 100, 0, 255)); | |
for (int g = 0; g < 100; g++) colorsList.add(Color.rgb(0, g * 255 / 100, 255)); | |
for (int b = 100; b > 0; b--) colorsList.add(Color.rgb(0, 255, b * 255 / 100)); | |
colorsList.add(Color.rgb(0, 255, 0)); | |
return colorsList; | |
} | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); | |
mCanvas = new Canvas(mBitmap); | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
super.onDraw(canvas); | |
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); | |
canvas.drawPath(mCirclePath, mCirclePaint); | |
canvas.drawPath(mLinePath, mLinePaint); | |
} | |
private void touchStart(float x, float y) { | |
mLinePath.reset(); | |
mLinePath.moveTo(x, y); | |
mX = x; | |
mY = y; | |
} | |
private void touchMove(float x, float y) { | |
float dx = Math.abs(x - mX); | |
float dy = Math.abs(y - mY); | |
mLinePath.reset(); | |
mLinePath.moveTo(x, y); | |
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { | |
mLinePath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); | |
mCanvas.drawPath(mLinePath, mLinePaint); // draw to canvas each move | |
mCirclePath.reset(); | |
mCirclePath.addCircle(mX, mY, BRUSH_RADIUS, Path.Direction.CW); | |
mCanvas.drawPath(mCirclePath, mCirclePaint); // draw to canvas each move | |
mX = x; | |
mY = y; | |
} | |
} | |
private void touchUp() { | |
mLinePath.lineTo(mX, mY); | |
mCirclePath.reset(); | |
// commit the path to our offscreen | |
mCanvas.drawPath(mLinePath, mLinePaint); | |
// kill this so we don't double draw | |
mLinePath.reset(); | |
} | |
final Random r = new Random(); | |
@Override | |
public boolean onTouchEvent(MotionEvent event) { | |
float x = event.getX(); | |
float y = event.getY(); | |
switch (event.getAction()) { | |
case MotionEvent.ACTION_DOWN: | |
touchStart(x, y); | |
invalidate(); | |
break; | |
case MotionEvent.ACTION_MOVE: | |
touchMove(x, y); | |
mLinePaint.setColor(mColoursList.get(getColorIndex())); | |
mCirclePaint.setColor(mColoursList.get(getColorIndex())); | |
invalidate(); | |
break; | |
case MotionEvent.ACTION_UP: | |
touchUp(); | |
invalidate(); | |
break; | |
} | |
return true; | |
} | |
private int getColorIndex(){ | |
int size = mColoursList.size(); | |
if(mCurrentColorIndex == size){ | |
mCurrentColorIndex = 0; | |
} | |
return mCurrentColorIndex++; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment