English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Dans le développement précédent de l'application de pedometer ultra-précis pour Android-L'accueil de Dylan Pedometer utilise un contrôle personnalisé, similaire à l'interface de QQ Movement, avec des effets d'animation, nous allons parler de la manière dont ce View est dessiné.
1.Regardons d'abord l'effet visuel
2.Analyse de l'effet visuel
Description de la fonction : jaune représente le nombre total de pas prévu par l'utilisateur, rouge représente le nombre de pas actuels de l'utilisateur.
Analyse initiale : redéfinir le méthode onDraw() de View personnalisée pour dessiner un arc.
3.Connaissances nécessaires pour dessiner un arc
Il y a une méthode pour dessiner un arc dans Canvas
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Dessiner un arc
Le premier paramètre est l'objet RectF, une région rectangulaire elliptique définissant les limites de la forme, de la taille et de l'arc,
Le deuxième paramètre est l'angle de départ (degré) à l'origine de l'arc, l'angle de départ de l'arc, en degrés.
Le troisième paramètre est l'angle couvert par l'arc, dans le sens des aiguilles d'une montre, en degrés, avec zéro degré à partir du centre droit.
Le quatrième paramètre est vrai si, lors du dessin de l'arc, le centre est inclus, généralement utilisé pour dessiner des secteurs; s'il est faux, il s'agit d'une courbe en arc.
Le cinquième paramètre est l'objet Paint;
Pour cette méthode, vous pouvez consulter le schéma que j'ai dessiné à la main, il est pas très bon, pour expliquer le sens de ces paramètres et le processus de dessin, le dessin n'est pas très bon, j'espère que vous comprendrez!
4.Préparation du dessin
(1).Obtenir les coordonnées du point central
/**Coordonnée x du point central*/ float centerX = (getWidth()) / 2;
(2).Créer un rectangle de référence à l'extérieur de l'arc
/**Spécifier la zone de contour de l'arc en forme de cercle*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth);
5.Les principales étapes du dessin
(1).【第一步】绘制整体的黄色圆弧
/** * 1.tracer un arc jaune représentant le nombre total d'étapes * * @param canvas Pinceau * @param rectF Rectangle de référence */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** Couleur par défaut du pinceau, jaune */ paint.setColor(getResources().getColor(R.color.yellow)); /** Les jonctions sont des arcs de cercle*/ paint.setStrokeJoin(Paint.Join.ROUND); /** Définir le style du pinceau Paint.Cap.Round, Cap.SQUARE pour les formes circulaire et carrée*/ paint.setStrokeCap(Paint.Cap.ROUND); /** Définir le style de remplissage du pinceau Paint.Style.FILL : remplissage interne;Paint.Style.FILL_AND_STROKE : remplissage interne et contour; Paint.Style.STROKE : contour uniquement*/ paint.setStyle(Paint.Style.STROKE); /**La fonction anti-aliasing*/ paint.setAntiAlias(true); /**Définir la largeur du pinceau*/ paint.setStrokeWidth(borderWidth); /**Méthode de dessin d'arc * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Dessiner un arc Le premier paramètre est l'objet RectF, une région rectangulaire elliptique définissant les limites de la forme, de la taille et de l'arc, Le deuxième paramètre est l'angle de départ (degré) à l'origine de l'arc, l'angle de départ de l'arc, en degrés. Le troisième paramètre est l'angle couvert par l'arc, dans le sens des aiguilles d'une montre, en degrés, avec zéro degré à partir du centre droit. Le quatrième paramètre est si c'est true (vrai), il inclut le centre du cercle lors du dessin de l'arc, généralement utilisé pour dessiner des secteurs; si c'est false (faux), c'est une courbe d'arc; Le cinquième paramètre est l'objet Paint; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); }
(2).【第二步】绘制当前进度的红色圆弧
/** * 2.Dessiner l'arc rouge actuel */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.ROUND); paintCurrent.setStrokeCap(Paint.Cap.ROUND);//Rayon arrondi des coins paintCurrent.setStyle(Paint.Style.STROKE);//Définir le style de remplissage paintCurrent.setAntiAlias(true);//La fonction anti-aliasing paintCurrent.setStrokeWidth(borderWidth);//Définir la largeur du pinceau paintCurrent.setColor(getResources().getColor(R.color.red));//Définir la couleur du pinceau canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); }
(3).【第三步】绘制当前进度的红色数字
/** * 3Le nombre au centre du cercle */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//La fonction anti-aliasing vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//Style de police vTextPaint.setColor(getResources().getColor(R.color.red)); Rect bounds_Number = new Rect(); vTextPaint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); canvas.drawText(stepNumber, centerX, getHeight() / 2 + bounds_Number.height() / 2, vTextPaint); }
(4).【第四步】绘制”步数”的红色数字
/** * 4Le texte [步数] au centre du cercle */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(16)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//La fonction anti-aliasing vTextPaint.setColor(getResources().getColor(R.color.grey)); String stepString = "步数"; Rect bounds = new Rect(); vTextPaint.getTextBounds(stepString, 0, stepString.length(), bounds); canvas.drawText(stepString, centerX, getHeight()) / 2 + bounds.height() + getFontHeight(numberTextSize), vTextPaint); }
6.Comment l'animation est-elle réalisée->ValueAnimator
ValueAnimator est la classe la plus essentielle du mécanisme d'animation des propriétés, le mécanisme de fonctionnement de l'animation des propriétés est réalisé par le biais de l'opération constante des valeurs, et la transition d'animation entre la valeur initiale et la valeur finale est calculée par la classe ValueAnimator. Son mécanisme interne utilise un mécanisme de boucle temporelle pour calculer la transition entre les valeurs, nous n'avons qu'à fournir la valeur initiale et la valeur finale à ValueAnimator, et lui dire la durée de l'animation nécessaire, alors ValueAnimator nous aidera automatiquement à réaliser une transition lisse de la valeur initiale à la valeur finale.
/*Définir l'animation de progression * @param start la valeur initiale * @param current la valeur finale * @param length la durée de l'animation */ private void setAnimation(float start, float current, int length) { ValueAnimator progressAnimator = ValueAnimator.ofFloat(start, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngleLength); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /**une valeur de transition lisse générée entre la valeur initiale et la valeur finale à chaque fois, mettant à jour progressivement le progrès*/ currentAngleLength = (float) animation.getAnimatedValue(); invalidate(); } }); progressAnimator.start(); }
7.le code source complet personnalisé de StepArcView
import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; import android.view.View; import cn.bluemobi.dylan.step.R; /** * Créé par DylanAndroid le 2016/5/26. * l'arc d'affichage du nombre de pas */ public class StepArcView extends View { /** * la largeur de l'arc */ private float borderWidth = 38f; /** * la taille de la police pour dessiner le nombre de pas */ private float numberTextSize = 0; /** * le nombre de pas */ private String stepNumber = "0"; /** * l'angle de départ pour dessiner l'arc */ private float startAngle = 135; /** * l'angle entre l'angle correspondant au point final et l'angle correspondant au point de départ */ private float angleLength = 270; /** * l'angle compris entre le point final de l'arc rouge à dessiner actuel et le point de départ */ private float currentAngleLength = 0; /** * durée de l'animation */ private int animationLength = 3000; public StepArcView(Context context) { super(context); } public StepArcView(Context context, AttributeSet attrs) { super(context, attrs); } public StepArcView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /**Coordonnée x du point central*/ float centerX = (getWidth()) / 2; /**Spécifier la zone de contour de l'arc en forme de cercle*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth); /**【Étape 1】tracer un arc jaune représentant l'ensemble*/ drawArcYellow(canvas, rectF); /**【Étape 2】tracer un arc rouge représentant la progression actuelle*/ drawArcRed(canvas, rectF); /**【Étape 3】tracer le chiffre rouge représentant la progression actuelle*/ drawTextNumber(canvas, centerX); /**【Étape 4】tracer le chiffre rouge "étape"*/ drawTextStepString(canvas, centerX); } /** * 1.tracer un arc jaune représentant le nombre total d'étapes * * @param canvas Pinceau * @param rectF Rectangle de référence */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** Couleur par défaut du pinceau, jaune */ paint.setColor(getResources().getColor(R.color.yellow)); /** Les jonctions sont des arcs de cercle*/ paint.setStrokeJoin(Paint.Join.ROUND); /** Définir le style du pinceau Paint.Cap.Round, Cap.SQUARE pour les formes circulaire et carrée*/ paint.setStrokeCap(Paint.Cap.ROUND); /** Définir le style de remplissage du pinceau Paint.Style.FILL : remplissage interne;Paint.Style.FILL_AND_STROKE : remplissage interne et contour; Paint.Style.STROKE : contour uniquement*/ paint.setStyle(Paint.Style.STROKE); /**La fonction anti-aliasing*/ paint.setAntiAlias(true); /**Définir la largeur du pinceau*/ paint.setStrokeWidth(borderWidth); /**Méthode de dessin d'arc * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Dessiner un arc Le premier paramètre est l'objet RectF, une région rectangulaire elliptique définissant les limites de la forme, de la taille et de l'arc, Le deuxième paramètre est l'angle de départ (degré) à l'origine de l'arc, l'angle de départ de l'arc, en degrés. Le troisième paramètre est l'angle couvert par l'arc, dans le sens des aiguilles d'une montre, en degrés, avec zéro degré à partir du centre droit. Le quatrième paramètre est si c'est true (vrai), il inclut le centre du cercle lors du dessin de l'arc, généralement utilisé pour dessiner des secteurs; si c'est false (faux), c'est une courbe d'arc; Le cinquième paramètre est l'objet Paint; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); } /** * 2.Dessiner l'arc rouge actuel */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.ROUND); paintCurrent.setStrokeCap(Paint.Cap.ROUND);//Rayon arrondi des coins paintCurrent.setStyle(Paint.Style.STROKE);//Définir le style de remplissage paintCurrent.setAntiAlias(true);//La fonction anti-aliasing paintCurrent.setStrokeWidth(borderWidth);//Définir la largeur du pinceau paintCurrent.setColor(getResources().getColor(R.color.red));//Définir la couleur du pinceau canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); } /** * 3Le nombre au centre du cercle */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//La fonction anti-aliasing vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//Style de police vTextPaint.setColor(getResources().getColor(R.color.red)); Rect bounds_Number = new Rect(); vTextPaint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); canvas.drawText(stepNumber, centerX, getHeight() / 2 + bounds_Number.height() / 2, vTextPaint); } /** * 4Le texte [步数] au centre du cercle */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(16)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//La fonction anti-aliasing vTextPaint.setColor(getResources().getColor(R.color.grey)); String stepString = "步数"; Rect bounds = new Rect(); vTextPaint.getTextBounds(stepString, 0, stepString.length(), bounds); canvas.drawText(stepString, centerX, getHeight()) / 2 + bounds.height() + getFontHeight(numberTextSize), vTextPaint); } /** * 获取当前步数的数字的高度 * * @param fontSize 字体大小 * @return 字体高度 */ public int getFontHeight(float fontSize) { Paint paint = new Paint(); paint.setTextSize(fontSize); Rect bounds_Number = new Rect(); paint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); return bounds_Number.height(); } /** * dip 转换成px * * @param dip * @return */ private int dipToPx(float dip) { float density = getContext().getResources().getDisplayMetrics().density; return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1)); } /** * 所走的步数进度 * * @param totalStepNum 设置的步数 * @param currentCounts 所走步数 */ public void setCurrentCount(int totalStepNum, int currentCounts) { stepNumber = currentCounts + ""; setTextSize(currentCounts); /**如果当前走的步数超过总步数则圆弧还是270度,不能成为园*/ if (currentCounts > totalStepNum) { currentCounts = totalStepNum; } /**所走步数占用总共步数的百分比*/ float scale = (float) currentCounts / totalStepNum; /**Convertir en longueur de l'angle final à atteindre--> longueur de l'arc*/ float currentAngleLength = scale * angleLength; /**Commencer l'exécution de l'animation*/ setAnimation(0, currentAngleLength, animationLength); } /** * Définir l'animation de progression * ValueAnimator est la classe la plus essentielle du mécanisme d'animation des propriétés, le mécanisme de fonctionnement de l'animation des propriétés est réalisé par l'opération continue des valeurs. * La transition entre la valeur initiale et la valeur de fin est calculée par la classe ValueAnimator. * Il utilise un mécanisme de boucle temporelle interne pour calculer la transition entre les valeurs. * Nous devons fournir à ValueAnimator la valeur initiale et la valeur de fin, et lui dire la durée de l'animation nécessaire * Alors ValueAnimator complètera automatiquement le passage en douceur de la valeur initiale à la valeur de fin. * * @param last * @param current */ private void setAnimation(float last, float current, int length) { ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngleLength); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentAngleLength = (float) animation.getAnimatedValue(); invalidate(); } }); progressAnimator.start(); } /** * Définir la taille du texte pour éviter que le texte ne puisse pas être placé après une longueur de pas exceptionnelle, et régler la taille de la police dynamiquement * * @param num */ public void setTextSize(int num) { String s = String.valueOf(num); int length = s.length(); if (length <= 4) { numberTextSize = dipToPx(50); } else if (length > 4 && length <= 6) { numberTextSize = dipToPx(40); } else if (length > 6 && length <= 8) { numberTextSize = dipToPx(30); } else if (length > 8) { numberTextSize = dipToPx(25); } } }
8.Explication d'utilisation
dans xml
<cn.bluemobi.dylan.step.view.StepArcView android:id="@"+id/sv " android:layout_width="200dp" android:layout_height="200dp" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" />
Dans l'Activity
StepArcView sv = (StepArcView) findViewById(R.id.sv); sv.setCurrentCount(7000, 1000);
Ce que j'ai présenté à l'éditeur aujourd'hui est le tutoriel Android de l'effet circulaire et animé de la marche QQ, j'espère que cela vous sera utile. Si vous avez des questions, laissez-moi un message, l'éditeur répondra à temps. Merci également de votre soutien au site Web de l'enseignement des cris !
Déclaration : Le contenu de cet article est extrait du réseau, propriété de l'auteur original, contribué et téléversé par les utilisateurs d'Internet. Le site web ne détient pas de droits de propriété, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, le site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)