2019独角兽企业重金招聘Python工程师标准>>>

自定义控件—— 波浪形状圆形进度加载

时间管理的基础是精力管理,精力的高低、正负分影响到我们的效率

而时间是无法管理的,能够管理的只有自己,透过管理自己的习惯,管理自己的事件来达成对时间的管理。

而在每一天中,人生不丰于做多少事,而在于把重要的事情专注做、用心做,把它做到极致。

1、效果简阅

2、实现思路设计

3、初始化操作

private void init(Context context) {//绘制圆形的 PaintmCicrlPaint = new Paint();mCicrlPaint.setAntiAlias(true);mCicrlPaint.setColor(Color.BLUE);//绘制进度的 PaintmProgressPaint = new Paint();mProgressPaint.setAntiAlias(true);mProgressPaint.setColor(Color.RED);//设置只绘制重叠的部分mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//绘制文字的 PaintmTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setColor(Color.WHITE);mTextPaint.setTextSize(20);//绘制进度的PathmPath = new Path();/*** 手势识别监听*/final GestureDetector gestureDetector = new GestureDetector(listener);/*** 将触摸识别事件传递给 GestureDetector*/this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return gestureDetector.onTouchEvent(event);}});this.setClickable(true);//设置布局加载监听 this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//更新控件的大小viewHeight = ProgressView.this.getHeight();viewWidth = ProgressView.this.getWidth();//创建 bitmap 与 canvasbitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(bitmap);/*** 更新默认设置*/updateDefaulBuildValue();}});}GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {/*** 单击点击监听* @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {System.out.println("sing click ");if (clickListener != null) {clickListener.onSingleClick(e);return true;}return super.onSingleTapConfirmed(e);}/*** 双击点击监听* @param e* @return*/@Overridepublic boolean onDoubleTap(MotionEvent e) {if (clickListener != null) {clickListener.onDoubleClick(e);}return super.onDoubleTap(e);}/*** 常按事件监听* @param e*/@Overridepublic void onLongPress(MotionEvent e) {if (clickListener != null) {clickListener.onLongPressClick(e);}super.onLongPress(e);}};

同时设置了点击事件的监听接口回调

/*** 控件 点击事件监听 回调*/public interface OnWaveProgressClickListener {/*** 单击回调接口* @param e*/public void onSingleClick(MotionEvent e);/*** 双击回调接口* @param e*/public void onDoubleClick(MotionEvent e);/*** 找按回调接口* @param e*/public void onLongPressClick(MotionEvent e);}private OnWaveProgressClickListener clickListener;/*** 设置控件的点击事件** @param listener*/public void setWaveOnClickListener(OnWaveProgressClickListener listener) {this.clickListener = listener;}

4、测量

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);/*** 绘制的为正方形进度条,测量比较较小的长度为圆形的直径长度*/int width;int height;width = Math.min(widthSize, heightSize);height = Math.min(widthSize, heightSize);setMeasuredDimension(width, height);}

5、绘制

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制整体圆形mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);//绘制进度图形mPath.reset();//进度图形的高度   随着加载进度的改变float y = (1 - (float) currentProgress / maxProgress) * viewHeight;mPath.moveTo(viewWidth, y);mPath.lineTo(viewWidth, viewHeight);mPath.lineTo(0, viewHeight);mPath.lineTo(0, y);
///*** 计算振幅的比例* 振幅 的大小 是随着进度的大小动态改变的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}mPath.close();mCanvas.drawPath(mPath, mProgressPaint);
////绘制 中间显示的百分比文字String text = "" + (int) (((float) currentProgress / maxProgress) * 100);//获取绘制文字的宽度float textWidth = mTextPaint.measureText(text);//获取绘制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低处的距离//Ascent是baseline之上至字符最高处的距离//ascent + descent 就是测量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//计算绘制中间显示进度文字的坐标float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//绘制显示进度的文字mCanvas.drawText(text, textX, textY, mTextPaint);canvas.drawBitmap(bitmap, 0, 0, null);}

绘制分析

5.1绘制圆形背景

5.2绘制进度

5.3绘制波浪曲线

曲线分析 一

曲线分析 二

曲线分析三

绘制:

 /*** 计算振幅的比例* 振幅 的大小 是随着进度的大小动态改变的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}

效果

上面的图形中绘制了四组正反曲线,也就是说分别绘制了四个开口向上的曲线,四个开口向下的曲线,

这里采用的绘制思想是每一次都 绘制一个开口向上的曲线 和一个开口向下的曲线,然后形成一个完整的类似正弦曲线的线形,这里绘制了四次,也就是在FOR循环中循环了四次,具体的循环次数是不定的,依据控件的大小来动态设置

5.4绘制显示文本

//获取绘制文字的宽度float textWidth = mTextPaint.measureText(text);//获取绘制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低处的距离//Ascent是baseline之上至字符最高处的距离//ascent + descent 就是测量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//计算绘制中间显示进度文字的坐标float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//绘制显示进度的文字mCanvas.drawText(text, textX, textY, mTextPaint);

其中涉及到一些文本测量

6、完整源码

package com.animation.androidlongs.a360animationapplication.view;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;/*** Created by androidlongs on 16/8/9.*/
public class WaveProgressView extends View {private Paint mCicrlPaint;private Paint mProgressPaint;private Paint mTextPaint;private Canvas mCanvas;private Path mPath;private Bitmap bitmap;public WaveProgressView(Context context) {super(context);init(context);}public WaveProgressView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public WaveProgressView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {//绘制圆形的 PaintmCicrlPaint = new Paint();mCicrlPaint.setAntiAlias(true);mCicrlPaint.setColor(Color.BLUE);//绘制进度的 PaintmProgressPaint = new Paint();mProgressPaint.setAntiAlias(true);mProgressPaint.setColor(Color.RED);//设置只绘制重叠的部分mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//绘制文字的 PaintmTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setColor(Color.WHITE);mTextPaint.setTextSize(20);//绘制进度的PathmPath = new Path();/*** 手势识别监听*/final GestureDetector gestureDetector = new GestureDetector(listener);/*** 将触摸识别事件传递给 GestureDetector*/this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return gestureDetector.onTouchEvent(event);}});this.setClickable(true);//设置布局加载监听 this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//更新控件的大小viewHeight = WaveProgressView.this.getHeight();viewWidth = WaveProgressView.this.getWidth();//创建 bitmap 与 canvasbitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(bitmap);/*** 更新默认设置*/updateDefaulBuildValue();}});}GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {/*** 单击点击监听* @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {System.out.println("sing click ");if (clickListener != null) {clickListener.onSingleClick(e);return true;}return super.onSingleTapConfirmed(e);}/*** 双击点击监听* @param e* @return*/@Overridepublic boolean onDoubleTap(MotionEvent e) {if (clickListener != null) {clickListener.onDoubleClick(e);}return super.onDoubleTap(e);}/*** 常按事件监听* @param e*/@Overridepublic void onLongPress(MotionEvent e) {if (clickListener != null) {clickListener.onLongPressClick(e);}super.onLongPress(e);}};@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);/*** 绘制的为正方形进度条,测量比较较小的长度为圆形的直径长度*/int width;int height;width = Math.min(widthSize, heightSize);height = Math.min(widthSize, heightSize);setMeasuredDimension(width, height);}/*** 默认控件的 宽 高* 默认的 当前的进度    总的进度*/public int viewWidth = 150;public int viewHeight = 150;public int currentProgress = 0;public int maxProgress = 100;/*** 计算振幅大小 所用的比例数 默认为10*/private int mAplitudeCunt = 10;/*** 默认振幅的大小 为控件高度的 1/10*/private int mDefaulAmplitude = viewHeight / mAplitudeCunt;/*** 计算周期长度使用的比例数 默认为8*/private int mPriodicCount = 8;/*** 曲线默认的周期长度*/private int mDefaulPriodic = viewHeight / mPriodicCount;/*** 曲线的绘制次数*/private int mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);/*** 更新默认的设置*/private void updateDefaulBuildValue() {if (viewHeight < 400) {mPriodicCount = 8;mAplitudeCunt = 10;} else if (viewHeight < 600 && viewHeight >= 400) {mPriodicCount = 14;mAplitudeCunt = 16;} else if (viewHeight < 1000 && viewHeight >= 600) {mPriodicCount = 20;mAplitudeCunt = 20;} else if (viewHeight < 1400 && viewHeight >= 100) {mAplitudeCunt = 24;mPriodicCount = 26;} else {mPriodicCount = 30;mAplitudeCunt = 30;}/*** 默认振幅的大小 为控件高度的 1/10*/mDefaulAmplitude = viewHeight / mAplitudeCunt;/*** 曲线默认的周期长度*/mDefaulPriodic = viewHeight / 8;/*** 曲线的绘制次数*/mquadLineDrawCount = (int) ((float) viewWidth / mDefaulPriodic);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制整体圆形mCanvas.drawCircle(viewWidth / 2, viewWidth / 2, viewWidth / 2, mCicrlPaint);//绘制进度图形mPath.reset();//进度图形的高度   随着加载进度的改变float y = (1 - (float) currentProgress / maxProgress) * viewHeight;mPath.moveTo(viewWidth, y);mPath.lineTo(viewWidth, viewHeight);mPath.lineTo(0, viewHeight);mPath.lineTo(0, y);
///*** 计算振幅的比例* 振幅 的大小 是随着进度的大小动态改变的*/int amplitude = (int) ((1 - (float) currentProgress / maxProgress) * mDefaulAmplitude);if (currentProgress % 2 == 0) {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);}} else {for (int i = 0; i < mquadLineDrawCount; i++) {mPath.rQuadTo(mDefaulPriodic / 2, amplitude, mDefaulPriodic, 0);mPath.rQuadTo(mDefaulPriodic / 2, -amplitude, mDefaulPriodic, 0);}}mPath.close();mCanvas.drawPath(mPath, mProgressPaint);
////绘制 中间显示的百分比文字String text = "" + (int) (((float) currentProgress / maxProgress) * 100);//获取绘制文字的宽度float textWidth = mTextPaint.measureText(text);//获取绘制文字的高度Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//Descent是baseline之下至字符最低处的距离//Ascent是baseline之上至字符最高处的距离//ascent + descent 就是测量文字的高度float textHeight = fontMetrics.ascent + fontMetrics.descent;//计算绘制中间显示进度文字的坐标float textY = viewHeight / 2 - textHeight / 2;float textX = viewWidth / 2 - textWidth / 2;//绘制显示进度的文字mCanvas.drawText(text, textX, textY, mTextPaint);canvas.drawBitmap(bitmap, 0, 0, null);}/*** 控件 点击事件监听 回调*/public interface OnWaveProgressClickListener {/*** 单击回调接口** @param e*/public void onSingleClick(MotionEvent e);/*** 双击回调接口** @param e*/public void onDoubleClick(MotionEvent e);/*** 找按回调接口** @param e*/public void onLongPressClick(MotionEvent e);}private OnWaveProgressClickListener clickListener;/*** 控件 加载进度回调接口*/public interface OnWaveProgressListener {public void onProgresUpdate(int progress);public void onFinish();}private OnWaveProgressListener progressListener;/*** 设置更新当前进度** @param progress*/public void updateProgress(int progress) {if (progress <= 0) {progress = 0;} else if (progress > this.maxProgress) {progress = maxProgress;}this.currentProgress = progress;//进度更新接口回调if (progressListener != null) {progressListener.onProgresUpdate(currentProgress);}if (progress == maxProgress) {if (progressListener != null) {progressListener.onFinish();}}//重绘invalidate();}/*** 设置最大进度** @param max*/public void setMaxProgress(int max) {if (max <= 0) {max = 100;}this.setMaxProgress(max);}/*** 设置控件的点击事件** @param listener*/public void setWaveOnClickListener(OnWaveProgressClickListener listener) {this.clickListener = listener;}/*** 加载进度监听设置** @param listener*/public void setWaveOnProgressListener(OnWaveProgressListener listener) {this.progressListener = listener;}}

7、Activity中的使用

package com.animation.androidlongs.a360animationapplication;import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;import com.animation.androidlongs.a360animationapplication.view.WaveProgressView;public class MainActivity extends AppCompatActivity {private WaveProgressView customWaveProgressView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(MainActivity.this, FloatViewService.class);//startService(intent);customWaveProgressView = (WaveProgressView) findViewById(R.id.progress);handler.postDelayed(runnable,2000);//设置点击事件监听customWaveProgressView.setWaveOnClickListener(new WaveProgressView.OnWaveProgressClickListener() {@Overridepublic void onSingleClick(MotionEvent e) {System.out.println("onSingleClick");}@Overridepublic void onDoubleClick(MotionEvent e) {System.out.println("onDoubleClick");}@Overridepublic void onLongPressClick(MotionEvent e) {System.out.println("onLongPressClick");}});//设置进度更新监听customWaveProgressView.setWaveOnProgressListener(new WaveProgressView.OnWaveProgressListener() {@Overridepublic void onProgresUpdate(int progress) {}@Overridepublic void onFinish() {}});}private Handler handler = new Handler();private Runnable runnable = new Runnable() {@Overridepublic void run() {currentNum++;customWaveProgressView.updateProgress(currentNum);if (currentNum<maxNum){handler.postDelayed(runnable,200);}else {handler.removeCallbacks(runnable);currentNum = 0;}}};private int maxNum = 100;private int currentNum =0;
}

转载于:https://my.oschina.net/u/2447911/blog/730908

Android自定义波浪加载圆形进度条——(自定义控件 一)相关推荐

  1. android 环形时间显示_Android自定义波浪加载圆形进度条——(自定义控件 一)...

    自定义控件-- 波浪形状圆形进度加载 时间管理的基础是精力管理,精力的高低.正负分影响到我们的效率 而时间是无法管理的,能够管理的只有自己,透过管理自己的习惯,管理自己的事件来达成对时间的管理. 而在 ...

  2. android 海浪动画,android自定义波浪加载动画的实现代码

    本文实例为大家分享了android自定义波浪加载动画的具体代码,供大家参考,具体内容如下 效果图 1.自定义控件 WaveView package com.example.wh.myapplicati ...

  3. Process插件:typecho加载页面进度条插件

    介绍: typecho加载页面进度条插件 这是一款适用于typecho任何主题的加载页面进度条,可以让你的博客加载时显得更加顺滑而不会显得过于突兀,使用本插件可以很好得起到视觉缓冲的作用. 本插件有十 ...

  4. html加载swf 进度条,Flash加载外部文件创建进度条3种方法

    Flash加载外部文件创建进度条3种方法 互联网   发布时间:2008-10-07 09:36:14   作者:佚名   我要评论 加载外部文件的进度条(看帮助文档整理),只适合那些不愿看帮助文档的 ...

  5. 精通Android自定义View(十四)绘制水平向右加载的进度条

