Android 사용자 정의 view 물결 무늬 진도 구 효과 구현
사용자 정의 view 의 방식 은 매우 깊다.
1.사용자 정의 속성 attrs 가 져 오기(생략 가능)
2.onMeasure 방법 을 다시 쓰 고 컨트롤 의 너비 와 높이 를 계산한다.
3.onDraw 방법 을 다시 쓰 고 컨트롤 을 그립 니 다.
그 러 고 보 니 사용자 정의 view 의 방식 이 분명 하 네요.
오늘 의 효과 도 를 살 펴 보 겠 습 니 다.그 중 하 나 는 느 린 효과 입 니 다.
우 리 는 방법 에 따른다.
사용자 정의 속성
<declare-styleable name="WaveProgressView">
<attr name="radius" format="dimension|reference" />
<attr name="radius_color" format="color|reference" />
<attr name="progress_text_color" format="color|reference" />
<attr name="progress_text_size" format="dimension|reference" />
<attr name="progress_color" format="color|reference" />
<attr name="progress" format="float" />
<attr name="maxProgress" format="float" />
</declare-styleable>
효과 도 를 보면 어떤 속성 이 필요 한 지 알 수 있 습 니 다.말 안 할 게.그 다음 에 우리 의 이러한 속성 을 얻 는 것 은 바로
TypedArray
으로 얻 는 것 이다.물론 구조 에서 얻 을 수 있 습 니 다.일반적으로 우 리 는 구조 방법 을 복사 하고 매개 변수 가 적은 호출 매개 변수 가 많은 다음 에 매개 변수 가 가장 많은 것 으로 갑 니 다.
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WaveProgressView, defStyleAttr, R.style.WaveProgressViewDefault);
radius = (int) a.getDimension(R.styleable.WaveProgressView_radius, radius);
textColor = a.getColor(R.styleable.WaveProgressView_progress_text_color, 0);
textSize = a.getDimensionPixelSize(R.styleable.WaveProgressView_progress_text_size, 0);
progressColor = a.getColor(R.styleable.WaveProgressView_progress_color, 0);
radiusColor = a.getColor(R.styleable.WaveProgressView_radius_color, 0);
progress = a.getFloat(R.styleable.WaveProgressView_progress, 0);
maxProgress = a.getFloat(R.styleable.WaveProgressView_maxProgress, 100);
a.recycle();
주:R.style.WaveProgressView Default 는 이 컨트롤 의 기본 스타일 입 니 다.2.onMeasure 측정
우리 가 이 방법 을 다시 쓰 는 것 은 주로 아버지 가 본 너비 와 높이 를 가지 고 자신의 너비 와 높이 를 설정 하 는 것 이다.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//
int exceptW = getPaddingLeft() + getPaddingRight() + 2 * radius;
int exceptH = getPaddingTop() + getPaddingBottom() + 2 * radius;
int width = resolveSize(exceptW, widthMeasureSpec);
int height = resolveSize(exceptH, heightMeasureSpec);
int min = Math.min(width, height);
this.width = this.height = min;
// , padding
int minLR = Math.min(getPaddingLeft(), getPaddingRight());
int minTB = Math.min(getPaddingTop(), getPaddingBottom());
minPadding = Math.min(minLR, minTB);
radius = (min - minPadding * 2) / 2;
setMeasuredDimension(min, min);
}
우선 이 컨트롤 의 너비 와 높이 는 똑 같 을 것 입 니 다.원 이 니까 요.사실은 너비 와 높이 는 반지름 과 내 변 거리 와 관계 가 있 는데 이곳 의 내 변 거 리 는 우 리 는 상하 좌우 에서 가장 작은 하 나 를 취한 다.너비 와 높이 도 가장 작은 것 을 선택한다.this.width = this.height = min;
좌우 변 거 리 를 포함한다.resolveSize
이 방법 은 우리 가 원 하 는 너비 와 높이 를 잘 실현 해 주 었 다.
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST:
if (specSize < size) {
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size;
}
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
result = size;
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}
우리 가 쓰 면 이렇게 써.마지막 으로
setMeasuredDimension
를 통 해 너비 와 높이 를 설정 합 니 다.3.onDraw 그리 기
많은 안 드 로 이 드 가 API 를 제공 하 는 것 에 대해 서 는 더 이상 말 하지 않 겠 습 니 다.
그림 을 그 리 는 것 은 우선 붓 의 초기 화 이다.
path 경 로 를 그 리 는 붓 을
PorterDuff.Mode.SRC_IN
모드 로 설정 해 야 합 니 다.이 모드 는 겹 치 는 부분 만 표시 합 니 다.
pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pathPaint.setColor(progressColor);
pathPaint.setDither(true);
pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
우 리 는 모든 그림 을 투명 한bitmap
에 그리고 이것bitmap
을 canvas 에 그 릴 것 입 니 다.
if (bitmap == null) {
bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
}
계산 과 그리 기 편 하도록 나 는 좌 표를 평평 하 게 이동padding
하 는 거 리 를 매 었 다.
bitmapCanvas.save();
//
bitmapCanvas.translate(minPadding, minPadding);
// .... some thing
bitmapCanvas.restore();
3.1 원 을 그리다
bitmapCanvas.drawCircle(radius, radius, radius, circlePaint);
3.2 PATH 경 로 를 그립 니 다.첫째,파문 의 좌우 와 상하 의 진폭 이 천천히 줄 어드 는 것 을 실현 해 야 한다.
이것 을 그리 기 전에 우 리 는 2 단계 베 세 르 곡선의 대체적인 원 리 를 알 아야 한다.
쉽게 말 하면 P1 의 시작 점,P2 는 종점 이 고 P1 은 통제 점 이다.세 르 곡선의 공식 을 이용 하면 길 을 따라 가 는 점 을 얻 을 수 있 고 마지막 에 점 을 연결 하면 된다.
다음 그림 은 네트워크 에서 나 옵 니 다.
2 단계 베 세 르 곡선
안 드 로 이 드 sdk 에서 베 어 셀 곡선 을 그 리 는 함수
rQuadTo
방법 을 제공 합 니 다.
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
dx1:제어점 X 좌 표 는 이전 종점 X 좌표 의 변위 좌 표를 나타 내 고 마이너스 가 될 수 있 으 며 플러스 는 더하기,마이너스 는 상쇄 를 나타 낸다.dy1:제어점 Y 좌표,이전 종점 Y 좌표 에 대한 변위 좌표.마찬가지 로 마이너스 가 될 수 있 고 플러스 는 플러스 를 나타 내 며 마이너스 는 상쇄 를 나타 낸다.
dx2:종점 X 좌 표 는 똑 같이 상대 적 인 좌표 이 고 이전 종점 X 좌표 의 변위 치 에 비해 마이너스 가 될 수 있 으 며 플러스 는 플러스 를 나타 내 고 마이너스 수 치 는 상쇄 를 나타 낸다.
dy2:종점 Y 좌 표 는 똑 같이 상대 적 이 고 이전 종점 Y 좌표 의 변위 값 입 니 다.마이너스 가 될 수 있 고 플러스 는 플러스 를 나타 내 며 마이너스 는 상쇄 를 나타 낸다.
이 네 개의 매개 변 수 는 모두 상대 값 으로 전 종점 의 변위 값 에 비해 전달 된다.
진폭 이 천천히 줄 어드 는 것 을 실현 하려 면 우 리 는 제어점 의 y 좌 표를 조절 하면 된다.즉,
float percent=progress * 1.0f / maxProgress;
[0,1]의하나의 폐 구간,[0,1]이 물건 이 좋 군요.마음 에 들 어 요.많은 일 을 할 수 있어 요.
이렇게 하면 우 리 는
percent
에 따라 제어점 의 y 좌 표를 조절 할 수 있다.
//
int count = radius * 4 / 60;
// - y
float point = (1 - percent) * 15;
for (int i = 0; i < count; i++) {
path.rQuadTo(15, -point, 30, 0);
path.rQuadTo(15, point, 30, 0);
}
좌우 파문 을 실현 하려 면 폐쇄 경 로 를 제어 하 는 왼쪽 상단 의 x 좌표 만 있 으 면 된다.물론 근거percent
이기 도 하 다.여러분 은 아래 의 이 그림 을 결합 하여 위의 말 을 이해 할 수 있 습 니 다.
path 가 그린 전체 코드 세 션 입 니 다.
// PATH
//
path.reset();
float percent=progress * 1.0f / maxProgress;
float y = (1 - percent) * radius * 2;
//
path.moveTo(radius * 2, y);
//
path.lineTo(radius * 2, radius * 2);
//
path.lineTo(0, radius * 2);
//
// path.lineTo(0, y);
// , progress
path.lineTo(-(1 -percent) * radius*2, y);
if (progress != 0.0f) {
//
int count = radius * 4 / 60;
// - y
float point = (1 - percent) * 15;
for (int i = 0; i < count; i++) {
path.rQuadTo(15, -point, 30, 0);
path.rQuadTo(15, point, 30, 0);
}
}
//
path.close();
bitmapCanvas.drawPath(path, pathPaint);
3.3 진행 텍스트 그리 기이것 은 비교적 간단 합 니 다.컨트롤 의 중간 에 그리 면 됩 니 다.문자 에 관 한 좌표 계산 은 여전히 이해 하기 쉽다.
//
String text = progress + "%";
float textW = textPaint.measureText(text);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float baseLine = radius - (fontMetrics.ascent + fontMetrics.descent) / 2;
bitmapCanvas.drawText(text, radius - textW / 2, baseLine, textPaint);
마지막 으로 우리 의bitmap
를 canvas 에 그 리 는 것 을 잊 지 마 세 요.
canvas.drawBitmap(bitmap, 0, 0, null);
아,마지막 으로 실 용적 인 방법 입 니 다.여 기 는 thread+handler 를 사용 하지 않 고 속성 애니메이션 을 사용 합 니 다.알 잖 아!!!like
ObjectAnimator objectAnimator0 = ObjectAnimator.ofFloat(waveProgressView_0, "progress", 0f, 100f);
objectAnimator0.setDuration(3300);
objectAnimator0.setInterpolator(new LinearInterpolator());
objectAnimator0.start();
종결 어이로써 우리 의 효 과 를 이 루 었 다.이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 안 드 로 이 드 개발 에 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.