android+水滴粘性动画,Android控件实现水滴效果

看到ios版上QQ刷新效果像水滴,然后自己也想着去实现这样的效果,这篇文章暂时没有介绍下拉刷新的效果,只是单独用一个控件来实现这样的水滴效果。

效果图如下:

02242f8eaa20786556d5754df133229c.gif

一、总体思路

1、画两个圆形,其中一个就是上面的大圆,还有一个是下面的小圆,大圆和小圆不断变小,大圆的位置保持不变,小圆的位置不断向下移动,即圆心不断下移。

2、画两边的曲线,这时候用到贝塞尔曲线去画。

3、用属性动画实现动态的效果。

二、代码实现

1、找出画曲线的几个关键点。

8388c73cc6f5d222821d225942121f29.png

2e8c7a9fcea4c8c9a69cd9e76ff7115a.png

其实我是在第一张图的基础上,再在上面分别画两个圆,就可以得到第二张图了。关键是画出第一张图。

(1)在这里,p1,p2,p3,p4,这4个点分别对应两个圆的两边的点,即p1到p2就是圆的直径。p3和p4同理,那么就很容易确定这四个点的坐标了。

(2)然后c1和c2是分别控制p1到p3、p2到p4的曲线,是贝塞尔曲线的控制点。它们的横坐标对应的是p3,p4的横坐标(相等),纵坐标取两个圆心距离的一半。这样画出这个静态的图片就不难了。

(3)画上下两个圆进去,就会变成第二张图的效果。

2、在构造方法中调用init()初始化一些基本的变量

private void init(Context context, AttributeSet attrs) {

drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG

| Paint.FILTER_BITMAP_FLAG);

paint = new Paint();

paint.setColor(fillColor);

// 转换为像素单位

bigRadius = dip2px(context, bigRadius);

smallRadius = dip2px(context, smallRadius);

distance = dip2px(context, distance);

}

3、在onDraw()方法中画水滴效果

要注意的是path需要重新new, 贝塞尔曲线的绘制,用到是path.quadTo这方法。具体可以看代码。

@Override

protected void onDraw(Canvas canvas) {

// 必须重新new,不然路径会重复,我之前就是这样

path = new Path();

// 把画布移到中心

canvas.translate(width / 2, height / 2);

// 从canvas层面去除绘制时锯齿

canvas.setDrawFilter(drawFilter);

// 当前的两个圆心的距离

currentDis = distance * fraction;

// 计算当前大圆的半径

float bigRadius = this.bigRadius - currentDis / bigPercent;

float smallRadius = 0;

if (currentDis > 5) {// 距离大于5才改变小圆的半径

smallRadius = this.smallRadius - currentDis / smallPercent;

}

// 大圆两边的两个点坐标

leftX = -bigRadius;// 大圆当前的半径

leftY = rightY = 0;

rightX = bigRadius;// 大圆当前的半径

// 小圆两边的两个点坐标

leftX2 = -smallRadius;// 小圆当前的半径

leftY2 = rightY2 = currentDis;

rightX2 = -leftX2; // 小圆当前的半径

// 两个控制点

controlX1 = -smallRadius;// x坐标取小圆当前的半径大小

controlY1 = currentDis / 2;// y坐标取两个圆距离的一半

controlX2 = smallRadius;// x坐标取小圆当前的半径大小

controlY2 = currentDis / 2;// y坐标取两个圆距离的一半

path.moveTo(leftX, leftY);

path.lineTo(rightX, rightY);

// 用二阶贝塞尔曲线画右边的曲线,参数的第一个点是右边的一个控制点

path.quadTo(controlX2, controlY2, rightX2, rightY2);

path.lineTo(leftX2, leftY2);

// 用二阶贝塞尔曲线画左边边的曲线,参数的第一个点是左边的一个控制点

path.quadTo(controlX1, controlY1, leftX, leftY);

// 画大圆

canvas.drawCircle(0, 0, bigRadius, paint);

// 画小圆

canvas.drawCircle(0, currentDis, smallRadius, paint);

// 画path

canvas.drawPath(path, paint);

}

4、用属性动画,实现动态的效果。

/*** 执行属性动画,实现水滴的效果 */

public void perforAnim() {

ValueAnimator valAnimator = ObjectAnimator.ofFloat(0, 1);

valAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

fraction = (float) animation.getAnimatedValue();

postInvalidate();

}

});

valAnimator.setDuration(duration);

valAnimator.start();

}

5、重写onMeasure()方法,处理wrap_content情况。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

/*

* 处理为wrap_content情况,那么它的specMode是AT_MOST模式,在这种模式下它的宽/高

* 等于spectSize,这种情况下view的spectSize是parentSize,而parentSize是

* 父容器目前可以使用大小,就是父容器当前剩余的空间大小, 就相当于使用match_parent一样 的效果,因此我们可以设置一个默认的值

*/

int widthSpectMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSpectSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSpectMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSpectSize = MeasureSpec.getSize(heightMeasureSpec);

