Windows风格的Loading动画Android实现(2)
来源:互联网 发布:分色软件 编辑:程序博客网 时间:2024/05/22 17:34
前言
众所周知,为了不ANR,不可以在UI线程上执行耗时的操作。所以为了效率,也为了通用,我把计算绘制参数的操作放到工作线程中去了。参考了这篇文章。
首先创建一个工作线程(workerThread),一个与workerThread关联的Handler(workerHandler),还有一个和UI线程关联的Handler(uiHandler)。在onDraw()
执行结束之后,会通过workerHander发消息,workerThread收到消息会去重新计算绘制参数。完成之后,会通过uiHandler发消息,UI线程收到消息之后调用invalidate()
,会导致onDraw()被执行。进入下一次循环。
这样就实现了,重新计算绘制参数在workerThread执行,invalidate()
在UI线程执行。在这里,handler充当信使的作用,它可以在其他线程向自己关联的线程发消息、post runnable等等。
HandlerThread知识
HandlerThread类的注释:
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
Handler类的注释
/*** A Handler allows you to send and process {@link Message} and Runnable* objects associated with a thread's {@link MessageQueue}. Each Handler* instance is associated with a single thread and that thread's message* queue. When you create a new Handler, it is bound to the thread /* message queue of the thread that is creating it -- from that point on,* it will deliver messages and runnables to that message queue and execute* them as they come out of the message queue.* * <p>There are two main uses for a Handler: (1) to schedule messages and* runnables to be executed as some point in the future; and (2) to enqueue* an action to be performed on a different thread than your own.......
源码
public class LoadingView extends View { /** * A list that contains the cx of each point. */ private List<Float> cx; /** * The cy of every point is the same. */ private float cy; /** * The radius of every point is the same. */ private float radius; /** * The paints that used to draw each point. */ private List<Paint> paints; /** * The length that point transfer to enter and exit. */ private float dx; private List<Float> dxs; /** * The offset between each point. */ private float offset; /** * Used in animation. */ private long startMillis = -1; /** * Used to make translation more smooth */ private Interpolator enterInterpolator, exitInterpolator; /** * The time one point enter or exit */ private long duration; /** * The moving velocity of the point which is not entering or exiting */ private float v = 0.04F; /** * The number of points */ private int pointNum; private float cxOffest; private Handler uiHandler; private HandlerThread workerThread; private Handler workerHandler; public LoadingView(Context context) { super(context); init(); } public LoadingView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ pointNum = 4; cx = new ArrayList<Float>(Collections.nCopies(pointNum, 0.0F)); Paint paint = new Paint(); paint.setDither(true); paint.setAntiAlias(true); paint.setColor(Color.parseColor("#00BCD4")); paint.setAlpha(0); paints = new ArrayList<Paint>(); for (int i = 0; i < pointNum; i++) { paints.add(new Paint(paint)); } enterInterpolator = new DecelerateInterpolator(1.5F); exitInterpolator = new AccelerateInterpolator(2.0F); duration = 600; uiHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { invalidate(); return true; } }); workerThread = new HandlerThread("workerThread"); workerThread.start(); workerHandler = new Handler(workerThread.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message message) { updateDrawParams(); uiHandler.sendEmptyMessage(0); return true; } }); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); initSize(); } private void initSize(){ cy = getMeasuredHeight() / 2; radius = getMeasuredHeight() / 3; dx = getMeasuredWidth() / 3; cxOffest = (getMeasuredWidth() - 2*dx - v*duration*3) * 0.5F; offset = radius * 3; } @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < cx.size(); i++) { canvas.drawCircle(cx.get(i), cy, radius, paints.get(i)); } workerHandler.sendEmptyMessage(0);//update draw params on worker thread } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); workerThread.quit(); } private void updateDrawParams(){ long currentMillis = System.currentTimeMillis(); if (startMillis == -1){ startMillis = currentMillis; } // (pointNum * 2 * duration) is a cycle long passMills = (currentMillis - startMillis) % (pointNum * 2 * duration); // updateDrawParams each point's cx and alpha for (int i = 0; i < cx.size(); i++) { long step = passMills / duration; float animationFraction = (passMills % duration) * 1.0F / duration; float enterX, transX, exitX; if (step < 4) { // entering half if (i < step) { enterX = dx - i*offset + i*duration*v; transX = (passMills - (i + 1) * duration) * v; exitX = 0; paints.get(i).setAlpha(255); } else if (i == step) { float interpolatedFraction = enterInterpolator.getInterpolation(animationFraction); enterX = interpolatedFraction*dx - i*offset + i*duration*v; transX = 0; exitX = 0; paints.get(i).setAlpha((int) (255*interpolatedFraction)); } else { enterX = 0; transX = 0; exitX =0; paints.get(i).setAlpha(0); } } else { // exiting half if (i < step-4){ enterX = dx - i*offset + i*duration*v; transX = (passMills - (i + 1) * duration) * v; exitX = dx; paints.get(i).setAlpha(0); } else if (i == step-4){ float interpolatedFraction = exitInterpolator.getInterpolation(animationFraction); enterX = dx - i*offset + i*duration*v; transX = (passMills - (i + 1) * duration) * v; exitX = interpolatedFraction * dx; paints.get(i).setAlpha((int) (255*(1-interpolatedFraction))); } else { enterX = dx - i*offset + i*duration*v; transX = (passMills - (i + 1) * duration) * v; exitX = 0; paints.get(i).setAlpha(255); } } cx.set(i, cxOffest + enterX + transX + exitX); } }}
0 0
- Windows风格的Loading动画Android实现(2)
- Windows风格的Loading动画Android实现(1)
- Windows风格的Loading动画Android实现(3)
- 实现仿windows正在加载loading动画
- Android 实现Windows风格的Dialog
- Android实现Windows风格的Dialog
- Android 自定义View 实现loading动画
- 一款Loading动画的实现思路(一)
- android动画介绍--Animation 实现loading动画效果
- android动画介绍--Animation实现loading动画效果
- android应用的loading加载动画制作
- 【Android】应用的loading加载动画制作
- android应用的loading加载动画制作
- 收集炫酷的Android Loading动画
- android打造独一无二的loading动画效果
- Android 好看的loading动画效果
- CSS3实现loading(加载)动画效果
- CSS3 实现 Loading 动画
- 您计算机上的一个策略阻止您连接到该打印机列队。请与您的系统管理员联系
- centos7+mysql+svn(https方式访问)通过外网访问的配置
- WSUS环境下客户端常用命令
- GPU上和CPU上执行函数时间比较
- 视频的每一帧转换成字符图
- Windows风格的Loading动画Android实现(2)
- Android之——AIDL深入
- java之从1到n整数中1出现的次数
- PAT (Advanced Level) 1052. Linked List Sorting (25) 结构体排序
- 通过WSUS3.0 SP2为客户端部署IE8
- ACM常见高精度总结(java用法)
- 经典的SQL语句,适合新手练习使用(一)
- html5 列表居中
- osmand探索--编译运行源码