uc首页下拉效果android,Android 自定义View UC下拉刷新效果(一)

(点击上方公众号,可快速关注)

来源:伯乐在线专栏作者 - joe

链接:http://android.jobbole.com/85135/

啦啦啦,今天给大家带来最近弄的CircleProgress相关的效果。这里的效果图可能还看不出是UC浏览器的那个下拉刷新的效果,不过首先还是要说说这个进度条,在下一篇中将实现真正的下拉刷新!

话不多说,直接上图:

0818b9ca8b590ca3270a3433284dd417.png

progress_静态.png

0818b9ca8b590ca3270a3433284dd417.png

progress_动态.gif

特点:就是一个进度条

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=newPaint(Paint.ANTI_ALIAS_FLAG);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setStrokeCap(Cap.ROUND);

mPaint.setStrokeWidth(mBorderWidth);

mPaint.setColor(mColors[mCurrentColorIndex]);

mHookPaint=newPaint(mPaint);

mArrowPaint=newPaint(mPaint);

三个动画

privatevoidsetupAnimations(){

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(newSimpleAnimatorListener(){

@Override

publicvoidonAnimationRepeat(Animatoranimation){

toggleAppearingMode();

}

});

fractionAnimator=ValueAnimator.ofInt(0,255);

fractionAnimator.setInterpolator(ANGLE_INTERPOLATOR);

fractionAnimator.setDuration(100);

fractionAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){

@Override

publicvoidonAnimationUpdate(ValueAnimatoranimation){

fraction=animation.getAnimatedFraction();

mHookPaint.setAlpha((Integer)animation.getAnimatedValue());

invalidate();

}

});

}

四个draw相关方法

privatevoiddrawError(Canvascanvas){

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);

}

privatevoiddrawHook(Canvascanvas){

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);

}

privatevoiddrawArc(Canvascanvas){

floatstartAngle=mCurrentGlobalAngle-mCurrentGlobalAngleOffset;

floatsweepAngle=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);

}

}

publicvoiddrawTriangle(Canvasc,floatstartAngle,floatsweepAngle){

if(mArrow==null){

mArrow=newPath();

mArrow.setFillType(Path.FillType.EVEN_ODD);

}else{

mArrow.reset();

}

floatx=(float)(mRingCenterRadius *Math.cos(0)+fBounds.centerX());

floaty=(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(newSimpleAnimatorListener(){

@Override

publicvoidonAnimationRepeat(Animatoranimation){

toggleAppearingMode();

}

});

privatevoidtoggleAppearingMode(){

mModeAppearing= !mModeAppearing;

if(mModeAppearing){

mCurrentColorIndex= ++mCurrentColorIndex%4;

mNextColorIndex= ++mNextColorIndex%4;

mCurrentGlobalAngleOffset=(mCurrentGlobalAngleOffset+MIN_SWEEP_ANGLE *2)%360;

}

}

最终效果图

0818b9ca8b590ca3270a3433284dd417.png

下一篇介绍剩余的下拉刷新部分,还有就是两个圆圈的过度效果。。

相关的代码请移步 我的github。。。

https://github.com/lovejjfg/Circle

joe:90后程序猿。。

0818b9ca8b590ca3270a3433284dd417.png

打赏支持作者写出更多好文章,谢谢!

关注「安卓开发精选」看更多精选安卓技术文章↓↓↓

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值