Android 사용자 정의 view 물결 무늬 진도 구 효과 구현

오늘 우리 가 실현 해 야 할 이 view 는 상호작용 적 인 view 가 많 지 않 기 때문에 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();
종결 어
이로써 우리 의 효 과 를 이 루 었 다.이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 안 드 로 이 드 개발 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기