    1引言 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制三部曲综合 ...

  6. android自定义透明圆形,Android progressdialog自定义背景透明的圆形进度条类似于Dialog...

    很高兴能为大家分享一个背景是透明的圆形进度,先开效果图 效果图如下: 效果图 实现方法如下: 首先准备自己要定义成哪样子的效果的图片. 圆形进度条 1.创建Dialog的代码,你可以自己封装成一个方法 ...

  7. android 环形时间显示_Android圆形进度条颜色的设置

    最近几天由于项目的需要研究了一下listView的滑动数据动态的更新显示,其中需要在数据加载过程有圆形进度条的显示,遇到的问题是进度条的颜色设置,在网上查了一些资料结合自己的所得分享在此. xml布局 ...

  8. Android 自定义ImageView加载图片

    自定义imageview功能: 可以实现设置图片显示的时候,依据本身的比例进行图片的缩放 加载图片效果: 使用ImageLoader来加载 图片: 首先将ImageLoader的jar包关联到项目中 ...

  9. js - 预加载+监听图片资源加载制作进度条

    这两天遇到一个新需求:一个一镜到底的h5动画.因为功能的特殊性,就要求我们提前监听页面的静态图片是否全部加载完毕.即处理预加载. 总结下来,下次这种需求需要提前注意以下几点: 一.图片而不是背景图 本 ...

最新文章

  1. 2022-2028年中国儿童医疗行业深度调研及投资前景预测报告
  2. 系统更新链接服务器超时,Win10系统更新后Dr.com连接认证服务器一直超时如何解决?...
  3. 在C#中,变量名前的@符号是什么意思? [重复]
  4. 4.1 - 并发编程 - 进程练习题
  5. 007_FastDFS文件下载流程
  6. linux怎么还原bak文件,Linux restore命令:还原dump操作备份下的文件、目录或分区...
  7. 高性能Web动画和渲染原理系列(5)合成层的生成条件和陷阱
  8. 临时更换swap优先级
  9. 如何借助大数据提升医疗质量管理
  10. VS2010中添加WebService注意的几个地方
  11. php1怎么获取网卡id号,C#获得MAC地址(网卡序列号)代码
  12. 秩和比RSR法算法C语言,秩和比法(用秩和比法计算权重时怎样编秩?)
  13. Ubuntu下使用date显示毫秒级
  14. Spring 集成教程
  15. 民族传统体育类毕业论文文献都有哪些?
  16. word 职称计算机考试大纲,全国职称计算机考试Word2003大纲(1)
  17. 从看脸到读心:深度理解人的视觉技术走到哪了?
  18. java数据库连接Druidsql失败_Druid数据库连接池异常connection holder is null
  19. 【python】详解multiprocessing多进程-Pool进程池模块(二)
  20. 安装ubuntu 遇到的问题

热门文章

  1. 如何去除C#Strings中的空格?
  2. klib库下的kroundup32(二进制的四舍五入)算法
  3. JavaScript DOM编程艺术 - 读书笔记1-3章
  4. [转]ubuntu linux下DNS重启后丢失(不是Network-manager造成的情况)
  5. JAVA 重载,重写(覆盖)个人理解
  6. PHP双引号的小隐患
  7. 【VBA研究】查找目录以下全部文件的名称
  8. powerpoint打字慢
  9. Forefront Security For Exchange的反病毒测试
  10. -Git 使用技巧 总结 MD