Je souhaite développer un composant personnalisé qui dessine une partie du cercle en fonction de différentes valeurs. dessinez par exemple 1/4 de cercle, 1/2 cercle, etc. Le composant doit être animé pour afficher le processus de dessin. Le cercle partiel est dessiné au-dessus d'une vue d'image statique et je prévois d'utiliser deux vues, l'une animée au-dessus de la vue statique. Toute suggestion comment développer cela?
Je mets la capture d'écran pour référence.
S'il vous plaît se référer à l'image, et avoir une idée de comment ça ressemble. Merci!
Merci d'avance.
Vous devez dessiner la vue circulaire, puis créer une animation.
Création de la vue circulaire:
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;
}
}
Création de la classe d'animation pour définir le nouvel angle:
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();
}
}
Mettez un cercle dans votre mise en page:
<com.package.Circle
Android:id="@+id/circle"
Android:layout_width="300dp"
Android:layout_height="300dp" />
Et enfin pour commencer l'animation:
Circle circle = (Circle) findViewById(R.id.circle);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240);
animation.setDuration(1000);
circle.startAnimation(animation);
Le résultat est:
En plus de @JohnCordeiro, répondez. J'ai ajouté des paramètres de xml pour réutiliser le cercle et pour remplir le cercle si nécessaire.
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)
}
}
Et sur le 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" />
Voici le résultat: Notez le remplissage semi-transparent du bouton
Code ajouté pour le calcul des mesures de cercle correctes
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)
}
}