if (widthSpectMode == MeasureSpec.AT_MOST

&& heightSpectMode == MeasureSpec.AT_MOST) {

setMeasuredDimension(width, height);

} else if (widthSpectMode == MeasureSpec.AT_MOST) {

setMeasuredDimension(width, heightSpectSize);

} else if (heightSpectMode == MeasureSpec.AT_MOST) {

setMeasuredDimension(widthSpectSize, height);

}

}

6、其它的一些方法实现。

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

super.onLayout(changed, left, top, right, bottom);

if (changed) {

width = right - left;

height = bottom - top;

}

}

/**

* 根据手机的分辨率从 dp 的单位 转成为 px(像素)

*/

public int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

7、字段的定义

private final int fillColor = 0xff999999;// 填充颜色

private Paint paint;

private int width = 100, height = 300;// 默认宽高

/* 两个圆心的最大距离 /

private int distance = 60;

/* 当前两个圆心的距离 /

private float currentDis = 0;

private float bigRadius = 20;// 大圆半径

private float smallRadius = 10;// 小圆半径

private float controlX1, controlX2, controlY1, controlY2;// 两个控制点的坐标

private float leftX, leftY, rightX, rightY;// 大圆两边的两个点的坐标

private float leftX2, leftY2, rightX2, rightY2; // 小圆两边的两个坐标

DrawFilter drawFilter;

Path path;

/* 由属性动画控制,范围为0-1 */

float fraction = 0;// 比例值

