Android 사용자 정의 뷰 수면 상승 효과 구현
 
 실현 방향:
1.원 중 수면 상승 효 과 를 어떻게 실현 하 는 지:Paint 의 setXfermode 속성 을 이용 하여 Porter Duff.Mode.SRCIN 진도 가 있 는 사각형 과 원 의 교 집합 을 그립 니 다.
2.어떻게 물결 무늬 효과:베 어 셀 곡선 을 이용 하여 파 의 피크 수 치 를 동태 적 으로 바 꾸 고'진도 가 증가 함 에 따라 물결 무늬 가 점점 작 아 지 는 효과'를 실현 합 니까?
말 이 많 지 않 으 니 코드 를 보 세 요.
우선 사용자 정의 속성 값 입 니 다.어떤 사용자 정의 속성 값 이 있 습 니까?
원 배경 색:circlecolor,진도 색상:progresscolor,진행 표시 텍스트 색상:textcolor,진행 텍스트 크기:textsize,그리고 마지막:파문 최대 높이:rippletopheight
<declare-styleable name="WaterProgressView"> 
 <attr name="circle_color" format="color"/><!--    --> 
 <attr name="progress_color" format="color"/><!--     --> 
 <attr name="text_color" format="color"/><!--     --> 
 <attr name="text_size" format="dimension"/><!--    --> 
 <attr name="ripple_topheight" format="dimension"/><!--        -->
</declare-styleable>구성원 변수
public class WaterProgressView extends ProgressBar {
 //       
 public static final int DEFAULT_CIRCLE_COLOR = 0xff00cccc;
 //       
 public static final int DEFAULT_PROGRESS_COLOR = 0xff00CC66;
 //       
 public static final int DEFAULT_TEXT_COLOR = 0xffffffff;
 //       
 public static final int DEFAULT_TEXT_SIZE = 18;
 //        
 public static final int DEFAULT_RIPPLE_TOPHEIGHT = 10;
 private Context mContext;
 private Canvas mPaintCanvas;
 private Bitmap mBitmap;
 //     
 private Paint mCirclePaint;
 //        
 private int mCircleColor;
 //      
 private Paint mProgressPaint;
 //         
 private int mProgressColor ;
 //    path
 private Path mProgressPath;
 //          
 private int mRippleTop = 10;
 //       
 private Paint mTextPaint;
 //       
 private int mTextColor;
 private int mTextSize = 18;
 //    ,             ,        
 private int mTargetProgress = 50;
 //         
 private GestureDetector mGestureDetector;
}
private void getAttrValue(AttributeSet attrs) { 
 TypedArray ta = mContext.obtainStyledAttributes(attrs, R.styleable.WaterProgressView); 
 mCircleColor = ta.getColor(R.styleable.WaterProgressView_circle_color,DEFAULT_CIRCLE_COLOR);    
 mProgressColor = ta.getColor(R.styleable.WaterProgressView_progress_color,DEFAULT_PROGRESS_COLOR); 
 mTextColor = ta.getColor(R.styleable.WaterProgressView_text_color,DEFAULT_TEXT_COLOR);  
 mTextSize = (int) ta.getDimension(R.styleable.WaterProgressView_text_size, DesityUtils.sp2px(mContext,DEFAULT_TEXT_SIZE)); 
 mRippleTop = (int)ta.getDimension(R.styleable.WaterProgressView_ripple_topheight,DesityUtils.dp2px(mContext,DEFAULT_RIPPLE_TOPHEIGHT)); 
 ta.recycle();
}mProgressPaint.setXfermode
// new          
public WaterProgressView(Context context) { 
 this(context,null);
}
// xml         View        
public WaterProgressView(Context context, AttributeSet attrs) { 
 this(context, attrs,0);
}
public WaterProgressView(Context context, AttributeSet attrs, int defStyleAttr) { 
 super(context, attrs, defStyleAttr); 
 this.mContext = context; 
 getAttrValue(attrs); 
 //           
 initPaint(); 
 mProgressPath = new Path(); 
}
private void initPaint() { 
 //      paint
 mCirclePaint = new Paint(); 
 mCirclePaint.setColor(mCircleColor); 
 mCirclePaint.setStyle(Paint.Style.FILL); 
 mCirclePaint.setAntiAlias(true); 
 mCirclePaint.setDither(true); 
 //       paint
 mProgressPaint = new Paint(); 
 mProgressPaint.setColor(mProgressColor); 
 mProgressPaint.setAntiAlias(true); 
 mProgressPaint.setDither(true); 
 mProgressPaint.setStyle(Paint.Style.FILL); 
 //  mProgressPaint      ,   xfermode PorterDuff.Mode.SRC_IN               ,    
 mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 
 //           
 mTextPaint = new Paint(); 
 mTextPaint.setColor(mTextColor); 
 mTextPaint.setStyle(Paint.Style.FILL); 
 mTextPaint.setAntiAlias(true); 
 mTextPaint.setDither(true); 
 mTextPaint.setTextSize(mTextSize);
}onMeasure()방법 코드:
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
 //   ,       View   ,       MeasureSpec.EXACTLY
 int width = MeasureSpec.getSize(widthMeasureSpec); 
 int height = MeasureSpec.getSize(heightMeasureSpec); 
 setMeasuredDimension(width,height); 
 //   Bitmap,    drawCircle,drawPath,drawText draw  bitmap   canvas ,     bitmap   onDraw   canvas ,
 //   bitmap width,height    left,top,right,bottom padding
 mBitmap = Bitmap.createBitmap(width-getPaddingLeft()-getPaddingRight(),height- getPaddingTop()-getPaddingBottom(), Bitmap.Config.ARGB_8888); 
 mPaintCanvas = new Canvas(mBitmap);
}drawPath 의 절 차 는 다음 과 같 습 니 다.
 
 그 중에서 ratio 의 코드 는 다음 과 같다.즉,ratio 는 현재 진도 가 전체 진도 에서 차지 하 는 백분율 이다.
