O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
Exploring Canvas
Exploring Canvas
Carregando em…3
×

Confira estes a seguir

1 de 52 Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si (20)

Anúncio

Semelhante a Canvas al ajillo (20)

Mais recentes (20)

Anúncio

Canvas al ajillo

  1. 1. @glomadrian Adrián García Lomas Canvas al ajillo
  2. 2. Lo que me gustaría que me hubieran contado sobre Canvas y Custom Views
  3. 3. Los detalles importan Adapta las vistas a las necesidades no las necesidades a las vistas Un mundo diferente y divertido
  4. 4. Ciclo de vida de una vista
  5. 5. Constructor onAttachedToWindow() onMeassure() onLayout()
  6. 6. dispatchDraw() draw() onDraw() invalidate()
  7. 7. Animación de carga
  8. 8. 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); }
  9. 9. ¿Qué pasa con el tamaño de la vista?
  10. 10. @Override protected 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); }
  11. 11. onDraw(Canvas canvas) 16ms (60 fps) Evitar nuevas instancias No usar invalidate()
  12. 12. X Y ● width / 2 , height / 2 ● 0 , 0
  13. 13. private float circleStartDegree = 0; private float circleEndDegree = 360; private float actualCircleEndDegree = circleEndDegree; @Override protected void onDraw(Canvas canvas) { drawCircle(canvas); } private void drawCircle(Canvas canvas) { canvas.drawArc(circleArea, circleStartDegree, actualCircleEndDegree, false, circlePaint); }
  14. 14. circlePaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, 0));
  15. 15. Animación
  16. 16. 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(); }
  17. 17. public void start(){ valueAnimator.start(); } ValueAnimator onUpdate degree = value invalidate onDraw()
  18. 18. Interpolators Acelerate Acelerate Decelerate BounceInterpolator OvershootInterpolator ...
  19. 19. valueAnimator.setInterpolator(new BounceInterpolator());
  20. 20. valueAnimator.setInterpolator(new DecelateInterpolator());
  21. 21. 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); }
  22. 22. setLayerType(LAYER_TYPE_SOFTWARE, null);
  23. 23. Muerte a las vistas cuadradas
  24. 24. @Override protected 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); } @Override protected void onDraw(Canvas canvas) { canvas.drawPath(curvedPath, pathPaint); }
  25. 25. curvedPath.quadTo(x1, y1, x2, y2); x1, y1 x2, y2
  26. 26. 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
  27. 27. 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
  28. 28. 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
  29. 29. 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(); }
  30. 30. pathPaint.setStyle(Paint.Style.FILL);
  31. 31. Interceptando touch events dentro de un área
  32. 32. @Override protected 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); }
  33. 33. @Override public 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); }
  34. 34. Usando path para animar
  35. 35. 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; }
  36. 36. @Override public void onAnimationUpdate(ValueAnimator animation) { float value = animation.getAnimatedFraction(); float[] coordinates = getPathCoordinates(infinitePath, value); this.ballX = coordinates[0]; this.ballY = coordinates[1]; invalidate() }
  37. 37. Midiendo el rendimiento
  38. 38. onDraw() Recursos OpenGL Espera CPU 16 ms
  39. 39. private void onDraw(Canvas canvas) { heavyWork(); canvas.drawArc(internalCircle, circleStartDegree, circleEndDegree, false, circlePaint); }
  40. 40. Clean code también en vistas
  41. 41. @Override protected 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); } }
  42. 42. @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); externalCirclePainter.draw(canvas); internalCirclePainter.draw(canvas); progressPainter.draw(canvas); iconPainter.draw(canvas); }
  43. 43. ¿Preguntas?

