Canvas al ajillo

52
@glomadria n Adrián García Lomas Canvas al ajillo

Transcript of Canvas al ajillo

Page 1: Canvas al ajillo

@glomadrian

Adrián García Lomas

Canvas al ajillo

Page 2: Canvas al ajillo

Lo que me gustaría que me hubieran contado sobre Canvas y Custom Views

Page 3: Canvas al ajillo

Los detalles importan

Adapta las vistas a las necesidades no las necesidades a las vistasUn mundo diferente y divertido

Page 4: Canvas al ajillo

Ciclo de vidade una vista

Page 5: Canvas al ajillo

Constructor

onAttachedToWindow()

onMeassure()

onLayout()

Page 6: Canvas al ajillo

dispatchDraw()

draw()

onDraw()

invalidate()

Page 7: Canvas al ajillo

Animación de carga

Page 8: Canvas al ajillo

public Loading(Context context) { super(context); initialize();}

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

public Loading(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize();}

private void initialize() { circlePaint = new Paint(); circlePaint.setColor(circleColor); circlePaint.setAntiAlias(true); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setStrokeWidth(circleStroke);}

Page 9: Canvas al ajillo

¿Qué pasa con el tamaño de la vista?

Page 10: Canvas al ajillo

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; createCircle();}

private void createCircleArea() {int circleAreawidth = width - strokeWidth;int circleAreaHeight = heihgt - strokeWidth;circleArea = new RectF(strokeWidth, strokeWidth, circleAreawidth, circleAreaHeight);}

Page 11: Canvas al ajillo

onDraw(Canvas canvas)

16ms (60 fps)

Evitar nuevas instancias

No usar invalidate()

Page 12: Canvas al ajillo

X

Y

● width / 2 , height / 2

● 0 , 0

Page 13: Canvas al ajillo

private float circleStartDegree = 0;private float circleEndDegree = 360;private float actualCircleEndDegree = circleEndDegree;

@Overrideprotected void onDraw(Canvas canvas) { drawCircle(canvas);}

private void drawCircle(Canvas canvas) {canvas.drawArc(circleArea, circleStartDegree, actualCircleEndDegree, false, circlePaint);}

Page 14: Canvas al ajillo

circlePaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, 0));

Page 15: Canvas al ajillo

Animación

Page 16: Canvas al ajillo

private void initializeAnimator() { valueAnimator = ValueAnimator.ofInt(circleStartDegree, circleEndDegree); valueAnimator.setDuration(1000); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { int degreeValue = (int) valueAnimator.getAnimatedValue(); actualCircleEndDegree = degreeValue; invalidate(); } });}

private void initialize() { initializePainter(); initializeAnimator();}

Page 17: Canvas al ajillo

public void start(){ valueAnimator.start(); } ValueAnimato

r

onUpdatedegree = value

invalidate

onDraw()

Page 18: Canvas al ajillo

Interpolators Acelerate

Acelerate Decelerate

BounceInterpolator

OvershootInterpolator

...

Page 19: Canvas al ajillo

valueAnimator.setInterpolator(new BounceInterpolator());

Page 20: Canvas al ajillo

valueAnimator.setInterpolator(new DecelateInterpolator());

Page 21: Canvas al ajillo

blurPainter = new Paint(circlePaint);blurPainter.setColor(Color.RED);blurPainter.setStrokeWidth(circleStroke * 1.20F);blurPainter.setMaskFilter(new BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL));

private void drawCircle(Canvas canvas) { canvas.drawArc(internalCircle, circleStartDegree, circleEndDegree, false, blurPainter); canvas.drawArc(internalCircle, circleStartDegree, circleEndDegree, false, circlePaint);}

Page 22: Canvas al ajillo
Page 23: Canvas al ajillo

setLayerType(LAYER_TYPE_SOFTWARE, null);

Page 24: Canvas al ajillo

Muerte a las vistas cuadradas

Page 25: Canvas al ajillo

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; createPath();}

private void createPath() { curvedPath = new Path(); curvedPath.moveTo(0, 0); curvedPath.lineTo(width, 0);}

@Overrideprotected void onDraw(Canvas canvas) { canvas.drawPath(curvedPath, pathPaint);}

Page 26: Canvas al ajillo

curvedPath.quadTo(x1, y1, x2, y2);

x1, y1

x2, y2

Page 27: Canvas al ajillo

private void createPath() { float pathCurvatureY = height / 2; float middleX = width / 2; curvedPath = new Path(); curvedPath.moveTo(0, 0); curvedPath.quadTo(middleX, pathCurvatureY, width, 0);

} 0,0

middleX, pathCurvatureY

width, 0

Page 28: Canvas al ajillo