float ratio = getProgress()*1.0f/getMax();
int rightTop = (int) ((1-ratio)*height);
mProgressPath.moveTo(width,rightTop);
mProgressPath.lineTo(width,height);
mProgressPath.lineTo(0,height);
mProgressPath.lineTo(0,rightTop); 
 우 리 는 파 봉 의 최고점 을 10 으로 설정 하면 한 단락 의 파장 은 40 이 고
width*1.0f/40단락 의 이런 곡선 을 그 려 야 한다 면 곡선 을 그 리 는 코드 는 다음 과 같다.
int count = (int) Math.ceil(width*1.0f/(10 *4));
for(int i=0; i<count; i++) { 
 mProgressPath.rQuadTo(10,10,2* 10,0);
 mProgressPath.rQuadTo(10,-10,2* 10,0);  
}
mProgressPath.close();
mPaintCanvas.drawPath(mProgressPath,mProgressPaint);
float top = (mTargetProgress-getProgress())*1.0f/mTargetProgress* mRippleTop;
float top = (mTargetProgress-getProgress())*1.0f/mTargetProgress* mRippleTop;
for(int i=0; i<count; i++) { 
 mProgressPath.rQuadTo(mRippleTop,top,2* mRippleTop,0);
 mProgressPath.rQuadTo(mRippleTop,-top,2* mRippleTop,0); 
}그러나 그림 에서 더 블 클릭 할 때 수면 이 0%에서 목표 진도 로 올 라 가 고 클릭 할 때 수면 이 목표 진도 에서 계속 움 직 이 는 효 과 를 어떻게 실현 합 니까?
먼저 더 블 클릭 효과 의 실현 을 말 합 니 다.이것 은 간단 합 니 다.Handler 를 정의 합 니 다.더 블 클릭 할 때
handler.postDelayed(runnable,time) 일정 시간progress+1마다 runnable 에서invalidate()진 도 를 계속 업데이트 하고 현재 progress 가 mTarget Progress 에 도착 할 때 까지 계속 업데이트 합 니 다.코드 는 다음 과 같다.
/**
 *       
 */