Notas do Editor

  • Motivacion de la charla, introdución a la api de canvas, path, algunos trucos un poco de perfonance para ellos explicare dos pequeños ejemplos un loading y una vista que usaremos de boton
  • Realmente no son dificiles de usar
    No ir siempre a buscar la solucion a GITHUB
    No necesitas todo lo que aporta la librearia
    Más control
    Adaptado totalmente a tus necesidades
    Es muy divertido programar vistas, es totalmente diferente a lo que hacemos dia a dia
  • Ciclo de vida de una vista, por que es importante conocer por que pasos toma la vista
  • Primero se ejecuta el contructor, que es donde crearemos los objetos necesarios que no dependan del tamaño de la vista
    Es llamado justo despues de que el padre hagaun addView()
    measure() && onMeassure() en este momento la vista aun no tiene tamaño y es aqui donde se puede definir en caso de que necesitemos modificarlo, por ejemlo aqui podemos saber si nuestra vista
    se encuentra dentro de un tamaño concreto, de un math_parent o de un wrap_content y actuar en consecuencia
    layout && onLayout() el onLayout se ejecuta por cada uno de las vistas hijas añadidas en la mayoria de los casos no es necesario

  • dispathDraw() && draw() y onDraw() es el metodo más importante y es donde vamos a realizar todas las tareas de pintado de nuestras vistas custom
    una vez realizado el onDraw() la vista es mostrada y no se volvera a pintar a no ser que se llame al método invalidate()
    este métoco hace volver a empezar el ciclo de pintado y entonces el método onDraw() vovlera a ser ejecutado
  • Para ilustrar mejor todo esto vamos hacer paso a paso una animación de carga parecida a esta
  • Hablar del paint,
    Controla el color, el estilo los tamaños y muchas cosas más
    Es un objeto que necesitaremos todo el tiempo que dure la vista por lo que conviene creerlo al principio
  • Por lo general el tamaño de una vista suele dar problemas sobretodo al principio.
    Por el proceso que pasa la vista el tamaño no se obtiene hasta cierto momento del ciclo de vida de la vista
  • El método onSizeChanged es muy importante siempre se llamará cuando el tamaño cambie.
    Eso quiere decir que se llamara despues del onLayout
    Este es un buen sitio para crear todos los componentes que necesiten de tamaño.
    Le resto el borde para evitar que el circulo se corte
    RectF define un rectangulo, donde se definen las 4 posiciones x1, y1, x2, y2
  • Método donde ocurre todo
    Tener en cuenta los 16MS es el tiempo que se tiene para pintar
    Por eso hay que evitar todos los proceso pesados en este método
    si se usa invalidate se entra en un bucle
    Canvas es el objeto donde se pinta todo, canvas provee una cantidad de metodos para el pintado
    entre ellos drawCircle drawPath etc
  • explicar método circle RectF
    Grados
    desde donde empieza
    false / true
    Mejorar circulo
  • Que es DashPathEffect pinta el stroke dash
    Hay más pathEffect
  • QUe es value animator y para que sirve
    Como lo vamos a usar
    Crear animación al crear la vista
    Tiene dos listener importantes
    Vamos a usar el update listener
    Este listener salta cada vez que un valor se actualiza
    El truco consiste en setear el valor del circulo al que nos devuelve el valueAnimator
    y forzar el pintado
    Varios tipos de animator float int color
  • Explicar lo que ha pasado y asi es como funcionan las animaciones en canvas
    Frame a frame
  • Explicar que el value animator los devuelve de manera lineal
    y que se le puede pasar un interpolator para definir cómo deben ser devueltos
    Explicar que son funciones matemáticas
    Hay muchos
  • Explicar que queremos mejorar el ciruclo amarillo poniendo por debajo una distorion
  • explicar que creamos otro painter con otras propiedades
    en este caso Rojo con un ancho 20% más
    y una mascara de blur
  • No obtenemos nada...
    Pregunta?
  • Solo en vistas estaticas
    vistas que no esten dentro de un adapter ni sean reutilizadas
    No solo pasa aqui, tambien en las mascaras en canvas para imagenes etc
  • Cambio de cuadradas - innovar no ir siempre a lo mismo
    Explicar lo que vamos hacer
  • Explicar path, que es y para qué sirve
    Cómo funciona
  • Explicar como funciona quadTo
  • Paso 1
  • Some magic
  • Resultado, explicar lo que se puede consguir con poco
  • Explicar el problema
    Pregunta como solucionar

×