Android 사용자 정의 view 의 모방 결제 보 깨 신용 계기판 예제
대비 그림:
우선 일부 속성 을 사용자 정의 할 수 있 습 니 다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RoundIndicatorView">
<!-- -->
<attr name="maxNum" format="integer"/>
<!-- -->
<attr name="startAngle" format="integer"/>
<!-- -->
<attr name="sweepAngle" format="integer"/>
</declare-styleable>
</resources>
이 어 구조 방법 에서 사용자 정의 속성 과 붓 을 초기 화 합 니 다.
private void initAttr(AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.RoundIndicatorView);
maxNum = array.getInt(R.styleable.RoundIndicatorView_maxNum,500);
startAngle = array.getInt(R.styleable.RoundIndicatorView_startAngle,160);
sweepAngle = array.getInt(R.styleable.RoundIndicatorView_sweepAngle,220);
//
sweepInWidth = dp2px(8);
sweepOutWidth = dp2px(3);
array.recycle();
}
private void initPaint() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(0xffffffff);
paint_2 = new Paint(Paint.ANTI_ALIAS_FLAG);
paint_3 = new Paint(Paint.ANTI_ALIAS_FLAG);
paint_4 = new Paint(Paint.ANTI_ALIAS_FLAG);
}
다음은 onMeasure 를 다시 쓰 는 것 도 간단 합 니 다.확정 값 이 아 닌 300*400 의 크기 를 직접 지정 합 니 다.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
if (wMode == MeasureSpec.EXACTLY ){
mWidth = wSize;
}else {
mWidth =dp2px(300);
}
if (hMode == MeasureSpec.EXACTLY ){
mHeight= hSize;
}else {
mHeight =dp2px(400);
}
setMeasuredDimension(mWidth,mHeight);
}
핵심 부분 인 onDraw 가 왔 습 니 다.원 의 반지름 을 구조 방법 에서 설정 하지 않도록 주의 하 세 요.그 때 는 view 의 너비 와 높 은 값 을 얻 을 수 없 기 때문에 저 는 onDraw 방법 에서 반지름 을 설정 합 니 다.기본 값 은 view 너비 의 1/4 입 니 다.원점 을 view 의 중심 으로 이동:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
radius = getMeasuredWidth()/4; // ,
canvas.save();
canvas.translate(mWidth/2,(mWidth)/2);
drawRound(canvas); //
drawScale(canvas);//
drawIndicator(canvas); //
drawCenterText(canvas);//
canvas.restore();
}
절차 가 뚜렷 하고 순서대로 계기판 의 네 부분 을 그 려 서 우 리 는 한 부분 씩 본다.drawRound():이 건 간단 합 니 다.내외 원호 에 필요 한 속성 이 정의 되 었 습 니 다.붓 은 흰색 입 니 다.setAlpha()를 통 해 투명 도 를 설정 합 니 다.범 위 는 00~ff 입 니 다.
private void drawRound(Canvas canvas) {
canvas.save();
//
paint.setAlpha(0x40);
paint.setStrokeWidth(sweepInWidth);
RectF rectf = new RectF(-radius,-radius,radius,radius);
canvas.drawArc(rectf,startAngle,sweepAngle,false,paint);
//
paint.setStrokeWidth(sweepOutWidth);
int w = dp2px(10);
RectF rectf2 = new RectF(-radius-w , -radius-w , radius+w , radius+w);
canvas.drawArc(rectf2,startAngle,sweepAngle,false,paint);
canvas.restore();
}
제1 부분 완성,그림 참조drawScale():사용자 정의 view 글 을 몇 편 보 았 다 면 회전 캔버스 로 눈금 과 문 자 를 그 리 는 방법 을 알 고 있 을 것 입 니 다.canvas.rotate 를 호출 하면 캔버스 를 회전 시 킬 수 있 습 니 다.음 수 는 시계 방향 을 대표 합 니 다.여기 서 우 리 는 시작 위 치 를 원점 바로 위,즉 270 도 까지 회전 시 켜 눈금 과 문자 의 좌 표를 잘 계산 할 계획 입 니 다.그림 을 다 그 릴 때마다 시계 반대 방향 으로 눈금 간격 을 돌려 그림 이 끝 날 때 까지 순환 합 니 다.우 리 는 원 도 를 살 펴 보 자.굵 은 눈금 선 은 모두 6 개 이 고 숫자의 눈금 은 다시 굵 은 눈금 선 아래 에 있 으 며 두 개의 굵 은 눈금 선 사이 에 5 개의 가 는 눈금 선 이 있 고 중간 에 있 는 세분 선 아래 에 대응 하 는 문자 가 있다.우 리 는 스 캔 한 각 도 를 30 으로 나 누 면 각 눈금 의 간격 이 고 판단 을 통 해 대응 하 는 눈금 과 문 자 를 그 릴 수 있다.
텍스트 의 너비 와 높이 를 얻 는 방법 은 두 가지 가 있 습 니 다.하 나 는 paint.measuretext(text)로 문자 의 폭 을 측정 하고 반환 값 유형 은 float 이지 만 높이 를 얻 지 못 합 니 다.다른 하 나 는 Rect rect=new Rect();paint.getTextBounds(text,0,text.length(),rect); 텍스트 의 속성 을 rect 에 넣 는 것 은 int 값 에 불과 합 니 다.우리 가 그린 문 자 는 매우 작 기 때문에 첫 번 째 로 높이 가 필요 하지 않 으 면 사용 하 는 것 이 좋 습 니 다.
또한,나 는 문 자 를 그 릴 때 좌표 값 은 문자 의 왼쪽 아래 각 을 대표 하고 일반적인 왼쪽 상단 과 다 르 기 때문에 canvas.drawText 에서 들 어 오 는 xy 좌 표 는 text 의 왼쪽 아래 좌표 이다.
private String[] text ={" "," "," "," "," "};
private void drawScale(Canvas canvas) {
canvas.save();
float angle = (float)sweepAngle/30;//
canvas.rotate(-270+startAngle); // (270)
for (int i = 0; i <= 30; i++) {
if(i%6 == 0){ //
paint.setStrokeWidth(dp2px(2));
paint.setAlpha(0x70);
canvas.drawLine(0, -radius-sweepInWidth/2,0, -radius+sweepInWidth/2+dp2px(1), paint);
drawText(canvas,i*maxNum/30+"",paint);
}else { //
paint.setStrokeWidth(dp2px(1));
paint.setAlpha(0x50);
canvas.drawLine(0,-radius-sweepInWidth/2,0, -radius+sweepInWidth/2, paint);
}
if(i==3 || i==9 || i==15 || i==21 || i==27){ //
paint.setStrokeWidth(dp2px(2));
paint.setAlpha(0x50);
drawText(canvas,text[(i-3)/6], paint);
}
canvas.rotate(angle); //
}
canvas.restore();
}
private void drawText(Canvas canvas ,String text ,Paint paint) {
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(sp2px(8));
float width = paint.measureText(text); // getTextBounds , float,
// Rect rect = new Rect();
// paint.getTextBounds(text,0,text.length(),rect);
canvas.drawText(text,-width/2 , -radius + dp2px(15),paint);
paint.setStyle(Paint.Style.STROKE);
}
두 번 째 부분 이 끝나 면 그림 을 보 세 요.draw Indicator:이 단 계 는 화 외 원호 의 진도 값 입 니 다.원 도 를 관찰 한 결과 세 가지 문 제 를 해결 해 야 합 니 다.진 도 를 나타 내 는 라디에이터 값 과 작은 원점 의 좌 표 는 어떻게 계산 하고 진도 값 의 투명 도 점 변 은 어떻게 실현 합 니까?작은 원점 이 광원 처럼 가장자리 가 모호 한 효 과 는 어떻게 실현 합 니까?
좌표 계산 에 있어 서도 비교적 간단 합 니 다.현재 값 을 최대 치 에 비교 하고 하나의 비례 를 얻 으 면 진도 조 가 스 캔 한 라디안 을 계산 할 수 있 습 니 다.작은 원점 은 진도 조 의 끝 을 그립 니 다.각 도 는 이미(시작 각도+스 캔 한 각도)가 있 습 니 다.삼각함수 로 계산 하면 됩 니 다.
색상 그 라 데 이 션 에 대해 서 는 paint 의 shader 로 렌 더 링 할 수 있 습 니 다.5 개의 키 가 있 습 니 다.
작은 도 트 에 광원 과 같은 가장자리 퍼 지 효과 가 있 습 니 다.저 는 paint 의 setMask Filter 를 사 용 했 습 니 다.그 중 하 나 는 BlurMask Filter 가 가장자리 퍼 지 효 과 를 실현 할 수 있 습 니 다~(다른 방법 이 있 는 지 모 르 겠 습 니 다) 코드
private int[] indicatorColor = {0xffffffff,0x00ffffff,0x99ffffff,0xffffffff};
여기 색상 배열 이 이렇게 값 을 추출 하 는 이 유 는 글 마지막 에 설명 합 니 다.
private void drawIndicator(Canvas canvas) {
canvas.save();
paint_2.setStyle(Paint.Style.STROKE);
int sweep;
if(currentNum<=maxNum){
sweep = (int)((float)currentNum/(float)maxNum*sweepAngle);
}else {
sweep = sweepAngle;
}
paint_2.setStrokeWidth(sweepOutWidth);
Shader shader =new SweepGradient(0,0,indicatorColor,null);
paint_2.setShader(shader);
int w = dp2px(10);
RectF rectf = new RectF(-radius-w , -radius-w , radius+w , radius+w);
canvas.drawArc(rectf,startAngle,sweep,false,paint_2);
float x = (float) ((radius+dp2px(10))*Math.cos(Math.toRadians(startAngle+sweep)));
float y = (float) ((radius+dp2px(10))*Math.sin(Math.toRadians(startAngle+sweep)));
paint_3.setStyle(Paint.Style.FILL);
paint_3.setColor(0xffffffff);
paint_3.setMaskFilter(new BlurMaskFilter(dp2px(3), BlurMaskFilter.Blur.SOLID)); //
canvas.drawCircle(x,y,dp2px(3),paint_3);
canvas.restore();
}
하드웨어 가속 을 닫 는 것 을 기억 하 십시오.바로3 부 완료,그림 보기
draw Center Text:이 단 계 는 간단 합 니 다.방금 말 한 문 자 를 그 릴 때 왼쪽 아래 에서 시작 하 는 것 과 두 가지 문자 폭 의 차 이 를 측정 하면 됩 니 다.
private void drawCenterText(Canvas canvas) {
canvas.save();
paint_4.setStyle(Paint.Style.FILL);
paint_4.setTextSize(radius/2);
paint_4.setColor(0xffffffff);
canvas.drawText(currentNum+"",-paint_4.measureText(currentNum+"")/2,0,paint_4);
paint_4.setTextSize(radius/4);
String content = " ";
if(currentNum < maxNum*1/5){
content += text[0];
}else if(currentNum >= maxNum*1/5 && currentNum < maxNum*2/5){
content += text[1];
}else if(currentNum >= maxNum*2/5 && currentNum < maxNum*3/5){
content += text[2];
}else if(currentNum >= maxNum*3/5 && currentNum < maxNum*4/5){
content += text[3];
}else if(currentNum >= maxNum*4/5){
content += text[4];
}
Rect r = new Rect();
paint_4.getTextBounds(content,0,content.length(),r);
canvas.drawText(content,-r.width()/2,r.height()+20,paint_4);
canvas.restore();
}
여기까지 그리 기 부분 이 거의 완성 되 지 않 았 습 니 다.다음은 값 을 바 꿀 때 애니메이션 효 과 를 실현 하고 배경 색 을 바 꾸 는 것 입 니 다.setCurrent NumAnim 은 사용자 가 호출 할 수 있 도록 제공 합 니 다.속성 애니메이션 을 통 해 현재 값 을 변경 할 수 있 습 니 다.현재 값(currentNum)에 setter 와 getter 를 추가 해 야 합 니 다.속성 애니메이션 내부 에서 호출 해 야 하기 때 문 입 니 다.
애니메이션 의 시간 에 대해 계산 공식 을 간단하게 쓰 고 애니메이션 과정 을 감청 하여 배경 색 의 변 화 를 실현 한다.어떻게 해야만 알 리 페 이 깨 신용 처럼 레 드 오렌지 옐 로 우 블 루 의 그 라 데 이 션 을 할 수 있 습 니까?나 는 내 생각 에 따라 세 가지 색깔 사이 의 그 라 데 이 션 효 과 를 실현 했다.
여러분 은 속성 애니메이션 을 배 울 때 플러그 인 평가 기의 역할 을 알 아야 합 니 다.저 는 ArgbEvaluator 평가 기 를 사용 하여 색상 의 점진 적 인 변 화 를 실현 하고 그의 evaluate 방법 을 호출 하여 0~1 의 비례 를 전달 하고 시작 과 끝 에 있 는 색 을 전달 하면 현재 비례 에 따라 이 두 색 사이 에 있 는 색상 값 을 얻 을 수 있 습 니 다.
여기 서 저 는 빨간색 에서 오렌지,그리고 파란색 까지 의 그 라 데 이 션 을 실 현 했 습 니 다.최대 치 는 500 이 라 고 가정 하면 현재 치 x 는 0~250 과정 에서 빨간색 에서 오렌지,x/(500/2)까지 0~1 의 변화 비례 를 얻 을 수 있 습 니 다.현재 치 는 250~500 과정 에서 오렌지 에서 파란색 까지 0~1 의 변화 과정 비례 가 필요 합 니 다.계산 방법 은(x-250)/(250)입 니 다. 그 중 250 은(500/2)얻 은 것 이다.이런 사고방식 에 따라 당연히 더 많은 색깔 간 의 점차 적 인 변 화 를 실현 할 수 있다.바로 방법 을 강구 하여 각 구간 에서 0~1 의 비례 치 를 계산 하면 된다.데이터 형식 변환 에 주의 하 세 요.코드 를 올 리 세 요!
public int getCurrentNum() {
return currentNum;
}
public void setCurrentNum(int currentNum) {
this.currentNum = currentNum;
invalidate();
}
public void setCurrentNumAnim(int num) {
float duration = (float)Math.abs(num-currentNum)/maxNum *1500+500; //
ObjectAnimator anim = ObjectAnimator.ofInt(this,"currentNum",num);
anim.setDuration((long) Math.min(duration,2000));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
int color = calculateColor(value);
setBackgroundColor(color);
}
});
anim.start();
}
private int calculateColor(int value){
ArgbEvaluator evealuator = new ArgbEvaluator();
float fraction = 0;
int color = 0;
if(value <= maxNum/2){
fraction = (float)value/(maxNum/2);
color = (int) evealuator.evaluate(fraction,0xFFFF6347,0xFFFF8C00); //
}else {
fraction = ( (float)value-maxNum/2 ) / (maxNum/2);
color = (int) evealuator.evaluate(fraction,0xFFFF8C00,0xFF00CED1); //
}
return color;
}
짜 잔 짜 잔~외부 에서 setCurrent NumAnim 을 호출 하면 애니메이션 의 수 치 를 바 꿀 수 있 습 니 다.자,그리고 마지막 질문 은 앞에서 언급 한 것 입 니 다.
왜 투명도 그 라 데 이 션 색상 배열 이 이 렇 습 니까?
private int[] indicatorColor = {0xffffffff,0x00ffffff,0x99ffffff,0xffffffff};
대개 불투명-->투명-->반투명-->불투명 한 변화―첫 번 째 는 불필요 하지 않 습 니까?왜 처음부터 불투명 해 야 합 니까?
답:저도 좀 궁금 합 니 다.sweepGradient 색상 의 점차 적 인 변 화 는 x 정 축 에서 시작 되 기 때 문 입 니 다.제 색상 배열 이 이 렇 습 니 다.즉,투명->반투명->불투명:
private int[] indicatorColor = {0x00ffffff,0x99ffffff,0xffffffff};
그러면 원 을 그 려 서 이렇게 생 겼 어 요.그리고 우리 의 계기판 은 160 도 에서 시작 하여 220 도 를 쓸 었 다.즉,이렇게 일부 각도(0~20 도)가 투명 해 지면 우리 가 원 하 는 효과 가 아니 라 는 것 이다.그래서 나 는 이렇게 썼 다.
private int[] indicatorColor = {0xffffffff,0x00ffffff,0x99ffffff,0xffffffff};
이런 배열.이렇게 그 려 져 있어 요.이렇게 하면 적어도 0~20 도 는 하 얗 게 보이 고 전체 진도 조 는 투명 에서 불투명 까지 의 효 과 를 실현 한다.
사실 우아 하 지 는 않 아 요.시작 각도 와 스 캔 한 각 도 는 사용자 정의 로 변경 할 수 있 기 때문이다.그래서 친구 들 에 게 더 좋 은 방법 이 있 나 요?
원본 주소:http://xiazai.jb51.net/201701/yuanma/diy_roundindicator_jb51.rar
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.