转载注明出处。

这里说的效果指的是winphone的忽快忽慢的小圆点(恩,你懂得吧= =)。分为转圈和直线两种。在网上看到有人实现了直线的,于是下下来源码看了一下,顺带实现了转圈的。感觉还算好看。在这里做个记录。顺便谢谢那个慷慨开源的哥们儿~~、

   先说说直线运动小圆点的原理吧。定义一个数组分别对于小圆点,再定义一个同样大小的数组规定每个点的Visibility情况。由后者控制每个点的可见性。定义直线上3/10的区域是慢速区域,其他为快速区。开启一个线程,线程每运行一次画面刷新一次。每个点依次出发,之间有一定时间间隔。根据点运行的距离判断下一次点应该在哪。下面是代码。在原作的基础上我给出了更详细的注释。读者应该能一遍看懂了~工程文件我就不提供了,大家自己实现吧。 

WP7ProgressView

  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一样让小球跑两圈。恩请看代码:

Cirlcle

  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进度指示器的实现相关推荐

  1. android仿微信 进度条,Android开发之模仿微信打开网页的进度条效果(高仿)

    一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下  "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是 ...

  2. android进度指示器_等待的痛苦—浏览进度指示器地狱的7个级别

    android进度指示器 by Mike Zetlow 由Mike Zetlow 等待的痛苦-浏览进度指示器地狱的7个级别 (The Pain of Waiting - Navigating the ...

  3. Android笔记之(图片高斯+Glide实现微信图片加载策略+仿微信进度条)

    很久以前就想自己实现一下仿微信图片加载的那种策略了,先加载一张模糊的图片,然后再加载清晰大图,今天研究了一下,不过要是Glide支持进度条显示就好了,不得不说Glide很强大, 不啰嗦了,直接上代码了 ...

  4. android 余额宝收益列表,Android 仿支付宝中的余额宝收益进度条

    一. 看效果 二.上代码 package com.framework.widget; import android.app.Activity; import android.content.Conte ...

  5. android 余额宝,Android 仿支付宝中的余额宝收益进度条

    一. 看效果 二.上代码 package com.framework.widget; import android.app.activity; import android.content.conte ...

  6. android加载h5页面加进度条,使用Android仿微信加载H5页面的进度条

    这篇文章主要为大家详细介绍了Android仿微信加载H5页面进度条,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 前言 Android中WebView打卡前端页面时受到网路环境,页面内容大小的影响 ...

  7. Android 仿微信小程序开屏页加载loading

    Android 仿微信小程序开屏页加载loading 废话不多说,先上效果图~ 首先就是底层有一个灰色的圆,然后按照圆形的轨迹进行绘制. 啊~说那么多也没用,还是直接上代码吧,哈哈哈哈 绘制底部圆形及 ...

  8. Android仿抖音加载框之两颗小球转动控件

    Android仿抖音加载框之两颗小球转动控件 本篇文章已授权微信公众号 hongyangAndroid(鸿洋)独家发布. 效果图 安卓版抖音v2.5加载框: 本控件效果图: 使用方法 源码地址:And ...

  9. Android 仿微信录制短视频(不使用 FFmpeg)

    转载请标明出处与作者:https://blog.csdn.net/u011133887/article/details/83654724 项目中原本就有录制短视频的功能,使用的是 # qdrzwd/V ...

  10. Android 仿钉钉、微信 群聊组合头像

    CombineBitmap 项目地址:SheHuan/CombineBitmap 简介: Android 仿钉钉.微信 群聊组合头像 更多:作者   提 Bug 标签: 效果预览   功能 生成类似钉 ...

最新文章

  1. 情人节学写html5微信游戏
  2. 简要说明建设城市大脑三条关键标准规范
  3. 神经网络预测模型算法_MATLAB Elman神经网络的数据预测—电力负荷预测模型研究...
  4. python 类-9. 类 — Python 3.9.0 文档
  5. 今天感觉有点冷了其实。
  6. MySQL(MariaDB)之参数详解(-)
  7. CodeForces - 91B Queue(单调队列+二分)
  8. 最新web 2.0 配色 (一)
  9. Java垃圾收集器:G1GC何时将CMS强制退出?
  10. mysql主从复制原理详解_深入研究MySQL(三)、主从复制原理及演示
  11. Eclipse maven工程 Missing artifact com.sun:tools:jar:1.7.0:system 解决方法
  12. ABSynthe : 侧信道攻击加密函数窃取密钥
  13. 巧用批处理cmd快速切换IP地址
  14. python迅雷远程下载页面_迅雷远程下载
  15. Microsoft Word 教程:如何在 Word 中创建项目符号列表、显示字数统计?
  16. NLPCC-2019 依存句法分析领域移植评测技术分享(封闭情况下双第一)
  17. 一个大数据架构师应该掌握的技能
  18. JMeter对接口进行压力测试
  19. 在以TCP为连接方式的服务器中,为什么在服务端设计当中需要考虑心跳?
  20. 金字塔原理(麦肯锡)-要点汇总

热门文章

  1. 通过互联网搜索接口更新拼写语法库的设计
  2. matlab的lambda,matlab lambda 级数
  3. shell 字符串中是否包含任一字符串
  4. ubuntu 卸载python_如何在各种环境下正确安装python——Linux
  5. 开始php脚本,php bypass disable function
  6. heapsort(Java)(最小堆)
  7. OpenGL快速入门
  8. Apache 代理nodejs[未测试]
  9. 北航教授王田苗:中国机器人的发展机遇与挑战是什么?
  10. 使用PInvoke.NET插件为托管代码添加Win32 API签名