English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In der Entwicklung des Android-Hochpräzisions-Schrittzählers-Dylan's Schrittzähler verwendet auf der Startseite einen benutzerdefinierten Kontroller, der der Oberfläche von QQ-Sport ähnelt, sowie Animationseffekte. Nachfolgend erkläre ich, wie dieser View gezeichnet wird.
1. Schauen wir uns zunächst das Bild an
2. Bildanalyse
Funktionsbeschreibung: Gelb stellt die vom Benutzer festgelegte Gesamtzahl der geplanten Übungsstufen dar, Rot stellt die aktuelle Anzahl der gelaufenen Schritte des Benutzers dar.
Erste Analyse: Das komplette Custom-View umfasst das Überschreiben der Methode onDraw(), um den Bogen zu zeichnen.
3. Notwendige Kenntnisse zum Zeichnen eines Bogens
Es gibt eine Methode zum Zeichnen eines Bogens im Canvas
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Zeichne den Kreiszylinder
Parameter eins: Das RectF-Objekt, ein Rechteckbereich, der die Grenzen eines Ellipsen um den Shape, die Größe und den Kreiszylinder definiert,
Parameter zwei: Der Startwinkel (in Grad) am Anfang des Kreiszylinders, der Startwinkel des Kreiszylinders, in Grad.
Parameter drei: Der Winkel, den der Kreiszylinder abdeckt, im Uhrzeigersinn, in Grad, beginnt von Null Grad am rechten Mittelpunkt.
Der vierte Parameter, wenn er true (wahr) ist, umfasst die Zeichnung des Kreises den Mittelpunkt, oft verwendet, um das Segment zu zeichnen; wenn es false (falsch) ist, ist es eine Kurve.
Parameter fünf ist das Paint-Objekt;
Für diese Methode können Sie meine Handzeichnung überprüfen, die nicht sehr gut ist, um die Bedeutung dieser Parameter und den Zeichnungsprozess zu erklären. Es tut mir leid, dass die Zeichnung schlecht ist.
4. Die Vorbereitung der Zeichnung
(1). Hole die Koordinaten des Mittelpunkts
/**X-Koordinate des Mittelpunkts*/ float centerX = (getWidth()) / 2;
(2). Erstelle einen Referenzrechteck um den Bogen
/**Bestimme das Umrissrechteck der Kurve*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth);
5. Die Hauptschritte der Zeichnung
(1).【第一步】绘制整体的黄色圆弧
/** * 1.Zeichne die gelbe Kurve der Gesamtschritte * * @param canvas Pinsel * @param rectF Referenzrechteck */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** Standardfarbe des Pinsels, gelb */ paint.setColor(getResources().getColor(R.color.yellow)); /** Der Übergang ist eine Kurve*/ paint.setStrokeJoin(Paint.Join.ROUND); /** Die Stile der Pinsel sind Paint.Cap.Round, Cap.SQUARE und andere, die sich in runde und quadratische Formen umwandeln*/ paint.setStrokeCap(Paint.Cap.ROUND); /** Setze den Füllungsstil des Stiftes Paint.Style.FILL : füllt das Innere aus; Paint.Style.FILL_AND_STROKE : füllt das Innere und den Umriss aus; Paint.Style.STROKE : zeichnet nur den Umriss*/ paint.setStyle(Paint.Style.STROKE); /**Rauschunterdrückungsfunktion*/ paint.setAntiAlias(true); /**Setze die Breite des Stiftes*/ paint.setStrokeWidth(borderWidth); /**Methode zum Zeichnen von Kreiszylinder * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Zeichne den Kreiszylinder Parameter eins: Das RectF-Objekt, ein Rechteckbereich, der die Grenzen eines Ellipsen um den Shape, die Größe und den Kreiszylinder definiert, Parameter zwei: Der Startwinkel (in Grad) am Anfang des Kreiszylinders, der Startwinkel des Kreiszylinders, in Grad. Parameter drei: Der Winkel, den der Kreiszylinder abdeckt, im Uhrzeigersinn, in Grad, beginnt von Null Grad am rechten Mittelpunkt. Parameter vier: Wenn dies true (wahr) ist, wird der Mittelpunkt bei der Zeichnung des Kreiszylinders mit einbezogen, was normalerweise zur Zeichnung von Sektor verwendet wird; Wenn es false (falsch) ist, handelt es sich um eine Kurve, Parameter fünf ist das Paint-Objekt; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); }
(2).【第二步】绘制当前进度的红色圆弧
/** * 2.Zeichne den roten Kreiszylinder des aktuellen Schrittes */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.ROUND); paintCurrent.setStrokeCap(Paint.Cap.ROUND);//Abgerundete Kantenkrümmung paintCurrent.setStyle(Paint.Style.STROKE);//Setze den Füllungsstil paintCurrent.setAntiAlias(true);//Rauschunterdrückungsfunktion paintCurrent.setStrokeWidth(borderWidth);//Setze die Breite des Stiftes paintCurrent.setColor(getResources().getColor(R.color.red));//Malerfarbe einstellen canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); }
(3).【第三步】绘制当前进度的红色数字
/** * 3.Schrittanzahl am Zentrum des Kreises */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//Rauschunterdrückungsfunktion vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//Schriftstil 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).【第四步】绘制”步数”的红色数字
/** * 4.Text am Zentrum des Kreises [Schrittanzahl] */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(16)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//Rauschunterdrückungsfunktion 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. Wie wird die Animation realisiert->ValueAnimator
ValueAnimator ist eine der zentralsten Klassen im gesamten Mechanismus der Attributanimation, und der Betrieb des Attributanimationssystems wird durch das ständige Verändern von Werten realisiert. Der Übergang der Animation zwischen dem Startwert und dem Endwert wird von der Klasse ValueAnimator verantwortet. Intern verwendet es ein Mechanismus der Zeitwiederholung, um den Übergang zwischen den Werten zu berechnen. Wir müssen nur den Startwert und den Endwert an ValueAnimator liefern und ihm mitteilen, wie lange die Animation laufen soll, dann wird ValueAnimator automatisch für uns den Übergang vom Startwert zum Endwert auf smooth Weise vervollständigen.
/*Animation für den Fortschritt einrichten * @param start Der Anfangswert * @param current Der Endwert * @param length Die Dauer der 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) { /**Ein glatter Übergangswert zwischen dem Anfangswert und dem Endwert, der regelmäßig den Fortschritt aktualisiert*/ currentAngleLength = (float) animation.getAnimatedValue(); invalidate(); } }); progressAnimator.start(); }
7.Der gesamte Quellcode der benutzerdefinierten 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; /** * Erstellt von DylanAndroid am 2016/5/26. * zeigt die Kurve der Schrittzahl an */ public class StepArcView extends View { /** * Die Breite der Kurve */ private float borderWidth = 38f; /** * Die Schriftgröße der Schrittzahl */ private float numberTextSize = 0; /** * Schrittzahl */ private String stepNumber = "0"; /** * der Winkel, um die Kurve zu beginnen */ private float startAngle = 135; /** * der Winkel zwischen dem Endwinkel und dem Startwinkel */ private float angleLength = 270; /** * Der Winkel zwischen dem Endpunkt der roten Kurve des aktuellen Schritts und dem Ausgangspunkt */ private float currentAngleLength = 0; /** * Animationsdauer */ 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); /**X-Koordinate des Mittelpunkts*/ float centerX = (getWidth()) / 2; /**Bestimme das Umrissrechteck der Kurve*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth); /**【第一步】Zeichne die gelbe Kurve des Ganzen*/ drawArcYellow(canvas, rectF); /**【第二步】Zeichne die rote Kurve des aktuellen Fortschritts*/ drawArcRed(canvas, rectF); /**【第三步】Zeichne die rote Ziffer des aktuellen Fortschritts*/ drawTextNumber(canvas, centerX); /**【第四步】Zeichne die rote Ziffer "Schritte"*/ drawTextStepString(canvas, centerX); } /** * 1.Zeichne die gelbe Kurve der Gesamtschritte * * @param canvas Pinsel * @param rectF Referenzrechteck */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** Standardfarbe des Pinsels, gelb */ paint.setColor(getResources().getColor(R.color.yellow)); /** Der Übergang ist eine Kurve*/ paint.setStrokeJoin(Paint.Join.ROUND); /** Die Stile der Pinsel sind Paint.Cap.Round, Cap.SQUARE und andere, die sich in runde und quadratische Formen umwandeln*/ paint.setStrokeCap(Paint.Cap.ROUND); /** Setze den Füllungsstil des Stiftes Paint.Style.FILL : füllt das Innere aus; Paint.Style.FILL_AND_STROKE : füllt das Innere und den Umriss aus; Paint.Style.STROKE : zeichnet nur den Umriss*/ paint.setStyle(Paint.Style.STROKE); /**Rauschunterdrückungsfunktion*/ paint.setAntiAlias(true); /**Setze die Breite des Stiftes*/ paint.setStrokeWidth(borderWidth); /**Methode zum Zeichnen von Kreiszylinder * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//Zeichne den Kreiszylinder Parameter eins: Das RectF-Objekt, ein Rechteckbereich, der die Grenzen eines Ellipsen um den Shape, die Größe und den Kreiszylinder definiert, Parameter zwei: Der Startwinkel (in Grad) am Anfang des Kreiszylinders, der Startwinkel des Kreiszylinders, in Grad. Parameter drei: Der Winkel, den der Kreiszylinder abdeckt, im Uhrzeigersinn, in Grad, beginnt von Null Grad am rechten Mittelpunkt. Parameter vier: Wenn dies true (wahr) ist, wird der Mittelpunkt bei der Zeichnung des Kreiszylinders mit einbezogen, was normalerweise zur Zeichnung von Sektor verwendet wird; Wenn es false (falsch) ist, handelt es sich um eine Kurve, Parameter fünf ist das Paint-Objekt; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); } /** * 2.Zeichne den roten Kreiszylinder des aktuellen Schrittes */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.ROUND); paintCurrent.setStrokeCap(Paint.Cap.ROUND);//Abgerundete Kantenkrümmung paintCurrent.setStyle(Paint.Style.STROKE);//Setze den Füllungsstil paintCurrent.setAntiAlias(true);//Rauschunterdrückungsfunktion paintCurrent.setStrokeWidth(borderWidth);//Setze die Breite des Stiftes paintCurrent.setColor(getResources().getColor(R.color.red));//Malerfarbe einstellen canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); } /** * 3.Schrittanzahl am Zentrum des Kreises */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//Rauschunterdrückungsfunktion vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//Schriftstil 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.Text am Zentrum des Kreises [Schrittanzahl] */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(16)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//Rauschunterdrückungsfunktion 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; /**in die Länge des Winkels umgerechnet, den das Ende erreichen soll,--> Kurvenlänge*/ float currentAngleLength = scale * angleLength; /**Animation starten*/ setAnimation(0, currentAngleLength, animationLength); } /** * Animation für den Fortschritt einrichten * ValueAnimator ist eine der zentralen Klassen im整个属性动画机制中,属性动画的运行机制是通过不断地对值进行操作来实现的, * und der Übergang zwischen dem Anfangswert und dem Endwert wird von der Klasse ValueAnimator berechnet. * und seine internen Mechanismen verwenden einen Zeitzyklus, um den Übergang zwischen Werten zu berechnen, * Wir müssen nur die Anfangswert und den Endwert an ValueAnimator liefern und ihm mitteilen, wie lange die Animation dauern soll, * Dann wird ValueAnimator automatisch für uns sicherstellen, dass eine glatte Übergangswirkung von der Anfangswert auf den Endwert erfolgt. * * @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(); } /** * Die Textgröße wird eingestellt, um sicherzustellen, dass die Schriftgröße dynamisch angepasst wird, falls die Anzahl der Schritte besonders groß ist und nicht untergebracht werden kann. * * @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.Verwendungshinweise
in 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" />
Im Activity
StepArcView sv = (StepArcView) findViewById(R.id.sv); sv.setCurrentCount(7000, 1000);
Die oben genannten Android-ähnlichen QQ-Schrittumfangs- und Animationseffekte, die von mir vorgestellt werden, sollten Ihnen helfen. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht, ich werde Ihnen umgehend antworten. Ich danke auch sehr für die Unterstützung der Website "Ruf nach der Anleitung"!
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheber. Der Inhalt wurde von Internetnutzern freiwillig und selbstständig hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie urheberrechtlich geschützte Inhalte entdecken, sind Sie herzlich eingeladen, eine E-Mail an notice#w zu senden.3codebox.com (Bitte ersetzen Sie # durch @, wenn Sie eine E-Mail senden, und geben Sie relevante Beweise an. Sobald nachgewiesen wird, dass der Inhalt urheberrechtlich geschützt ist, wird diese Website den fraglichen Inhalt sofort löschen.)