/* 大圆半径变化的比例 /

private final int bigPercent = 8;

/* 小圆半径变化的比例 /

private final int smallPercent = 20;

// 动画的执行时间

private long duration = 3000;

三、总结

一种动画效果,应该先分析它的静态的实现,然后添加动态的效果,这样就比较容易实现它的动画效果了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 标题栏进度圈使用方法,Android 自定义标题栏 显示网页加载进度的方法实例...

这阵子在做Lephone的适配,测试组提交一个bug:标题栏的文字较长时没有显示完全,其实这并不能算个bug,并且这个问题在以前其他机器也没有出现,只是说在Lephone的这个平台上显示得不怎么美观,因为联想将原生的…

android7.0uri,整理: 解决Android7.0以上文件报FileUriExposedException问题

最近项目Android编译版本改为targetSdkVersion26, 之前隐藏的版本问题暴露出来, 尤其是文件第三方打开及Apk更新问题,这里记录下7.0以后文件相关问题问题描述:安装apk的代码一般写法如下,网上随处可以搜到:public static void installApk(Context context, File fil…

android+使用bmob冲突,bmob开发android遇到的问题

昨天尝试使用bmob,但是在使用文件对象时候遇到问题,但是他们的工作人员周末没上班,问题没解决,昨晚一晚没睡好,之后大清早的来求帮助了。源码如下:String path Environment.getExternalStorageDirectory()…

第一台鸿蒙手机是,第一台预装鸿蒙OS的手机终于登场。

原标题:第一台预装鸿蒙OS的手机终于登场。千呼万唤始出来,之前大家期待了很久的鸿蒙OS它终于真正到来了。据工业和信息化部公布的消息,搭载鸿蒙OS的新款华为手机正式入网了,这也将是华为第一台预装鸿蒙OS的新款手机。但令人完全没…

linux sed 正则转义,Linux运维云升笔记 (一)正则表达式以及文档编辑器sed

正则表达式概述使用单个字符来描述、匹配一系列符合某个语句规则的字符串,由普通字符与特殊字符组成,正则表达式广泛使用在脚本编程、文本编辑器中。正则表达式简写为regex、regexp、RE。再大多数语言当中正则表达式都被包括在两个正斜杠当中“/”正则表…

html 自动切换tab栏,html 实现tab切换的示例代码

tab切换在项目中也算是常用技术,一般实现tab切换都用js或者jq实现,今天介绍两种只用css实现tab切换方法:方法一:原理:通过label标签的关联属性和input的单选类型实现相应div的显示1.创建一个类名为wrap的div当作容器2.…

html匹配属性正则表达式,正则表达式匹配html标签的属性值

html">正则表达式是做文本解析工作必不可少的技能。如Web服务器日志分析,网页前端开发等。很多高级文本编辑器都支持正则表达式的一个子集,熟练掌握正则表达式,经常能够使你的一些工作事半功倍。例如统计代码行数,只需一个…

同一个html页面中两个area,HTML中的map和area标签

1. 标签介绍&#xff1a;(1)map标签&#xff1a; 该标签是指图片的映射&#xff0c;也就是说一张可以点击的图片的映射&#xff1b;属性介绍&#xff1a;<1> id: 中的 usemap 属性可引用 中的 id 或 name 属性(取决于浏览器)<2>name:同上说明&#xff1a;不同的浏览…

html 响应式布局 九宫格,两种方法实现响应式九宫格布局

html布局以及基础样式代码如下响应式九宫格html, body { color:#222; margin:0; padding: 0; text-decoration: none; }ul { list-style: none outside none; margin:0; padding: 0; }body { background-color:#eee; }ul li:nth-child(8n1) {background-color:#36A1DB}ul li:nt…

html跳转网页为什么网页无法访问,朋友的网站被网址跳转,导致官网无法正常访问...

原标题&#xff1a;朋友的网站被网址跳转&#xff0c;导致官网无法正常访问昨天中午接到客户的一个电话&#xff0c;告知其某个网站打开之后直接跳转到其他的网站。客户的这个网站&#xff0c;不是我们做的&#xff0c;但是关系一直保持的不错&#xff0c;所以就顺带给他解决一…

2021中卫一中高考成绩查询,2021年宁夏高中排名及分数线 高考本科升学率排行榜...

2019年宁夏高中排名及分数线 高考本科升学率排行榜如何判断一所高中学校的优劣好坏&#xff0c;人们往往从这几个方面来看&#xff1a;高考/竞赛成绩、生源质量、师资力量、软硬件设施、管理水平等。高考成绩因为最直接&#xff0c;最广为关注&#xff0c;但是很多时候未免有失…

微观经济学如何计算机会成本,【微观经济学】机会成本

概念&#xff1a;机会成本机会成本是指你做了某项选择&#xff0c;而不得不因此失去的其他利益。比如你选择了A&#xff0c;就必须放弃B&#xff0c;B就是A的机会成本。对企业来说&#xff0c;最优方案的机会成本&#xff0c;就是次优方案可能带来的收益。机会成本是听起来很简…

如何注释python中html,Python在HTML中提取带注释的代码,python,html,被

假设被注释代码段如下&#xff1a;html""""""如果直接对此代码段使用pyquery转换并提取from pyquery import PyQuery as pqresponse pq(html)("div.forum_content")print(response)会报错&#xff1a;lxml.etree.ParserError: Docume…

基于蓝墨云平台的计算机教学,基于蓝墨云班课的中职计算机“分层教学”模式探究...

崔月娇一、教学现状概述一方面&#xff0c;我校是面向全国招生&#xff0c;部分欠发达地区的学生由于资源配置导致计算机基础相当薄弱&#xff0c;而来自发达地区的学生早早地接触了计算机&#xff0c;部分计算机基础操作已相当熟练&#xff0c;学生的计算机水平参差不齐&#…

计算机专业和机电专业的区别,12届计算机专业和机电专业.doc

12届计算机专业和机电专业12届计算机1班、12届机电1、2、3、4班《计算应用基础》月考试题学号&#xff1a;_________ 姓名&#xff1a;_________ 班级&#xff1a;_____________考试说明&#xff1a;1、考试时间90分钟2、总分&#xff1a;100分3、应用的班级有12计算机1班、12届…

计算机基础知识上机操作excer,《计算机应用基础》Excel上机操作练习题.doc

《计算机应用基础》Excel上机操作练习题.doc《计算机应用基础》Excel上机操作练习题第1题 建立一工作簿&#xff0c;并作如下操作1&#xff0e; 在Sheet工作表中输入如下内容&#xff1a;在A1单元格中输入&#xff1a;中华人民共和国以数字字符的形式在B1单元格…

angularjs html 缓存,如何删除使用AngularJS的HTML中的浏览器缓存?

如何删除HTML浏览器的缓存&#xff0c;它使用AngularJS&#xff1f;我在我的index.html中使用了以下内容。我也尝试在我的app.js中使用$templateCache&#xff0c;但没用。如何删除使用AngularJS的HTML中的浏览器缓存&#xff1f;app.config([$routeProvider, function($routeP…

dede列表页if判断输出html,首页、列表页调用文章body内容的两种方法

随着源码的开放性&#xff0c;很多SEOER对页面的要求也越来越复杂多样性&#xff0c;很多时候&#xff0c;织梦系统的原有功能并不能满足seoer的页面布置要求&#xff0c;这就需要继续开发页面&#xff0c;做更多的功能调用。今天徐金华SEO给大家讲的是关于首页、列表页调用文章…

计算机如何驱动无线网络,win7如何安装无线网卡驱动 安装无线网卡驱动的方法...

今天告诉大家win7安装无线网卡驱动&#xff1f;无线网卡就是既能接受无线信号&#xff0c;又能发射无线信号的网络设备&#xff0c;但无线网卡就需要安装无线网卡驱动。许多新手用户不懂安装步骤&#xff0c;其实安装方法简单&#xff0c;接下来给大家说明一下win7安装无线网卡…

闽江师范专科高等学校计算机专业在哪个校区,闽江师范高等专科学校有几个校区(官网发布数据)...

闽江师范高等专科学校有几个校区一直都是大家关注的问题之一&#xff0c;根据闽江师范高等专科学校官方网站的学校简介&#xff0c;我们将闽江师范高等专科学校一共有多少个校区的资料缓存到本页&#xff0c;给需要了解的同学参考&#xff0c;最新校区新增&#xff0c;校区合并…