Android 自定义View UC下拉刷新效果(一)
来源:互联网 发布:umts是什么网络类型 编辑:程序博客网 时间:2024/05/16 04:02
啦啦啦,今天给大家带来最近弄的CircleProgress
相关的效果。这里的效果图可能还看不出是UC浏览器的那个下拉刷新的效果,不过首先还是要说说这个进度条,在下一篇中将实现真正的下拉刷新!
话不多说,直接上图:
特点:就是一个进度条
1、可以设置多种颜色。
2、可以显示多种状态(LOADING、SUCCESS、ERROR,其实远不止这几种)
3、可以控制是否显示箭头
相关准备工作
知识点:
1.Canvas
里面相关方法
2.drawArc()
画圆弧的方法
3.drawPath()
画路径的方法
4.属性动画使用
结果的钩钩或者那个叉叉还有那个箭头都是使用drawPath()
来完成的。
在onDraw里面对应有四个相关的方法:
1.drawArc(Canvas canvas)
:画对应的进度
2.drawTriangle(Canvas c, float startAngle, float sweepAngle)
:画箭头
3.drawHook(Canvas canvas)
:画钩钩
4.drawError(Canvas canvas)
:画叉叉
三个动画控制:
两个来控制进度条的 startAngle
和sweepAngle
,一个用来控制画钩钩或者画叉叉的时候的渐变效果!
相关代码
三支画笔
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeCap(Cap.ROUND); mPaint.setStrokeWidth(mBorderWidth); mPaint.setColor(mColors[mCurrentColorIndex]); mHookPaint = new Paint(mPaint); mArrowPaint = new Paint(mPaint);
三个动画
private void setupAnimations() { mObjectAnimatorAngle = ObjectAnimator.ofFloat(this, mAngleProperty, 360f); mObjectAnimatorAngle.setInterpolator(ANGLE_INTERPOLATOR); mObjectAnimatorAngle.setDuration(ANGLE_ANIMATOR_DURATION); mObjectAnimatorAngle.setRepeatMode(ValueAnimator.RESTART); mObjectAnimatorAngle.setRepeatCount(ValueAnimator.INFINITE); mObjectAnimatorSweep = ObjectAnimator.ofFloat(this, mSweepProperty, 360f - MIN_SWEEP_ANGLE * 2); mObjectAnimatorSweep.setInterpolator(SWEEP_INTERPOLATOR); mObjectAnimatorSweep.setDuration(SWEEP_ANIMATOR_DURATION); mObjectAnimatorSweep.setRepeatMode(ValueAnimator.RESTART); mObjectAnimatorSweep.setRepeatCount(ValueAnimator.INFINITE); mObjectAnimatorSweep.addListener(new SimpleAnimatorListener() { @Override public void onAnimationRepeat(Animator animation) { toggleAppearingMode(); } }); fractionAnimator = ValueAnimator.ofInt(0, 255); fractionAnimator.setInterpolator(ANGLE_INTERPOLATOR); fractionAnimator.setDuration(100); fractionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { fraction = animation.getAnimatedFraction(); mHookPaint.setAlpha((Integer) animation.getAnimatedValue()); invalidate(); } });}
四个draw相关方法
private void drawError(Canvas canvas) { mError.reset(); mError.moveTo(fBounds.centerX() + fBounds.width() * 0.2f * fraction, fBounds.centerY() - fBounds.height() * 0.2f * fraction); mError.lineTo(fBounds.centerX() - fBounds.width() * 0.2f * fraction, fBounds.centerY() + fBounds.height() * 0.2f * fraction); mError.moveTo(fBounds.centerX() - fBounds.width() * 0.2f * fraction, fBounds.centerY() - fBounds.height() * 0.2f * fraction); mError.lineTo(fBounds.centerX() + fBounds.width() * 0.2f * fraction, fBounds.centerY() + fBounds.height() * 0.2f * fraction); mHookPaint.setColor(mColors[3]); canvas.drawPath(mError, mHookPaint); canvas.drawArc(fBounds, 0, 360, false, mHookPaint);}private void drawHook(Canvas canvas) { mHook.reset(); mHook.moveTo(fBounds.centerX() - fBounds.width() * 0.25f * fraction, fBounds.centerY()); mHook.lineTo(fBounds.centerX() - fBounds.width() * 0.1f * fraction, fBounds.centerY() + fBounds.height() * 0.18f * fraction); mHook.lineTo(fBounds.centerX() + fBounds.width() * 0.25f * fraction, fBounds.centerY() - fBounds.height() * 0.20f * fraction); mHookPaint.setColor(mColors[0]); canvas.drawPath(mHook, mHookPaint); canvas.drawArc(fBounds, 0, 360, false, mHookPaint);}private void drawArc(Canvas canvas) { float startAngle = mCurrentGlobalAngle - mCurrentGlobalAngleOffset; float sweepAngle = mCurrentSweepAngle; if (mModeAppearing) { mPaint.setColor(gradient(mColors[mCurrentColorIndex], mColors[mNextColorIndex], mCurrentSweepAngle / (360 - MIN_SWEEP_ANGLE * 2))); sweepAngle += MIN_SWEEP_ANGLE; } else { startAngle = startAngle + sweepAngle; sweepAngle = 360 - sweepAngle - MIN_SWEEP_ANGLE; } canvas.drawArc(fBounds, startAngle, sweepAngle, false, mPaint); if (showArrow) { drawTriangle(canvas, startAngle, sweepAngle); }}public void drawTriangle(Canvas c, float startAngle, float sweepAngle) { if (mArrow == null) { mArrow = new Path(); mArrow.setFillType(Path.FillType.EVEN_ODD); } else { mArrow.reset(); } float x = (float) (mRingCenterRadius * Math.cos(0) + fBounds.centerX()); float y = (float) (mRingCenterRadius * Math.sin(0) + fBounds.centerY()); mArrow.moveTo(0, 0); mArrow.lineTo(ARROW_WIDTH * mArrowScale, 0); mArrow.lineTo((ARROW_WIDTH * mArrowScale / 2), (ARROW_HEIGHT * mArrowScale)); mArrow.offset(x, y); mArrow.close(); c.rotate(startAngle + sweepAngle, fBounds.centerX(), fBounds.centerY()); c.drawPath(mArrow, mPaint);}
上面的代码就是相关核心的方法了,其实对应的进度条效果就是控制 startAngle
和sweepAngle
这两个对应的字段,然后不断的调用drawArc()
方法。
对于画钩钩或者画叉叉,就是一个ValueAnimator
,通过百分比控制缩放和画笔的透明度。
对于drawTriangle()
方法,如果你觉得很眼熟的话也很正常,其实这个就是在SwipeRefreshLayout
里面抄过来的。。。。。
一开始,我很纠结这个箭头怎么才能跟着进度条一起旋转,自己写的也是有各种问题,另外mArrowScale
这个参数在里面其实没有使用的。
如果没有offset偏移量,那么那个path肯定是画在左上角的。
x=mRingCenterRadius +fBounds.centerX();y=fBounds.centerY();
通过这个一设置,这个path其实就到了右边的中间靠着圆弧的内侧一点去了(因为这里的半径减去了圆弧自己的宽度。。),这么一来,再根据相关的角度旋转角度,就有一种跟着进度条一直转的效果了!
对于drawArc()
方法,主要是控制startAngle
和sweepAngle
这两个变量,mCurrentGlobalAngle
的变化范围是(0~360),而mCurrentSweepAngle
的变化范围是(0~360f - MIN_SWEEP_ANGLE * 2),为什么要减去两个最小值呢?因为sweepAngle
总会加一个或者总会减去一个最小值,所以最小间距还是MIN_SWEEP_ANGLE
。
至于什么时候加什么时候减呢?这里有一个变量值mModeAppearing
提供记录!那就是当mObjectAnimatorSweep
的动画重复的时候,就需要切换一下了。。
mObjectAnimatorSweep.addListener(new SimpleAnimatorListener() { @Override public void onAnimationRepeat(Animator animation) { toggleAppearingMode(); } });private void toggleAppearingMode() { mModeAppearing = !mModeAppearing; if (mModeAppearing) { mCurrentColorIndex = ++mCurrentColorIndex % 4; mNextColorIndex = ++mNextColorIndex % 4; mCurrentGlobalAngleOffset = (mCurrentGlobalAngleOffset + MIN_SWEEP_ANGLE * 2) % 360; }}
最终效果图
下一篇Android 自定义View UC下拉刷新效果(二)
介绍剩余的下拉刷新部分,还有就是两个圆圈的过度效果。。
相关的代码请移步 我的github。。。
— Edit By Joe —
- Android 自定义View UC下拉刷新效果(一)
- Android 自定义View UC下拉刷新效果(二)
- Android View 下拉刷新之头部效果自定义 [水]
- 自定义View之粘性下拉刷新效果
- Android自定义View(一)---ListView 下拉刷新
- Android自定义View-下拉刷新控件
- Android自定义View实现下拉刷新控件
- android 自定义下拉刷新动画效果
- android 自定义listview实现下拉刷新(一)
- Android自定义View之(下拉刷新+侧滑删除)
- Android自定义下拉刷新
- Android 自定义下拉刷新
- Android - 自定义下拉刷新
- Android自定义ListView实现下拉刷新,效果仿SwipeRefreshLayout
- 自定义下拉刷新控件-仿美团刷新效果
- 新手自定义控件,创建属于自己的下拉刷新(一)---Android,ListView实现IOS的弹性效果
- SwipeRefreshLayout源码分析+自定义UC头条下拉刷新Demo
- Android下拉刷新效果实现
- HashMap的实现原理
- Android5.0录屏方案
- 【VBA研究】版本无关的取EXCEL有效行列数方法
- ztree树中的id,pid
- 域名那些事
- Android 自定义View UC下拉刷新效果(一)
- Android绘图进阶之Path详解
- 【leetcode Database】185. Department Top Three Salaries
- 求二叉树的深度
- 用基于信息熵的topsis方法实现学生成绩的综合排名
- 【华为 OJ 】字符串加密
- java synchronized关键字
- unity 滚动视图的优化
- 新手上路 layer弹层组件 (www.layui.com)