本文同步自博主的个人博客wing的地方酒馆

很久很久以前,撸了一款loadingview(点击这里回顾),当时觉得还不错,现在看看觉得好丑啊!!! 于是想再撸一个,无意间在这里看到一个很不错的效果,于是手痒了,就想动动手,算起来,也有很久没有写过View了。

效果图

哈,可能又是我自我感觉良好,觉得效果还不错,不过没准再过半年我又嫌弃之前的自己了 哈哈哈。

还有呢,如果你看这篇比较吃力,推荐先去看看我之前学view的时候写的一些博客,难度是一点一点增加的。

简单说说自定义view的学习方式

实现思路

看到效果,首先要分析,这里主要是什么组成的。

首先呐,肯定要画两个圆圈,对吧? 不要告诉我你不会画圆。如果不会,请看上面的链接。

private void drawCircle(Canvas canvas, float present) {
canvas.drawCircle(mWidth / 2, mHeight / 2 -mMaxOffset, mMaxRadius, mPaint);
canvas.drawCircle(mWidth / 2, mHeight / 2 + mMaxOffset, mMaxRadius, mPaint);
}

然后想办法让圈圈转起来,怎么转起来呢,肯定是rotate方法了~~这里提供一个角度参数,让他自增,如果到360呢,就让他等于0,然后invalidate(),就可以实现圈圈转动的效果。


canvas.rotate(mDegrees += 3, mWidth / 2, mHeight / 2);
if (mDegrees == 360) {
mDegrees = 0;
}
invalidate();



恩。。已经转起来了。

接下来要想办法让两个小圆在转圈的过程中靠近,再远离,怎么实现呢?注意上面让小圆有间隔的mMaxOffset!我们可以根据旋转的百分比来动态改变这个offset!

所以,要改一下drawCircle()代码

float present = mDegrees / 360;
if (present < 0.5) {
mOffset = mMaxOffset * present;
} else {
mOffset = mMaxOffset * (1 - present);
} private void drawCircle(Canvas canvas) { canvas.drawCircle(mWidth / 2, mHeight / 2 - mOffset, mMaxRadius, mPaint);
canvas.drawCircle(mWidth / 2, mHeight / 2 + mOffset, mMaxRadius, mPaint);
}

现在是这样,恩..已经有点效果了。

那小圈靠近的时候,粘合动画怎么做?还记得qq消息点去除吗?跟那个道理一样!!! 就是画一个贝塞尔的path。坐标计算思路在模仿qq消息去除效果 这里思路是一样的,只不过微调了辅助点坐标。直接上代码:

 if (present <= 0.37 || present >= 0.63) drawPath(canvas, present);

 private void drawPath(Canvas canvas, float present) {
mPath.reset();
mPath.moveTo(mWidth / 2 - mMaxRadius, mHeight / 2 - mOffset);
mPath.lineTo(mWidth / 2 + mMaxRadius, mHeight / 2 - mOffset); float supportOffset = -30; if (present < 0.25) { //两个球相交
supportOffset = 30;
} else if (present >= 0.25 && present < 0.375f) {
Log.e("present", present + "");
supportOffset = -(480 * present - 150f);
} else if (present > 0.625) { //开始缩小 supportOffset = (480 * present - 330f);
if (present > 0.75) { //两个球开始相交
supportOffset = 30;
}
//supportOffset = 30;
} Log.e("wing", supportOffset + ""); mPath.quadTo(mWidth / 2 + supportOffset, mHeight / 2, mWidth / 2 + mMaxRadius,
mHeight / 2 + mOffset);
mPath.lineTo(mWidth / 2 - mMaxRadius, mHeight / 2 + mOffset);
mPath.quadTo(mWidth / 2 - supportOffset, mHeight / 2, mWidth / 2 - mMaxRadius,
mHeight / 2 - mOffset);
mPath.close();
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mPath, mPaint);
}

有一点值得注意的是,辅助点偏移坐标和percent的关系。以 supportOffset = -(480 * present - 150f);作为说明。这个方程式怎么得出出来的呢。 因为我想让百分比从0.25->0.375变化,而辅助点坐标从-30->30变化,所以是一个简单的初中数学中的线性方程。将k和b带入 y = kx +b 即可轻易得出。

之后在根据percent控制path的显隐,即可实现最上效果图的效果。

如果你感兴趣,可以下载源码研究下~~当然,如果觉得赞,点个star是对我最大的支持~

https://github.com/githubwing/LoadingView

(Android自定义View)来来来,一起再撸一个Material风格loadingView。的更多相关文章

  1. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  2. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  3. Android 自定义 view(三)—— onDraw 方法理解

    前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...

  4. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  5. Android自定义View

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

  6. Android自定义View之ProgressBar出场记

    关于自定义View,我们前面已经有三篇文章在介绍了,如果筒子们还没阅读,建议先看一下,分别是android自定义View之钟表诞生记.android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检 ...

  7. android自定义View之NotePad出鞘记

    现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...

  8. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  9. Android自定义View(CustomCalendar-定制日历控件)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/54020386 本文出自:[openXu的博客] 目录: 1分析 2自定义属性 3onMeas ...

随机推荐

  1. 注意类型转换——Effective C++

    注意类型转换: C++提供了四种新式类型转换: const_cast<T>(expression); static_cast<T>(expression); dynamic_c ...

  2. ●BZOJ 3998 [TJOI2015]弦论

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3998题解: 后缀自动机. 当T=0时, 由于在后缀自动机上沿着trans转移,每个串都是互不 ...

  3. WISCO信息组NOIP模拟赛-部落冲突

    传送门 首先肯定考虑树剖,这里没有要求区间加,所以可以用树状数组维护,不会卡常的 这里是边权,可以转化为点权:让每条边连接的较深的节点的点权等于边权即可,然后计算的时候减去lca #include&l ...

  4. VK Cup 2017 - Round 1

    和FallDream组队瞎打一通--B两个人写的都挂了233,最后只剩下FallDream写的A和我写的C,最后我yy了个E靠谱做法结果打挂了,结束之后改了改就A了,难受. AC:AC Rank:18 ...

  5. hdu 5437Alisha’s Party(优先队列)

    题意:邀请k个朋友,每个朋友带有礼物价值不一,m次开门,每次开门让一定人数p(如果门外人数少于p,全都进去)进来,当所有人到时会再开一次,每次都是礼物价值高的人先进. /*小伙伴最开始gg了,结果发现 ...

  6. PHP中利用DOM创建xml文档

    DOM创建xml文档 用dom创建如下文档: <booklist> <book id="1"> <title>天龙八部</title> ...

  7. eclipse中安装freemarker插件及ftl使用freemarker编辑器

    http://www.07net01.com/2015/08/895212.html eclipse中安装freemarker插件及ftl使用freemarker编辑器 在线安装的方法是:Help – ...

  8. 解决 APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tas

    报错信息:APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! 在网上查了一下,大部分网友分析是c ...

  9. openlayers3设置zoom不变

    设置maxZoom和minZoom一致,并去掉resolutions

  10. Linux平台安装MongoDB

    MongoDB 提供了 linux 各发行版本 64 位的安装包,你可以在官网下载安装包. 下载地址:https://www.mongodb.com/download-center#community ...