English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Android 자체 View로 QQ 운동 걸음수 원형 및 애니메이션 효과 구현

이전 Android 초정밀 걸음 세기 개발-Dylan 걸음 세기의 첫 페이지는 사용자 정의 컨트롤을 사용하며, QQ 운동의 인터페이스와 비슷하며, 애니메이션 효과도 있습니다. 아래에서 이 View가 어떻게 그려지는지 설명하겠습니다.

1. 효과 그림을 먼저 보겠습니다

2. 효과 그림 분석

기능 설명: 노란색은 사용자가 설정한 총 운동 스텝 수를, 빨간색은 사용자가 현재 걸은 스텝 수를 나타냅니다.

초기 분석: 완전히 custom View를 재정의하여 onDraw() 메서드를 그리기.

3. 원형을 그리는 필수 지식

Canvas에는 원형을 그리는 메서드가 있습니다

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//원형 도널 그리기

파라미터 일은 RectF 객체입니다. 원형 도널의 형태, 크기, 도널을 정의하는矩형 영역의 경계입니다.

파라미터 두는 원형 도널 시작에서의 시작 각도(도)입니다. 원형 도널의 시작 각도입니다. 단위는 도입니다.

파라미터 세는 원형 도널을 지나는 각도입니다. 시계 방향, 단위는 도이며, 오른쪽 중앙에서 0도로 시작합니다.

매개변수 네는 true(참)이면, 원형을 그리는 때 원심점을 포함시키며, 일반적으로 반월을 그리기 위해 사용됩니다. false(거짓)이면 이는 곡선이 됩니다.

파라미터 다섯은 Paint 객체입니다;

이 메서드에 대해, 저의 손으로 그린 도면을 보세요. 그림이 나쁘지만, 이러한 매개변수의 의미와 그리기 과정을 설명하려고 합니다. 그림이 나쁘다면 용서해 주세요!

4. 그리기의 준비 작업

(1). 중심점 좌표를 가져오기

/**중심점의 x 좌표*/
float centerX = (getWidth()) / 2;

(2). 원형 외의 참조 직사각형을 만들기

/**원형의 외곽 외곽矩를 지정합니다.*/
RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth);

5. 그리기의 주요 단계

(1).【第一步】전체의 노란 원형을 그리기

/**
* 1.총 단계 수의 노란색 원형을 그립니다.
*
* @param canvas 펜
* @param rectF 참조矩
*/
private void drawArcYellow(Canvas canvas, RectF rectF) {
Paint paint = new Paint();
/** 기본 펜 색상, 노란색입니다. */
paint.setColor(getResources().getColor(R.color.yellow));
/** 결합 부분이 원형으로 이루어져 있습니다.*/
paint.setStrokeJoin(Paint.Join.ROUND);
/** 화면 펜 스타일 Paint.Cap.Round, Cap.SQUARE 등이 원형, 정方形입니다.*/
paint.setStrokeCap(Paint.Cap.ROUND);
/** 화면 펜의 채우기 스타일 설정 Paint.Style.FILL : 내부 채우기; Paint.Style.FILL_AND_STROKE : 내부와 테두리 채우기; Paint.Style.STROKE : 단지 테두리 그리기*/
paint.setStyle(Paint.Style.STROKE);
/**지그재그 효과*/
paint.setAntiAlias(true);
/**화면 펜 너비 설정*/
paint.setStrokeWidth(borderWidth);
/**원형 도널 그리기 메서드
* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//원형 도널 그리기
파라미터 일은 RectF 객체입니다. 원형 도널의 형태, 크기, 도널을 정의하는矩형 영역의 경계입니다.
파라미터 두는 원형 도널 시작에서의 시작 각도(도)입니다. 원형 도널의 시작 각도입니다. 단위는 도입니다.
파라미터 세는 원형 도널을 지나는 각도입니다. 시계 방향, 단위는 도이며, 오른쪽 중앙에서 0도로 시작합니다.
파라미터 네는 이 것이 true(진정)이면, 원형 도널을 그리기 위해 원심점을 포함하여 그림을 그릴 것입니다; 그렇지 않으면(false) 이것은 기본적으로 곡선입니다:
파라미터 다섯은 Paint 객체입니다;
*/
canvas.drawArc(rectF, startAngle, angleLength, false, paint);
}

(2).【第二步】현재 진도의 빨간 원형을 그리기

/**
* 2.현재 단계의 빨간 원형 도널 그리기
*/
private void drawArcRed(Canvas canvas, RectF rectF) {
Paint paintCurrent = new Paint();
paintCurrent.setStrokeJoin(Paint.Join.ROUND);
paintCurrent.setStrokeCap(Paint.Cap.ROUND);//둥근 꼭지점 구도
paintCurrent.setStyle(Paint.Style.STROKE);//填充 스타일 설정
paintCurrent.setAntiAlias(true);//지그재그 효과
paintCurrent.setStrokeWidth(borderWidth);//화면 펜 너비 설정
paintCurrent.setColor(getResources().getColor(R.color.red));//펜 색상 설정
canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent);
}

