1.绘制圆圈遮罩
这里我们是用了混合模式来实现圆圈部分的扣除,这里我们用到了PorterDuff.Mode.CLEAR
/**
* 绘制圆圈遮罩
* @param canvas
*/
private void drawCircleMask(Canvas canvas) {
canvas.save();
//目标图Dst
canvas.drawRect(new Rect(0,0,getWidth(),getHeight()), mPaint);
//设置混合模式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//源图Src,重叠区域右下角部分
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 3, mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restore();
}
这时效果如下
2.绘制两个动画效果的圆圈
咱们绘制的两个图片如下
我们要做的就是通过计算将Bitmap缩放成与之前遮罩效果的圆圈一样大,因为我们这里用的两张图片是一样大的,因此我们只需要计算出内圆圈图片与遮罩圆圈的缩放比例即可,由于之前咱们给遮罩圆圈设置的半径为:控件宽度 / 3
因此我们缩放后的圆圈Bitmap宽高应当是如下图所示的中间红线部分加两边蓝色部分的总长
其中中间红线部分就是:控件宽度 / 3
,而蓝线部分可以通过PhotoShop
等工具测量,然后根据与红线部分的比例求出,代码如下,其中mInnerCircleBitmap
是内圆,mOutCircleBitmap
是外圆
/**
* 画圆圈外部的圆圈图片
*/
private void drawBitmapCircle(Canvas canvas) {
if(mInnerCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mInnerCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_innercircle);
mInnerCircleBitmap = Bitmap.createScaledBitmap(mInnerCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
if(mOutCircleBitmap == null){
int dstWidthAndHeight = (int) (getWidth() / 1.5f + getWidth() / 1.5f / 4);
mOutCircleBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_checkface_outcircle);
mOutCircleBitmap = Bitmap.createScaledBitmap(mOutCircleBitmap,dstWidthAndHeight,dstWidthAndHeight,true);
}
int left = (getWidth() - mInnerCircleBitmap.getWidth()) / 2;
int top = (int) (getWidth() / 2 - getWidth() / 3 - getWidth() / 1.5f / 8);
canvas.drawBitmap(mInnerCircleBitmap,left,top,mPaint);
canvas.drawBitmap(mOutCircleBitmap,left,top,mPaint);
}
这时效果如下
3.实现旋转动画效果
接下来我们就可以通过ValueAnimator
来实现圆圈的旋转效果了,从文章开头的效果我们可以看出两个圆圈的旋转方向是不一样的,因此我们逻辑上也要注意一个是顺时针旋转另一个是逆时针旋转,代码如下
private float mDegress = 0;//旋转角度
private void init() {
//定义动画
valueAnimator = ValueAnimator.ofFloat(0f, 360f);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(6000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mDegress = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
/**
* 画圆圈外部的圆圈图片
*/
private void drawBitmapCircle(Canvas canvas) {
if(mInnerCircleBitmap == null){
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
lin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
[外链图片转存中…(img-Iege9kao-1713803812304)]
[外链图片转存中…(img-kUMwP3yB-1713803812305)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!