android仿winphone进度指示器的实现
转载注明出处。
这里说的效果指的是winphone的忽快忽慢的小圆点(恩,你懂得吧= =)。分为转圈和直线两种。在网上看到有人实现了直线的,于是下下来源码看了一下,顺带实现了转圈的。感觉还算好看。在这里做个记录。顺便谢谢那个慷慨开源的哥们儿~~、
先说说直线运动小圆点的原理吧。定义一个数组分别对于小圆点,再定义一个同样大小的数组规定每个点的Visibility情况。由后者控制每个点的可见性。定义直线上3/10的区域是慢速区域,其他为快速区。开启一个线程,线程每运行一次画面刷新一次。每个点依次出发,之间有一定时间间隔。根据点运行的距离判断下一次点应该在哪。下面是代码。在原作的基础上我给出了更详细的注释。读者应该能一遍看懂了~工程文件我就不提供了,大家自己实现吧。
1 package com.example.dialog; 2 3 import android.content.Context; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.Paint; 7 import android.graphics.RectF; 8 import android.os.Handler; 9 import android.util.AttributeSet; 10 import android.util.Log; 11 import android.view.View; 12 13 public class WP7ProgessView extends View { 14 15 private int mColor = Color.RED; 16 private int mBackgroundColor = Color.BLACK; 17 private Paint mPainter = null; 18 19 private static final int RECT_NUMBER = 5; 20 private static int[] sPos = new int[RECT_NUMBER]; 21 private static int[] sVisible = new int[RECT_NUMBER]; 22 23 private static final int RECT_WIDTH = 5; // px 24 25 private static final float SLOW_RANGE = 0.30f; // 有30%的空间是慢的 26 27 private static final int UPDATE_PROGRESS_INTERVAL = 28; // ms 28 29 private static final int STANDARD_SCREEN_W = 480; // px 30 31 private UpdateProgessThread mThread = null; 32 33 public WP7ProgessView(Context context) { 34 this(context, null); 35 } 36 37 public WP7ProgessView(Context context, AttributeSet attrs) { 38 this(context, attrs, 0); 39 } 40 41 public WP7ProgessView(Context context, AttributeSet attrs, int defStyle) { 42 super(context, attrs, defStyle); 43 } 44 45 public WP7ProgessView(Context context, int color) { 46 this(context, null, 0); 47 mColor = color; 48 mPainter = new Paint(); 49 mPainter.setAntiAlias(true); 50 mPainter.setColor(mColor); 51 mPainter.setStyle(Paint.Style.FILL); 52 setBackgroundColor(mBackgroundColor); 53 } 54 55 public void setColor(int color) { 56 mColor = color; 57 mPainter.setColor(mColor); 58 } 59 60 public int getColor() { 61 return mColor; 62 } 63 64 @Override 65 public void draw(Canvas canvas) { 66 canvas.drawColor(mBackgroundColor); 67 super.draw(canvas); 68 69 for (int i = 0; i < RECT_NUMBER; i++) { 70 if (sVisible[i] == View.VISIBLE) { 71 drawRect(canvas, sPos[i]); 72 } 73 } 74 } 75 76 private void drawRect(Canvas canvas, int pos) { 77 int m = getHeight() / 2; 78 int w = RECT_WIDTH / 2; 79 canvas.drawRect(new RectF(pos - w, m - w, pos + w, m + w), mPainter); 80 } 81 82 @Override 83 protected void onAttachedToWindow() { 84 super.onAttachedToWindow(); 85 mThread = new UpdateProgessThread("WP7ProgessView", this); 86 mThread.start(); 87 } 88 89 @Override 90 protected void onDetachedFromWindow() { 91 mThread.stopping(); 92 mThread = null; 93 super.onDetachedFromWindow(); 94 } 95 96 @Override 97 protected void onWindowVisibilityChanged(int visibility) { 98 // TODO Auto-generated method stub 99 super.onWindowVisibilityChanged(visibility); 100 } 101 102 private static final class UpdateProgessThread extends Thread { 103 private WP7ProgessView host = null;//就理解为宿主吧。。 104 private int mInvisibleCount = 0; // 控制是不是重新开始一次循环,当都不可见了则说明需要重新开始了 105 private int mPosToShowNext = 0; // 显示下一个方块坐标 106 private int mIndexToShowNext = 0; // 检查显示下一个方块的方块坐标,如果为0则表示刚刚开始 107 108 private long mSleepTime = 0; 109 110 private boolean running = true; 111 112 public UpdateProgessThread(String name, WP7ProgessView v) { 113 super(name); 114 host = v; 115 for (int i = 0; i < RECT_NUMBER; i++) { 116 117 // 让所有的小方块不显示 118 sPos[i] = -RECT_WIDTH; 119 sVisible[i] = View.GONE; 120 } 121 122 // 至少先让第一个可见 123 sVisible[0] = View.VISIBLE; 124 } 125 126 public void run() { 127 int w = host.getWidth(); 128 Log.d("XXXXX", "w = " + w); 129 int slowRange = 0; 130 int fastRange1 = 0; 131 132 while (running) { 133 if (w <= 0) {//一般不会小于0只会等于0.此时这个view还没有被绘制,以下是准备操作 134 w = host.getWidth(); 135 slowRange = (int) (w * SLOW_RANGE); 136 fastRange1 = (w - slowRange) / 2; 137 Log.e("width", w + " " + slowRange + " " + fastRange1); 138 } 139 if (w > 0 && mSleepTime <= 0) { 140 mSleepTime = (long) (UPDATE_PROGRESS_INTERVAL 141 * STANDARD_SCREEN_W / w); 142 } 143 // int fastRange2 = fastRange1; 144 145 if (mPosToShowNext == 0) { 146 /** 147 * 现在我们来决定五个小方框的出现时机,研究了Windows Phone 7的progress 148 * dialog,它的效果是 149 * 至少能让五个小方块在同时出现在慢区域。所以在第一个方块走出慢区域的时候,第五个必然要进入慢区域. 150 * 算法是五个方块都要在慢区,所以他们的间隔是 slowRange/6, 快区是慢区的4/3倍,所以显示间隔就是 151 * slowRange * (1/6) * (4/3)。 152 */ 153 mPosToShowNext = (int) (slowRange * 2.0 / 9); 154 } 155 156 if (mIndexToShowNext < RECT_NUMBER - 1 ) { 157 /** 158 * 如果指定的方块跑过了显示下一个方块的点,则显示下一个方块。 159 */ 160 //因为第一个点已经是可见的,所以是RECT_NUMBER - 1 161 if (sPos[mIndexToShowNext] > mPosToShowNext) { 162 mIndexToShowNext++; 163 sVisible[mIndexToShowNext] = View.VISIBLE; 164 Log.e("index", "mIndexToShowNext:" + mIndexToShowNext); 165 } 166 } 167 168 try { 169 // 更新界面的时间间隔。 170 Thread.sleep(mSleepTime); 171 } catch (InterruptedException e) { 172 e.printStackTrace(); 173 } 174 175 for (int i = 0; i < RECT_NUMBER; i++) { 176 if (sVisible[i] != View.VISIBLE) { 177 // 如果这个点是看不见的,则不更新了。 178 Log.e("i", i + ""); 179 continue; 180 } 181 if (sPos[i] <= fastRange1 182 || sPos[i] >= (fastRange1 + slowRange)) { 183 // 让它移动快点。 184 sPos[i] += (2 * RECT_WIDTH); 185 } else if ((sPos[i] - fastRange1) < slowRange) { 186 // 让它移动慢点。 187 sPos[i] += RECT_WIDTH; 188 } 189 // 如果已经移出边界,则让它看不见 190 if (sPos[i] > w) { 191 sVisible[i] = View.GONE; 192 sPos[i] = -RECT_WIDTH; 193 } 194 } 195 196 mInvisibleCount = 0; 197 198 for (int i = 0; i < RECT_NUMBER; i++) { 199 if (sVisible[i] != View.VISIBLE) { 200 mInvisibleCount++; 201 } 202 } 203 204 // 如果需要重新开始,则初始化一些变量。 205 if (mInvisibleCount >= RECT_NUMBER) { 206 mIndexToShowNext = 0; 207 sVisible[0] = View.VISIBLE; 208 } 209 210 host.postInvalidate(); 211 } 212 } 213 214 public void stopping() { 215 running = false;//方便控制线程运行与否。 216 // stop(); 217 } 218 } 219 220 }
同时提供我稍作修改的一个Circle类。它是转圆圈的ProgressView。这个Circle类是一个自定义View,在每次返回键被按了时再进去会重新启动一个线程,看起来就是圈圈转的更快了。还有就是我的onMeasure方法没有重写,,懒得写了。所以在drawCircle
方法里你会看到我x,y坐标都加了十,那是为了偏离边界好看清楚我的圆。。。如果要用你可以自行修改这俩小bug.其它的我还没发现。其实bug1在每次activity的onStop()里把线程stopThread()一下就好了。下面是代码。这个注释就少了。可以参照上面看。主要变化的就是把他的距离变成了我的弧度,他只跑一圈我为了和winphone一样让小球跑两圈。恩请看代码:
1 package com.example.dialogcircle; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Color; 7 import android.graphics.Paint; 8 import android.util.AttributeSet; 9 import android.util.Log; 10 import android.view.View; 11 12 public class Circle extends View{ 13 14 private static final int UPDATE_PROGRESS_INTERVAL = 30;//ms 15 private static final float DEGREE = (float) 720.0;//一周360度 16 private static final float SLOWRANGE = (float) (360.0 * 0.3f);//慢的空间 17 private static final float FASTRANGE = (float) ((360.0 - SLOWRANGE) / 2);//慢的空间 18 private static final float SLICE = 5;//每次递增度数为10度 19 private static final float RADIUS = 5;//小圆的半径 20 21 private int mColor = Color.WHITE; 22 private float mRadius = 0; 23 24 25 private Paint mPainter = null; 26 27 private static int dotNum = 4; 28 29 private static float[] degOfDot; 30 private static int[] visibleDot; 31 32 private Context mContext; 33 34 public static UpdateThread mThread = null; 35 36 public Circle(Context context) { 37 super(context); 38 } 39 40 public Circle(Context context, AttributeSet attrs){ 41 super(context, attrs); 42 TypedArray paramsArray = context.obtainStyledAttributes(attrs, 43 R.styleable.Circle); 44 mColor = paramsArray.getColor(R.styleable.Circle_color, Color.WHITE); 45 mRadius = paramsArray.getFloat(R.styleable.Circle_radius, 120.0f); 46 dotNum = paramsArray.getInt(R.styleable.Circle_dotNum, 4); 47 48 mPainter = new Paint(); 49 mPainter.setAntiAlias(true); 50 mPainter.setStyle(Paint.Style.FILL); 51 mPainter.setColor(mColor); 52 53 degOfDot = new float[dotNum]; 54 visibleDot = new int[dotNum]; 55 paramsArray.recycle(); 56 57 mThread = new UpdateThread(this); 58 mThread.start(); 59 if(!mThread.isAlive())mThread.notify(); 60 } 61 public Circle(Context context, AttributeSet attrs, int defStyle){ 62 super(context, attrs, defStyle); 63 } 64 65 public void draw(Canvas canvas){ 66 super.draw(canvas); 67 for(int i = 0; i < dotNum; i++){ 68 if(visibleDot[i] == View.VISIBLE){ 69 drawCircle(canvas, degOfDot[i]); 70 } 71 } 72 } 73 private void drawCircle(Canvas canvas, float deg){ 74 float cx = 0, cy = 0; 75 cx = (float) (mRadius * ( 1.0 + Math.sin( deg / 180.0 * Math.PI))) + 10; 76 cy = (float) (mRadius * ( 1.0 - Math.cos( deg / 180.0 * Math.PI))) + 10; 77 canvas.drawCircle(cx, cy , RADIUS, mPainter); 78 } 79 80 81 static final class UpdateThread extends Thread{ 82 private Circle host = null; 83 private int mInvisibleCount = 0;//是否重新开始循环 84 private float mDegToShowNext = 0;//下一个圆角度 85 private int mIndexToShowNext = 0; 86 87 private long mSleepTime = UPDATE_PROGRESS_INTERVAL; 88 89 private boolean running = true; 90 91 public UpdateThread(Circle c){ 92 super(); 93 host = c; 94 for(int i = 0; i < dotNum; i++){ 95 degOfDot[i] = 0; 96 visibleDot[i] = View.GONE; 97 } 98 visibleDot[0] = View.VISIBLE; 99 } 100 public void run(){ 101 while(running){ 102 if(mDegToShowNext == 0){ 103 mDegToShowNext = (float)(SLOWRANGE * 2.0 / 9); 104 } 105 if(mIndexToShowNext < dotNum - 1){ 106 if(degOfDot[mIndexToShowNext] > mDegToShowNext){ 107 mIndexToShowNext++; 108 visibleDot[mIndexToShowNext] = View.VISIBLE; 109 } 110 } 111 try { 112 Thread.sleep(mSleepTime); 113 } catch (InterruptedException e) { 114 // TODO: handle exception 115 e.printStackTrace(); 116 } 117 118 for(int i = 0; i < dotNum; i++){ 119 if(visibleDot[i] != View.VISIBLE){ 120 continue; 121 } 122 //以下是运动范围分类 123 if(degOfDot[i] <= FASTRANGE 124 || (degOfDot[i] >= (FASTRANGE + SLOWRANGE) 125 && degOfDot[i] < (360.0 + FASTRANGE / 2.0)) 126 || (degOfDot[i] >= (360.0 + FASTRANGE / 2.0 + SLOWRANGE)) 127 &&(degOfDot[i] < 720.0) ){ 128 degOfDot[i] += (2.0 * SLICE); 129 }else if ((degOfDot[i] < FASTRANGE + SLOWRANGE) 130 && (degOfDot[i] > FASTRANGE) 131 || (degOfDot[i] < (360.0 + FASTRANGE / 2.0 + SLOWRANGE)) 132 && (degOfDot[i] >= (360.0 + FASTRANGE / 2.0))){ 133 // 让它移动慢点。 134 degOfDot[i] += SLICE; 135 } 136 if(degOfDot[i] >= DEGREE){ 137 visibleDot[i] = View.GONE; 138 degOfDot[i] = 0; 139 } 140 } 141 142 mInvisibleCount = 0; 143 144 for(int i = 0; i < dotNum; i++){ 145 if(visibleDot[i] != View.VISIBLE){ 146 mInvisibleCount++; 147 } 148 } 149 if(mInvisibleCount >= dotNum){ 150 mIndexToShowNext = 0; 151 visibleDot[0] = View.VISIBLE; 152 } 153 host.postInvalidate(); 154 } 155 } 156 public void stopThread(){ 157 running = false; 158 } 159 } 160 }
有任何问题请留言。为了大家的可持续发展我不提供源代码。程序员不能懒啊><
转载于:https://www.cnblogs.com/elefish/archive/2012/11/08/WpProgressView.html
android仿winphone进度指示器的实现相关推荐
- android仿微信 进度条,Android开发之模仿微信打开网页的进度条效果(高仿)
一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下 "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是 ...
- android进度指示器_等待的痛苦—浏览进度指示器地狱的7个级别
android进度指示器 by Mike Zetlow 由Mike Zetlow 等待的痛苦-浏览进度指示器地狱的7个级别 (The Pain of Waiting - Navigating the ...
- Android笔记之(图片高斯+Glide实现微信图片加载策略+仿微信进度条)
很久以前就想自己实现一下仿微信图片加载的那种策略了,先加载一张模糊的图片,然后再加载清晰大图,今天研究了一下,不过要是Glide支持进度条显示就好了,不得不说Glide很强大, 不啰嗦了,直接上代码了 ...
- android 余额宝收益列表,Android 仿支付宝中的余额宝收益进度条
一. 看效果 二.上代码 package com.framework.widget; import android.app.Activity; import android.content.Conte ...
- android 余额宝,Android 仿支付宝中的余额宝收益进度条
一. 看效果 二.上代码 package com.framework.widget; import android.app.activity; import android.content.conte ...
- android加载h5页面加进度条,使用Android仿微信加载H5页面的进度条
这篇文章主要为大家详细介绍了Android仿微信加载H5页面进度条,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 前言 Android中WebView打卡前端页面时受到网路环境,页面内容大小的影响 ...
- Android 仿微信小程序开屏页加载loading
Android 仿微信小程序开屏页加载loading 废话不多说,先上效果图~ 首先就是底层有一个灰色的圆,然后按照圆形的轨迹进行绘制. 啊~说那么多也没用,还是直接上代码吧,哈哈哈哈 绘制底部圆形及 ...
- Android仿抖音加载框之两颗小球转动控件
Android仿抖音加载框之两颗小球转动控件 本篇文章已授权微信公众号 hongyangAndroid(鸿洋)独家发布. 效果图 安卓版抖音v2.5加载框: 本控件效果图: 使用方法 源码地址:And ...
- Android 仿微信录制短视频(不使用 FFmpeg)
转载请标明出处与作者:https://blog.csdn.net/u011133887/article/details/83654724 项目中原本就有录制短视频的功能,使用的是 # qdrzwd/V ...
- Android 仿钉钉、微信 群聊组合头像
CombineBitmap 项目地址:SheHuan/CombineBitmap 简介: Android 仿钉钉.微信 群聊组合头像 更多:作者 提 Bug 标签: 效果预览 功能 生成类似钉 ...
最新文章
- 情人节学写html5微信游戏
- 简要说明建设城市大脑三条关键标准规范
- 神经网络预测模型算法_MATLAB Elman神经网络的数据预测—电力负荷预测模型研究...
- python 类-9. 类 — Python 3.9.0 文档
- 今天感觉有点冷了其实。
- MySQL(MariaDB)之参数详解(-)
- CodeForces - 91B Queue(单调队列+二分)
- 最新web 2.0 配色 (一)
- Java垃圾收集器:G1GC何时将CMS强制退出?
- mysql主从复制原理详解_深入研究MySQL(三)、主从复制原理及演示
- Eclipse maven工程 Missing artifact com.sun:tools:jar:1.7.0:system 解决方法
- ABSynthe : 侧信道攻击加密函数窃取密钥
- 巧用批处理cmd快速切换IP地址
- python迅雷远程下载页面_迅雷远程下载
- Microsoft Word 教程:如何在 Word 中创建项目符号列表、显示字数统计?
- NLPCC-2019 依存句法分析领域移植评测技术分享(封闭情况下双第一)
- 一个大数据架构师应该掌握的技能
- JMeter对接口进行压力测试
- 在以TCP为连接方式的服务器中,为什么在服务端设计当中需要考虑心跳?
- 金字塔原理(麦肯锡)-要点汇总
热门文章
- 通过互联网搜索接口更新拼写语法库的设计
- matlab的lambda,matlab lambda 级数
- shell 字符串中是否包含任一字符串
- ubuntu 卸载python_如何在各种环境下正确安装python——Linux
- 开始php脚本,php bypass disable function
- heapsort(Java)(最小堆)
- OpenGL快速入门
- Apache 代理nodejs[未测试]
- 北航教授王田苗:中国机器人的发展机遇与挑战是什么?
- 使用PInvoke.NET插件为托管代码添加Win32 API签名