private void createPath() { float pathCurvatureY = height / 2; float middleX = width / 2; curvedPath = new Path(); curvedPath.moveTo(0, 0); curvedPath.quadTo(middleX, pathCurvatureY, width, 0); curvedPath.lineTo(width, height);

}

width, height

Page 29: Canvas al ajillo

private void createPath() { float pathCurvatureY = height / 2; float middleX = width / 2; curvedPath = new Path(); curvedPath.moveTo(0, 0); curvedPath.quadTo(middleX, pathCurvatureY, width, 0); curvedPath.lineTo(width, height); curvedPath.lineTo(0, height); }

0, height

Page 30: Canvas al ajillo

private void createPath() { float pathCurvatureY = height / 2; float middleX = width / 2; curvedPath = new Path(); curvedPath.moveTo(0, 0); curvedPath.quadTo(middleX, pathCurvatureY, width, 0); curvedPath.lineTo(width, height); curvedPath.lineTo(0, height); curvedPath.close();}

Page 31: Canvas al ajillo

pathPaint.setStyle(Paint.Style.FILL);

Page 32: Canvas al ajillo
Page 33: Canvas al ajillo
Page 34: Canvas al ajillo

Interceptando touch events dentro de un área

Page 35: Canvas al ajillo

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; createPath(); createTouchRegion();}

private void createTouchRegion() { RectF pathBoundsRect = new RectF(); curvedPath.computeBounds(rectF, true); regionToCheck = new Region(pathBoundsRect.left, pathBoundsRect.top, pathBoundsRect.right,

pathBoundsRect.bottom); regionToCheck.setPath(curvedPath, regionToCheck);}

Page 36: Canvas al ajillo

@Overridepublic boolean onTouchEvent(MotionEvent event) { boolean result = false; int pointX = (int) event.getX(); int pointY = (int) event.getY(); if (isPointInsidePathArea(pointX, pointY)) { result = super.onTouchEvent(event); } return result;}

private boolean isPointInsidePathArea(int x, int y) { return regionToCheck.contains(x, y);}

Page 37: Canvas al ajillo
Page 38: Canvas al ajillo

Usando path para animar

Page 39: Canvas al ajillo

private float[] getPathCoordinates(Path path, float fraction) { float aCoordinates[] = { 0f, 0f }; PathMeasure pm = new PathMeasure(path, false); pm.getPosTan(pm.getLength() * fraction, aCoordinates, null); return aCoordinates;}

Page 40: Canvas al ajillo

@Overridepublic void onAnimationUpdate(ValueAnimator animation) { float value = animation.getAnimatedFraction(); float[] coordinates = getPathCoordinates(infinitePath, value); this.ballX = coordinates[0]; this.ballY = coordinates[1]; invalidate()}

Page 41: Canvas al ajillo
Page 42: Canvas al ajillo

Midiendo el rendimiento

Page 43: Canvas al ajillo
Page 44: Canvas al ajillo
Page 45: Canvas al ajillo
Page 46: Canvas al ajillo
Page 47: Canvas al ajillo

onDraw()

Recursos

OpenGL

Espera CPU

16 ms

Page 48: Canvas al ajillo

private void onDraw(Canvas canvas) { heavyWork(); canvas.drawArc(internalCircle, circleStartDegree, circleEndDegree, false, circlePaint);}

Page 49: Canvas al ajillo

Clean code también en vistas

Page 50: Canvas al ajillo

@Overrideprotected void onDraw(Canvas canvas) { if (mRunning) { if (mShowLeftEye) { canvas.drawCircle(mLeftEyePos[0], mLeftEyePos[1], mEyeCircleRadius,mCirclePaint); } if (mShowRightEye) { canvas.drawCircle(mRightEyePos[0], mRightEyePos[1], mEyeCircleRadius, mCirclePaint); } if (mFirstStep) { mArcPath.reset(); mArcPath.addArc(mRectF, mStartAngle, mSweepAngle); canvas.drawPath(mArcPath, mArcPaint); } else { mArcPath.reset(); mArcPath.addArc(mRectF, mStartAngle, mSweepAngle); canvas.drawPath(mArcPath, mArcPaint); }} else { canvas.drawCircle(mLeftEyePos[0], mLeftEyePos[1], mEyeCircleRadius, mCirclePaint); canvas.drawCircle(mRightEyePos[0], mRightEyePos[1], mEyeCircleRadius,mCirclePaint); canvas.drawPath(mArcPath, mArcPaint);}}

Page 51: Canvas al ajillo

@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); externalCirclePainter.draw(canvas); internalCirclePainter.draw(canvas); progressPainter.draw(canvas); iconPainter.draw(canvas);}

Page 52: Canvas al ajillo

¿Preguntas?