Android 사용자 정의 View 링 진도 바 의 사고 와 인 스 턴 스 실현
얼마 전에 콩잎 FM 의 음악 재생 화면 을 보 았 는데 링 모양 의 진도 가 있어 서 너무 예 뻤 어 요.그래서 왜 혼자 만 들 지 않 았 을 까 하 는 생각 이 들 었 어 요.그래서 사용자 정의 과정 을 시 작 했 어 요.
콩짜개 FM 의 재생 화면 은 아래 그림 과 같다.
기능 분석
비록 기능 이 비교적 간단 하지만,여전히 자세하게 분석 해 야 한다.
1.아이콘 밖 에 동그라미 가 하나 더 있어 너비 설정 가능
2.원형 진도 바 와 진도 바 밑 에 너비,색상 등 을 설정 할 수 있 습 니 다.
3.내부 에 둥 근 그림 이 있어 회전 이 가능
사고 분석 을 실현 하 다.
1.원 폭 설정 가능
이것 은 비교적 쉽 습 니 다.onDraw 방법 에서 canvas 로 직접 그리 면 됩 니 다.물론 간격 과 반지름 의 처리 에 있어 서 자세 해 야 합 니 다.컨트롤 본 체 는 긴 사각형 입 니 다.우 리 는 비교적 짧 은 쪽 을 지름 으로 선택 하 는 동시에 내부 의 padding 도 처리 해 야 합 니 다.
2.원형 진도 바 와 진도 바 밑 에 너비,색상 등 을 설정 할 수 있 습 니 다.
이것 은 canvas 의 draw Arc 방법 으로 이 루어 질 수 있 습 니 다.서로 다른 길이 의 원호 형 을 그 려 서 진 도 를 나타 내 는 목적 을 달성 할 수 있 습 니 다.그러나 주의해 야 할 것 은 원호 형의 반지름 과 시작 과 끝 점 을 잘 계산 해 야 합 니 다.
3.내부 에 둥 근 그림 이 있어 회전 이 가능
이 수 요 는 그림,원형,회전 이 가능 한 세 부분 으로 나 눌 수 있다.
먼저 그림 이 있 습 니 다.간단 합 니 다.canvas 의 drawbitmap 방법 으로 그립 니 다.
그리고 원형 은 복잡 하지만 전체적으로 canvas 를 사용 하여 bitmap 를 조작 하고 코드 에서 자세히 말 합 니 다.
마지막 으로 회전 할 수 있 습 니 다.canvas 의 rotate 방법 으로 할 수 있 습 니 다.
효과 전시
이렇게 많은 말 을 했 는데 마지막 효 과 는 어 떨 까요?말 만 으로 는 증거 가 없 으 니 코드 전시 에 들 어가 기 전에 마지막 효 과 를 보 세 요.
이것 은 제 가 직접 만 든 정시 잠 금 화면 프로젝트 입 니 다.주 소 는 여기주소또는로 컬 다운로드입 니 다.
이것 은 이 프로젝트 가 잠 금 화면 을 실행 할 때의 움 직 이 는 그림 입 니 다.
코드 구현
다음은 코드 를 보 여 주 며 분석 을 시작 하 겠 습 니 다.
우리 의 주요 업 무 는 사용자 정의 view 의 onDraw 방법 으로 이 루어 집 니 다.그래서 우 리 는 View 류 를 계승 하 는 하위 클래스 가 필요 합 니 다.우 리 는 그 를 MyProgress 라 고 부 릅 시다.
저희 가 보 여 드 린 게 바로 이 MyProgress 의 onDraw 방법 입 니 다.
1.원 폭 설정 가능
아주 간단 합 니 다.우 리 는 canvas 의 drawCircle 방법 만 호출 하면 됩 니 다.그러나 padding 에 대한 처 리 를 주의해 야 합 니 다.처리 하지 않 으 면 무효 이기 때 문 입 니 다.
super.onDraw(canvas); // onDraw
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom(); // padding
//get the view's width and height and decide the radiu
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingTop - paddingBottom;
radiu = Math.min(width , height) / 2 - boundWidth - progressWidth; // , ,boundWidth ,progressWidth
//setup the paint
paint.setStyle(Paint.Style.STROKE); // paint
paint.setStrokeWidth(boundWidth); //
paint.setColor(Color.BLACK); //
//draw the inner circle
int centerX = paddingLeft + getWidth()/2;
int centerY = paddingTop + getHeight() / 2; //
canvas.drawCircle(centerX,centerY, radiu, paint); //
2.원형 진도 바 와 진도 바 밑 에 너비,색상 등 을 설정 할 수 있 습 니 다.여기 서 주의해 야 할 것 은 바로 시작 하 는 각도 와 끝 나 는 각도 입 니 다.진도 항목 의 목적 을 달성 하기 위해 우 리 는 업무 상태의 변화 에 따라 이 값 을 바 꿔 야 합 니 다.
//set paint for arc
paint.setStrokeWidth(progressWidth);
paint.setStrokeCap(Paint.Cap.ROUND);// ,
//prepare for draw arc
RectF oval = new RectF();
oval.left = centerX -totalRadiu ;
oval.top =centerY- totalRadiu ;
oval.right = centerX + totalRadiu;
oval.bottom = centerY+ totalRadiu; // ,
paint.setColor(progressBackColor);//
//draw background arc
canvas.drawArc(oval, arcStar, arcEnd, false, paint); // ,
//draw progress arc
paint.setColor(progressColor);//
canvas.drawArc(oval, arcStar, progress, false, paint);//
3.내부 에 둥 근 그림 이 있어 회전 이 가능이 단락 은 비교적 복잡 해서 직접 코드 로 설명 한다.
float totalRadiu = radiu +boundWidth +progressWidth/2;//
//draw the circlr pic
if (drawable != null&&bitmap == null) {
image = ((BitmapDrawable) drawable).getBitmap();// bitmap
bitmap = Bitmap.createBitmap((int)(2*totalRadiu),(int)(2*totalRadiu), Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);// bitmap canvas
Paint bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);// paint
bitmapCanvas.drawCircle(totalRadiu, totalRadiu, radiu, bitmapPaint);//
bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));// , ,
bitmapCanvas.drawBitmap(image,null,new RectF(0,0,2*totalRadiu,2*totalRadiu) , bitmapPaint);//
}
Rect rect = new Rect((int)(centerX -totalRadiu),(int)(centerY-totalRadiu),(int)(centerX+totalRadiu),(int)(centerY+ totalRadiu));// rect,
canvas.save();
if(isRotate)
canvas.rotate(rotateDegree,centerX,centerY);// , ,rotateDegree
canvas.drawBitmap(bitmap,null ,rect, paint);//
위의 코드 가 있 으 면 저 희 는 View 의 주체 부분 을 사용자 정의 하면 완 성 됩 니 다.물론 보조 적 인 부분 도 있 습 니 다.예 를 들 어 진도 업데이트 와 각도 선택 함수,색상 과 너비 등 매개 변 수 를 설정 합 니 다.전체 코드
MyProgress
public class MyProgressBar extends View {
float progress = 360;
float arcStar = 270;
float arcEnd = 360;
double rotateStep = 0.2;
Bitmap bitmap;
int totalTime;
Bitmap image;
Drawable drawable;
int boundWidth = 5;
private int progressWidth = 30;
private boolean isRotate = false;
private int progressColor = Color.GREEN;
private int progressBackColor = Color.GREEN;
private float rotateDegree = 0;
public MyProgressBar(Context context) {
super(context);
}
public MyProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private float radiu;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public void setRadiu(float radiu) {
this.radiu = radiu;
invalidate();
}
//start countDownTimer progress
public void start(long time) {
bitmap = null;
time *= 60000;
final float step = (float) 360 / (time / 30);
CountDownTimer mTimer = new CountDownTimer(time, 30) {
public void onTick(long millisUntilFinished) {
progress -= step;
rotateDegree -= rotateStep;
invalidate();
}
@Override
public void onFinish() {
end(step);
}
};
mTimer.start();
}
private void end(float step) {
progress -= step;
invalidate();
progress = 0;
rotateDegree = 0;
invalidate();
}
public void setBoundWidth(int width) {
boundWidth = width;
}
public void setProgressWidth(int width) {
progressWidth = width;
}
public void setProgressColor(int color) {
progressColor = color;
}
public void setProgressBackColor(int color) {
progressBackColor = color;
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
invalidate();
}
public void setIsRote(boolean rotate)
{
this.isRotate = rotate;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
//get the view's width and height and decide the radiu
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingTop - paddingBottom;
radiu = Math.min(width , height) / 2 - boundWidth - progressWidth;
//setup the paint
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(boundWidth);
paint.setColor(Color.BLACK);
//draw the inner circle
int centerX = paddingLeft + getWidth()/2;
int centerY = paddingTop + getHeight() / 2;
canvas.drawCircle(centerX,centerY, radiu, paint);
float totalRadiu = radiu +boundWidth +progressWidth/2;
//draw the circlr pic
if (drawable != null&&bitmap == null) {
image = ((BitmapDrawable) drawable).getBitmap();
bitmap = Bitmap.createBitmap((int)(2*totalRadiu),(int)(2*totalRadiu), Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
Paint bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);
bitmapCanvas.drawCircle(totalRadiu, totalRadiu, radiu, bitmapPaint);
bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
bitmapCanvas.drawBitmap(image,null,new RectF(0,0,2*totalRadiu,2*totalRadiu) , bitmapPaint);
}
Rect rect = new Rect((int)(centerX -totalRadiu),(int)(centerY-totalRadiu),(int)(centerX+totalRadiu),(int)(centerY+ totalRadiu));
canvas.save();
if(isRotate)
canvas.rotate(rotateDegree,centerX,centerY);
canvas.drawBitmap(bitmap,null ,rect, paint);
canvas.restore();
//set paint for arc
paint.setStrokeWidth(progressWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
//prepare for draw arc
RectF oval = new RectF();
oval.left = centerX -totalRadiu ;
oval.top =centerY- totalRadiu ;
oval.right = centerX + totalRadiu;
oval.bottom = centerY+ totalRadiu;
paint.setColor(progressBackColor);
//draw background arc
canvas.drawArc(oval, arcStar, arcEnd, false, paint);
//draw progress arc
paint.setColor(progressColor);
canvas.drawArc(oval, arcStar, progress, false, paint);
}
}
이 사용자 정의 VIEW 를 포함 한 전체 프로젝트 는 GitHub 의 프로젝트 주소여기 있 습 니 다.를 참고 할 수도 있 고로 컬 다운로드총결산
간단 해 보 이 는 사용자 정의 View 제작 에서 생각 할 만 한 문제 가 적지 않 은 것 도 이 글 이 있 는 이유 다.
1.원형 커팅 그림 을 처리 할 때 커팅 된 canvas 가 사용 하 는 좌 표 는 전체 좌표 가 아니 라 그림 을 처리 하 는 것 에 대비 해 야 합 니 다.
2.그림 을 그 릴 때 반복 되 는 처 리 를 최소 화해 야 한다.예 를 들 어 원형 그림 을 자 르 면 한 번 이면 충분 하 다.만약 에 횟수 가 너무 많 으 면 진 도 를 업데이트 할 때마다 한 번 씩 진행 하기 때문에 전체 View 가 비교적 카드 가 되 고 진도 가 정확 하지 않다.
3.사용자 정의 View 의 몇 가지 관건 적 인 좌표 에 대해 비교적 간단 하고 알 기 쉬 운 표현 식 으로 표시 해 야 한다.그렇지 않 으 면 후기 에 헷 갈 리 고 좌표 의 수렁 에 빠 질 수 있다.
4.어떤 강력 해 보 이 는 효 과 는 합 리 적 으로 분석 하고 단계별 로 실현 하 는 것 이 어렵 지 않다.
자,이상 이 이 글 의 모든 내용 입 니 다.본 논문 의 내용 이 안 드 로 이 드 개발 자 여러분 에 게 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.