(3).【第三步】현재 진도의 빨간 숫자를 그리기

/**
* 3環형 중심의 스탭 숫자
*/
private void drawTextNumber(Canvas canvas, float centerX) {
Paint vTextPaint = new Paint();
vTextPaint.setTextAlign(Paint.Align.CENTER);
vTextPaint.setAntiAlias(true);//지그재그 효과
vTextPaint.setTextSize(numberTextSize);
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
vTextPaint.setTypeface(font);//글꼴 스타일
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環형 중심[步数]의 텍스트
*/
private void drawTextStepString(Canvas canvas, float centerX) {
Paint vTextPaint = new Paint();
vTextPaint.setTextSize(dipToPx(16));
vTextPaint.setTextAlign(Paint.Align.CENTER);
vTextPaint.setAntiAlias(true);//지그재그 효과
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. 애니메이션은 어떻게 구현되는지->ValueAnimator

ValueAnimator는 전체 속성 애니메이션 메커니즘에서 가장 핵심적인 클래스로, 속성 애니메이션의 실행 메커니즘은 지속적으로 값을 조작하여 이루어집니다. 초기 값과 종료 값 사이의 애니메이션 전환은 ValueAnimator 클래스가 책임집니다. 그것의 내부는 시간 루프 메커니즘을 사용하여 값을 간격으로 계산하며, 우리는 초기 값과 종료 값을 제공하고, 애니메이션을 실행해야 할 시간을 알려주면 ValueAnimator는 자동으로 초기 값에서 부드럽게 종료 값으로 이동하는 효과를 완료합니다.

/*진도에 애니메이션 설정
* @param start 초기 값
* @param current 종료 값
* @param length 애니메이션 시간
*/
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) {
/**시작값과 종료값 사이에서 생성되는 매우 부드러운 전환 값, 진행 상황을 계속 업데이트*/
currentAngleLength = (float) animation.getAnimatedValue();
invalidate();
}
});
progressAnimator.start();
}

7. 전체自定义 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;
/**
* DylanAndroid에 의해 생성된 2016/5/26.
* 단계수를 표시하는 원호
*/
public class StepArcView extends View {
/**
* 원호의 너비
*/
private float borderWidth = 38f;
/**
* 단계수를 그리는 문자의字体 크기
*/
private float numberTextSize = 0;
/**
* 단계수
*/
private String stepNumber = "0";
/**
* 원호를 시작하는 각도
*/
private float startAngle = 135;
/**
* 종점에 해당하는 각도와 시작점에 해당하는 각도의 각도
*/
private float angleLength = 270;
/**
* 현재 그려진 단계의 적색 반경 끝에서 출발点到의 각도
*/
private float currentAngleLength = 0;
/**
* 애니메이션 시간
*/
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 좌표*/
float centerX = (getWidth()) / 2;
/**원형의 외곽 외곽矩를 지정합니다.*/
RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth);
/**【제1단계】전체의 노란 원형을 그립니다.*/
drawArcYellow(canvas, rectF);
/**【제2단계】현재 진도의 빨간 원형을 그립니다.*/
drawArcRed(canvas, rectF);
/**【제3단계】현재 진도의 빨간 숫자를 그립니다.*/
drawTextNumber(canvas, centerX);
/**【제4단계】"단계수"의 빨간 숫자를 그립니다.*/
drawTextStepString(canvas, centerX);
}
/**
* 1.총 단계 수의 노란색 원형을 그립니다.
*
* @param canvas 펜
* @param rectF 참조矩
*/
private void drawArcYellow(Canvas canvas, RectF rectF) {
Paint paint = new Paint();
/** 기본 펜 색상, 노란색입니다. */
paint.setColor(getResources().getColor(R.color.yellow));
/** 결합 부분이 원형으로 이루어져 있습니다.*/
paint.setStrokeJoin(Paint.Join.ROUND);
/** 화면 펜 스타일 Paint.Cap.Round, Cap.SQUARE 등이 원형, 정方形입니다.*/
paint.setStrokeCap(Paint.Cap.ROUND);
/** 화면 펜의 채우기 스타일 설정 Paint.Style.FILL : 내부 채우기; Paint.Style.FILL_AND_STROKE : 내부와 테두리 채우기; Paint.Style.STROKE : 단지 테두리 그리기*/
paint.setStyle(Paint.Style.STROKE);
/**지그재그 효과*/
paint.setAntiAlias(true);
/**화면 펜 너비 설정*/
paint.setStrokeWidth(borderWidth);
/**원형 도널 그리기 메서드
* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//원형 도널 그리기
파라미터 일은 RectF 객체입니다. 원형 도널의 형태, 크기, 도널을 정의하는矩형 영역의 경계입니다.
파라미터 두는 원형 도널 시작에서의 시작 각도(도)입니다. 원형 도널의 시작 각도입니다. 단위는 도입니다.
파라미터 세는 원형 도널을 지나는 각도입니다. 시계 방향, 단위는 도이며, 오른쪽 중앙에서 0도로 시작합니다.
파라미터 네는 이 것이 true(진정)이면, 원형 도널을 그리기 위해 원심점을 포함하여 그림을 그릴 것입니다; 그렇지 않으면(false) 이것은 기본적으로 곡선입니다:
파라미터 다섯은 Paint 객체입니다;
*/
canvas.drawArc(rectF, startAngle, angleLength, false, paint);
}
/**
* 2.현재 단계의 빨간 원형 도널 그리기
*/
private void drawArcRed(Canvas canvas, RectF rectF) {
Paint paintCurrent = new Paint();
paintCurrent.setStrokeJoin(Paint.Join.ROUND);
paintCurrent.setStrokeCap(Paint.Cap.ROUND);//둥근 꼭지점 구도
paintCurrent.setStyle(Paint.Style.STROKE);//填充 스타일 설정
paintCurrent.setAntiAlias(true);//지그재그 효과
paintCurrent.setStrokeWidth(borderWidth);//화면 펜 너비 설정
paintCurrent.setColor(getResources().getColor(R.color.red));//펜 색상 설정
canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent);
}
/**
* 3環형 중심의 스탭 숫자
*/
private void drawTextNumber(Canvas canvas, float centerX) {
Paint vTextPaint = new Paint();
vTextPaint.setTextAlign(Paint.Align.CENTER);
vTextPaint.setAntiAlias(true);//지그재그 효과
vTextPaint.setTextSize(numberTextSize);
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
vTextPaint.setTypeface(font);//글꼴 스타일
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環형 중심[步数]의 텍스트
*/
private void drawTextStepString(Canvas canvas, float centerX) {
Paint vTextPaint = new Paint();
vTextPaint.setTextSize(dipToPx(16));
vTextPaint.setTextAlign(Paint.Align.CENTER);
vTextPaint.setAntiAlias(true);//지그재그 효과
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;
/**반지름을 계산하여 최종 도달할 각도의 길이로 변환--> 반지름 길이*/
float currentAngleLength = scale * angleLength;
/**애니메이션 시작*/
setAnimation(0, currentAngleLength, animationLength);
}
/**
* 진도에 애니메이션 설정
* ValueAnimator는 전체 속성 애니메이션 메커니즘 중 가장 중요한 클래스로, 속성 애니메이션의 실행 메커니즘은 반복적으로 값을 처리하여 구현됩니다.
* 초기 값과 종료 값 사이의 애니메이션 전환은 ValueAnimator 클래스가 책임지게 됩니다.
* 그리고 내부에서는 시간 루프 기계를 사용하여 값을 계산하며 애니메이션을 생성합니다.
* 우리는 초기 값과 종료 값을 ValueAnimator에 제공하고, 그리고 애니메이션이 실행되어야 할 시간을 알려줍니다.
* 그렇다면 ValueAnimator는 자동으로 초기 값에서 원활하게 종료 값으로 이동하는 효과를 완료합니다.
*
* @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();
}
/**
* 문자 크기를 설정하여, 걸음수가 매우 크게 되어서 글자가 들어가지 않도록, 글꼴 크기를 동적으로 설정합니다.
*
* @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.사용 설명서

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" />

Activity에서


7000, 1000);

위에 설명한 것은 저가 여러분에게 소개한 안드로이드 복제 QQ 스타킹 거리 및 애니메이션 효과입니다. 여러분에게 도움이 되길 바랍니다. 어떤 질문이 있으시면 댓글을 남겨 주시기 바랍니다. 저는 즉시 답변을 드리겠습니다. 또한,呐喊 가이드 웹사이트에 대한 여러분의 지원에 깊이 감사드립니다!

성명: 이 글은 인터넷에서 가져왔으며, 저작권자는 모두입니다. 내용은 인터넷 사용자가 자발적으로 기여하고 업로드한 것이며, 이 사이트는 소유권을 가지지 않으며, 인공 편집을 하지 않았으며, 이에 대한 법적 책임도 부담하지 않습니다. 저작권 침해가 의심되는 내용이 있으시면, notice#w로 이메일을 보내 주시기 바랍니다.3codebox.com에 (이메일 보내기 시, #을 @으로 변경하시고) 신고를 하시고, 관련 증거를 제공하시면, 해당 내용이 실제로 침해된 경우, 이 사이트는 즉시 해당 내용을 삭제합니다.

좋아하는 것