Android 자체 보기 QQ 운동 걸음 수 원호 및 애니메이션 효과 구현

이전Android 초 정밀 만보 기 개발-Dylan 만보의 첫 페이지 에 사용자 정의 컨트롤 을 사 용 했 습 니 다.QQ 운동 의 인터페이스 와 비슷 하고 애니메이션 효과 도 있 습 니 다.다음은 이 View 가 어떻게 그 려 졌 는 지 알려 드 리 겠 습 니 다.
1.효과 도 를 먼저 본다
这里写图片描述
2.효과 도 분석
기능 설명:노란색 은 사용자 가 설정 한 총 계획 단련 걸음 수 를 대표 하고 빨간색 은 사용자 가 현재 가 고 있 는 걸음 수 를 대표 합 니 다.
초보 분석:View 재 작성 onDraw()방법 을 완전히 사용자 정의 하고 원 호 를 그립 니 다.
3.원 호 를 그 리 는 데 필요 한 지식
Canvas 에서 원 호 를 그 리 는 방법 이 있어 요.
drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)//그림 호,
매개 변 수 는 RectF 대상 이 고 사각형 구역 의 타원형 경 계 는 모양,크기,전호 에 정의 합 니 다.
매개 변수 두 번 째 는 시작 각(도)이 전호 의 시작,원호 의 시작 각도,단 위 는 도 이다.
매개 변수 3 원호 가 스 캔 한 각 도 는 시계 방향,단 위 는 도 이 고 오른쪽 중간 부터 0 도 입 니 다.
매개 변수 4 는 true(진짜)라면 원 호 를 그 릴 때 원심 을 포함 시 켜 부채 형 을 그립 니 다.false(가짜)라면 이것 은 포물선 이 될 것 입 니 다.
매개 변수 5 는 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  ,                   、  、  ,
       ( )      ,      ,    。
          ,     ,    ,         。
        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 단계]'걸음 수'의 빨간색 숫자 그리 기

/**
* 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 에 제공 하고 애니메이션 이 실행 되 는 시간 을 알려 주면 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;
/**
* Created by DylanAndroid on 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);
/**【   】         */
drawArcYellow(canvas, rectF);
/**【   】           */
drawArcRed(canvas, rectF);
/**【   】           */
drawTextNumber(canvas, centerX);
/**【   】  "  "     */
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  ,                   、  、  ,
       ( )      ,      ,    。
          ,     ,    ,         。
        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" />
활동 중

StepArcView sv = (StepArcView) findViewById(R.id.sv);
sv.setCurrentCount(7000, 1000);
위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 안 드 로 이 드 모방 QQ 운동 걸음 수 원호 와 애니메이션 효과 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 저 에 게 메 시 지 를 남 겨 주세요.소 편 은 신속하게 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기