private void startDoubleTapAnimation() { 
 setProgress(0); 
 doubleTapHandler.postDelayed(doubleTapRunnable,60);
}
private Handler doubleTapHandler = new Handler(){ 
 @Override 
 public void handleMessage(Message msg) {  
 super.handleMessage(msg); 
 }
};
//      , 60ms      
private Runnable doubleTapRunnable = new Runnable() { 
 @Override 
 public void run() {  
 if(getProgress() < mTargetProgress) {   
  invalidate();   
  setProgress(getProgress()+1);   
  doubleTapHandler.postDelayed(doubleTapRunnable,60);  
 } else {   
  doubleTapHandler.removeCallbacks(doubleTapRunnable);  
 } 
 }
};mSingleTapAnimationCount-- 그리고 우 리 는 초기 파 봉 을 한 번 에 플러스 로 바 꾸 면 수면 에서 밀 려 오 는 효 과 를 실현 할 수 있 습 니 다.핵심 코드 는 다음 과 같 습 니 다.
private void startSingleTapAnimation() { 
 isSingleTapAnimation = true; 
 singleTapHandler.postDelayed(singleTapRunnable,200);
}
private Handler singleTapHandler = new Handler(){ 
 @Override 
 public void handleMessage(Message msg) {  
 super.handleMessage(msg); 
 }
};
//      , 200ms      
private Runnable singleTapRunnable = new Runnable() { 
 @Override 
 public void run() {  
 if(mSingleTapAnimationCount > 0) {   
  invalidate();   
  mSingleTapAnimationCount--;   
  singleTapHandler.postDelayed(singleTapRunnable,200);  
 } else {   
  singleTapHandler.removeCallbacks(singleTapRunnable);  
 //            
  isSingleTapAnimation = false;   
 //           50 
  mSingleTapAnimationCount = 50;  
 } 
 }
};변 경 된 코드 는 다음 과 같 습 니 다.
//   
mProgressPath.reset();
//      draw path
int rightTop = (int) ((1-ratio)*height);
mProgressPath.moveTo(width,rightTop);
mProgressPath.lineTo(width,height);
mProgressPath.lineTo(0,height);
mProgressPath.lineTo(0,rightTop);
//      ,     
int count = (int) Math.ceil(width*1.0f/(mRippleTop *4));
//    animation  
if(!isSingleTapAnimation&&getProgress()>0) { 
 float top = (mTargetProgress-getProgress())*1.0f/mTargetProgress* mRippleTop; 
 for(int i=0; i<count; i++) {  
 mProgressPath.rQuadTo(mRippleTop,-top,2* mRippleTop,0);   
 mProgressPath.rQuadTo(mRippleTop,top,2* mRippleTop,0); 
 }
} else { 
 //  animation  ,       , mRippleTop  2 
 //             ,           
 float top = (mSingleTapAnimationCount*1.0f/50)*10; 
 //         
 if(mSingleTapAnimationCount%2==0) {  
  for(int i=0; i<count; i++) {   
  mProgressPath.rQuadTo(mRippleTop *2,top*2,2* mRippleTop,0);    
  mProgressPath.rQuadTo(mRippleTop *2,-top*2,2* mRippleTop,0);   
 } 
 } else {  
 for(int i=0; i<count; i++) {   
  mProgressPath.rQuadTo(mRippleTop *2,-top*2,2* mRippleTop,0);    
  mProgressPath.rQuadTo(mRippleTop *2,top*2,2* mRippleTop,0); 
 } 
 }
}
mProgressPath.close();
mPaintCanvas.drawPath(mProgressPath,mProgressPaint);주의 점:
1.drawCircle 에서 padding 을 고려 하려 면 circle 의 너비 와 높이 는 getWidth 와 getHeight 에서 padding 값 을 빼 고 코드 는 다음 과 같 습 니 다.
//   bitmap    
int width = getWidth()-getPaddingLeft()-getPaddingRight();
int height = getHeight()-getPaddingTop()-getPaddingBottom();
//  
mPaintCanvas.drawCircle(width/2,height/2,height/2,mCirclePaint); 
 그럼 baseline 의 height 좌 표를 어떻게 얻 습 니까?
Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
//  ascent baseline  ,  ascent   。descent+ascent   ,        
float baseLine = height*1.0f/2 - (metrics.descent+metrics.ascent)/2;
//     
String text = ((int)(ratio*100))+"%";
//       
float textWidth = mTextPaint.measureText(text);
Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
//descent+ascent   ,        
float baseLine = height*1.0f/2 - (metrics.descent+metrics.ascent)/2;
mPaintCanvas.drawText(text,width/2-textWidth/2,baseLine,mTextPaint);(getPaddingLeft(),getPaddingTop())에 번역 하 는 것 을 기억 하 세 요.
canvas.translate(getPaddingLeft(),getPaddingTop());
canvas.drawBitmap(mBitmap,0,0,null);총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.