programacion - evento touch android studio
Cómo dibujar un círculo con animación en Android con un tamaño de círculo basado en un valor (3)
Código agregado para calcular medidas de círculo correctas
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
class Circle(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint: Paint
private val rect: RectF
var angle = 0f
companion object {
private val START_ANGLE_POINT = 270f
}
init {
val strokeWidth = resources.getDimension(R.dimen.toast_circle_stroke_width)
paint = Paint().apply {
setAntiAlias(true)
setStyle(Paint.Style.STROKE)
setStrokeWidth(strokeWidth)
setColor(Color.RED)
}
val circleSize = resources.getDimension(R.dimen.toast_circle_size)
rect = RectF(
strokeWidth,
strokeWidth,
circleSize + strokeWidth,
circleSize + strokeWidth
)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val circleSize = resources.getDimension(R.dimen.toast_circle_size).toInt()
val strokeWidth = resources.getDimension(R.dimen.toast_circle_stroke_width).toInt()
super.onMeasure(
MeasureSpec.makeMeasureSpec(circleSize + 2 * strokeWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(circleSize + 2 * strokeWidth, MeasureSpec.EXACTLY));
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint)
}
}
Quiero desarrollar un componente personalizado que dibuje parte del círculo en función de diferentes valores. por ejemplo, dibujar 1/4 de círculo, 1/2 círculo, etc. El componente debe ser animado para mostrar el proceso de dibujo. El círculo parcial se dibuja en la parte superior de una vista de imagen estática, y planeo usar dos vistas, animadas, una encima de la vista estática. ¿Alguna sugerencia de cómo desarrollar esto?
Puse la captura de pantalla como referencia.
Consulte la imagen y tenga una idea de cómo se ve. ¡Gracias!
Gracias por adelantado.
Como extra de la respuesta de @JohnCordeiro. He agregado parámetros de xml para reutilizar el círculo y llenar el círculo si es necesario.
class RecordingCircle(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint: Paint
private val rect: RectF
private val fillPaint: Paint
private val fillRect: RectF
var angle: Float
var startAngle: Float
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordingCircle)
startAngle = typedArray.getFloat(R.styleable.RecordingCircle_startAngle, 0f)
val offsetAngle = typedArray.getFloat(R.styleable.RecordingCircle_offsetAngle, 0f)
val color = typedArray.getColor(R.styleable.RecordingCircle_color, ResourcesCompat.getColor(resources, R.color.recording, null))
val strokeWidth = typedArray.getFloat(R.styleable.RecordingCircle_strokeWidth, 20f)
val circleSize = typedArray.getDimension(R.styleable.RecordingCircle_cicleSize, 100f)
val fillColor = typedArray.getColor(R.styleable.RecordingCircle_fillColor, 0)
typedArray.recycle()
paint = Paint().apply {
setAntiAlias(true)
setStyle(Paint.Style.STROKE)
setStrokeWidth(strokeWidth)
setColor(color)
}
rect = RectF(
strokeWidth,
strokeWidth,
(circleSize - strokeWidth),
(circleSize - strokeWidth)
)
fillPaint = Paint().apply {
setAntiAlias(true)
setStyle(Paint.Style.FILL)
setColor(fillColor)
}
val offsetFill = strokeWidth
fillRect = RectF(
offsetFill,
offsetFill,
(circleSize - offsetFill),
(circleSize - offsetFill)
)
//Initial Angle (optional, it can be zero)
angle = offsetAngle
}
override protected fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (fillColor > 0) {
canvas.drawArc(rect, 0f, 360f, false, fillPaint)
}
canvas.drawArc(rect, startAngle, angle, false, paint)
}
}
Y en el xml:
<com.myapp.RecordingCircle android:id="@+id/cameraRecordButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:offsetAngle="360"
app:color="@color/light_grey"
app:strokeWidth="10"
app:cicleSize="@dimen/camera_record_button"
app:fillColor="@color/recording_bg" />
<com.myapp.RecordingCircle android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:startAngle="270"
app:color="@color/recording"
app:strokeWidth="10"
app:cicleSize="@dimen/camera_record_button" />
Aquí el resultado: observe el relleno semitransparente del botón
Tienes que dibujar la vista circular, y luego debes crearle una animación.
Crear la vista circular:
public class Circle extends View {
private static final int START_ANGLE_POINT = 90;
private final Paint paint;
private final RectF rect;
private float angle;
public Circle(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 40;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);
//size 200x200 example
rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth);
//Initial Angle (optional, it can be zero)
angle = 120;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
}
}
Crear la clase de animación para establecer el nuevo ángulo:
public class CircleAngleAnimation extends Animation {
private Circle circle;
private float oldAngle;
private float newAngle;
public CircleAngleAnimation(Circle circle, int newAngle) {
this.oldAngle = circle.getAngle();
this.newAngle = newAngle;
this.circle = circle;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime);
circle.setAngle(angle);
circle.requestLayout();
}
}
Poner círculo en su diseño:
<com.package.Circle
android:id="@+id/circle"
android:layout_width="300dp"
android:layout_height="300dp" />
Y finalmente comenzando la animación:
Circle circle = (Circle) findViewById(R.id.circle);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);
El resultado es: