高仿IOS下拉刷新的粘虫效果
最近看需要做一款下拉刷新的效果,由于需要和Ios界面保持一致,所以这用安卓的方式实现了ios下的下拉刷新的粘虫效果。
最新的安卓手机版本的QQ也有这种类似的效果,就是拖动未读信息的那个红色圆圈,拖动近距离的是就有这种粘虫的效果。
下面是安卓版本的嘟嘟App的效果截图,后面会简单的介绍下的实现原理
原理:
如下图所示,在没有进行下拉的是,显示的是A图,实际上是一个圆形,当进行向下的拖动的时候,圆形会进行拉伸,这里简单用模拟下圆形被用力拉伸的效果。
1、被拉伸的圆形,实际上分为3部分,上面的部分(是个半圆,稍微大点,简称为大圆),中间部分(是一个拉伸的部分,有2条平滑的曲线),下面部分(也是一个半圆,较小,成为小圆)
2、当滑动的距离越来越大的时候,模拟的力就越大,那么圆就拉伸越厉害。这样我们可以把上面的大圆和下面的小圆变的越来越小。中间部分,变成的越来越长。
3、拖动过程理解,那么简述下绘制的流程,从1点开始绘制,1~2是一个四分之一的圆形,2~3是一个曲线,我们可以用贝塞尔曲线来绘制,具体贝塞尔是什么东西,可以自行百度,这里不做解释。3~4是一个半圆,4~5和2~3一样,也是一个贝塞尔曲线。5~1和1~2一样也是四分之一的圆形。
上面就是简单原理,可能实际效果还是需要优化的,不过原理再次,后面只需要慢慢优化即可,当初实现这个功能也是费了2天时间。
下面是代码片段,具体完整代码,后面会给出下载链接。
public class RefreshView extends View { static final int BEZIER_OFFSET = McDimenUtil.dp2Px(15);// 贝塞尔曲线的偏移值
static final int R = McDimenUtil.dp2Px(30); // 圆球的半径
static final int Y_OFFSET = McDimenUtil.dp2Px(60); // 竖直方向最大的偏移值 int currentX;
int currentY;
private boolean isReFreshed;
private int offsetY;
private OnPullRefreshCallback onPullRefreshCallback;
private Paint paint;
private Path path;
int startX;
int startY; public RefreshView(Context paramContext) {
super(paramContext);
init();
} public RefreshView(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext, paramAttributeSet);
init();
} public RefreshView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {
super(paramContext, paramAttributeSet, paramInt);
init();
} static void addBcr(Path paramPath, int x1, int y1, int x2, int y2, float rate) {
int i = (int) (rate * BEZIER_OFFSET);
int cx = (x2 + x1) / 2 - i; // 控制点xs
int cy = (y2 + y1) / 2 - i; // 控制点y
paramPath.quadTo(cx, cy, x2, y2);
} static void addBcr2(Path paramPath, int x1, int y1, int x2, int y2, float rate) {
int i = (int) (rate * BEZIER_OFFSET);
int cx = (x2 + x1) / 2 + i; // 控制点xs
int cy = (y2 + y1) / 2 - i; // 控制点y
paramPath.quadTo(cx, cy, x2, y2);
} public void draw(Canvas paramCanvas) {
super.draw(paramCanvas);
update(paramCanvas);
} void init() {
this.path = new Path();
this.paint = new Paint();
this.paint.setAntiAlias(true);
this.paint.setColor(Color.parseColor("#2baaff"));
} public boolean onTouchEvent(MotionEvent event) {
currentX = (int) event.getX();
currentY = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = currentX;
startY = currentY;
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移值,然后重新绘制
setOffsetY(currentY - startY);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// 重置界面
setOffsetY(0);
startX = startY = currentY = currentX = 0;
break;
}
return true; // super.onTouchEvent(event);
} public boolean isReFreshed() {
return this.isReFreshed;
} public void setOffsetY(int offset) {
this.offsetY = offset;
if (offsetY >= 0) {
invalidate();
}
} void update(Canvas paramCanvas) {
this.path.reset();
int width = getWidth();
int height = getHeight();
float rate = 1.0F * this.offsetY / height;
int r = (int) (R * (1.0F - rate)); // 圆球的半径,动态改变的,当拖拉的时候,r的会根据距离改变,进行变化 this.path.moveTo(width / 2, 0.0F);// 移动到(width/2 , 0)这个点 this.path.arcTo(new RectF(width / 2 - r, 0.0F, r + width / 2, r * 2), -90.0F, 90.0F);
// 根据半径r,换出一个四分之一的圆形 int m = (int) (9.0F * (rate * r));// 算出底部的校园与上面的大圆的圆心的距离
if ((m > Y_OFFSET) && (this.onPullRefreshCallback != null)) { // 如果这个距离超过了限制,则可以出发回调
this.onPullRefreshCallback.onCallback();
this.isReFreshed = true;
invalidate();
// return;
} this.isReFreshed = false;
int x2 = (int) (r + width / 2 - rate * r); // 小圆的水平的直径右边的点x坐标
int y = r + m; // 小圆的圆心坐标,y坐标
int x1 = (int) (width / 2 - r + rate * r);// 小圆的水平的直径左边的点x坐标
// 绘制一个贝塞尔曲线
addBcr(this.path, r + width / 2, r, x2, y, rate); int r2 = (x2 - x1) / 2; // 小圆的半径
// 绘制一个半圆
this.path.arcTo(new RectF(x1, y - r2, x2, y + r2), 0.0F, 180.0F); // 绘制一个贝塞尔曲线
addBcr2(this.path, x1, y, width / 2 - r, r, rate); // 在绘制上面的一个四分之一园
this.path.arcTo(new RectF(width / 2 - r, 0.0F, r + width / 2, r * 2), 180.0F, 90.0F); this.path.setFillType(Path.FillType.WINDING);
paramCanvas.drawPath(this.path, this.paint);
} public void setOnPullRefreshCallback(OnPullRefreshCallback callback) {
this.onPullRefreshCallback = callback;
} public static abstract interface OnPullRefreshCallback {
public abstract void onCallback();
}
}
运行效果:
完整代码下载地址:
http://download.csdn.net/detail/xia215266092/8107081
高仿IOS下拉刷新的粘虫效果的更多相关文章
- 仿IOS中下拉刷新的“雨滴”效果
在IOS中,有非常赞的"水滴"下拉效果.非常久之前也想在Android上实现,可是苦于能力有限,一直未能付诸行动.这几天趁着空隙时间.写了一版初步实现,基本达到了"水滴& ...
- 使用 CSS overscroll-behavior 控制滚动行为:自定义下拉刷新和溢出效果
CSS 的新属性 overscroll-behavior 允许开发者覆盖默认的浏览器滚动行为,一般用在滚动到顶部或者底部. 背景 滚动边界和滚动链接(boundary & chaining) ...
- iOS下拉刷新和上拉刷新
在iOS开发中,我们经常要用到下拉刷新和上拉刷新来加载新的数据,当前这也适合分页.iOS原生就带有该方法,下面就iOS自带的下拉刷新方法来简单操作. 上拉刷新 1.在TableView里,一打开软件, ...
- Android自定义控件之仿美团下拉刷新
美团的下拉刷新分为三个状态: 第一个状态为下拉刷新状态(pull to refresh),在这个状态下是一个绿色的椭圆随着下拉的距离动态改变其大小. 第二个部分为放开刷新状态(release to r ...
- iOS 下拉刷新-上拉加载原理
前言 讲下拉刷新及上拉加载之前先给大家解释UIScrollView的几个属性 contentSize是UIScrollView可以滚动的区域. contentOfinset 苹果官方文档的解释是&qu ...
- iOS 下拉刷新和加载更多 (OC\Swift)
Swift语言出来之后, 可能还没有第三方的下拉刷新和上提加载, 所以自己用UIRefreshControl控件和UITableView实例的tableFooterView(底部视图)属性结合起来写了 ...
- iOS 下拉刷新 上拉加载实现原理
1.下拉刷新 实现原理 if (scrollView.contentOffset.y < -100) { [UIView animateWithDuration:1.0 animations:^ ...
- 用vue写一个仿app下拉刷新的组件
如果你用vue弄移动端的页面,那么下拉刷新还是比较常见的场景,下面来研究如何写一个下拉刷新的组件(先上图); 由于节省大家的时间,样式就不贴出来了. html结构也不必介绍了,直接看代码吧-.- &l ...
- iOS:下拉刷新控件UIRefreshControl的详解
下拉刷新控件:UIRefreshControl 1.具体类信息: @interface UIRefreshControl : UIControl //继承控制类 - (instancetype)ini ...
随机推荐
- struts2乱码问题
简介:做了个功能,用的struts2,表单提交到后台,接收后打印出来的数据乱码. 解决步骤: 1. struts.xml中配置<constant name="struts.i18n ...
- jQuery nyroModal 插件遇到问题
nyroModal ver 1.6.2 弹出层插件 浏览更多 初始化大小问题 //页面加载完成后初始化 设置大小 $(function() { $.nyroModalSettings({ widt ...
- 一款非常好用的boostrap的验证插件、再也不用自己手写正则表达式和js了
基于jquery.bootstrap数据验证插件bootstrapValidator教程 bootstrap:能够增加兼容性的强大框架. 因为项目需要数据验证,看bootstrapValidator ...
- 2018.08.17 bzoj4653: [Noi2016]区间(线段树+尺取法)
传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于m的就移动左指针删除区间更新答案,否则移动右指针加入区间更新答案. 话说忘记排序以及建树的时 ...
- Django的路由层(2)
https://www.cnblogs.com/yuanchenqi/articles/8931472.html django2.0版的path Django默认支持以下5个转化器: str,匹配除了 ...
- C++之类和对象的使用(三)
对象数组 如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供.Student stud[3]={90,92,01};//合法 如果构造函数有多个参数,则不能用在定义时直接所提供所有 ...
- UML学习归纳整理
转载自:https://www.jianshu.com/p/83afa19c5096 写在前面 之前在学校比较系统的学习过统一建模语言UML,但长时间没使用遗忘了许多,最近因工作需要,所以对UML重新 ...
- SPSS-非参数检验—两独立样本检验 案例解析
今天跟大家研究和分享一下:spss非参数检验——两独立样本检验, 我还是引用教程里面的案例,以:一种产品有两种不同的工艺生产方法,那他们的使用寿命分别是否相同 下面进行假设:1:一种产品两种不同的工艺 ...
- 大文件webuploader的基本使用
webuploader的简单使用 需要的文件 自备 百度很多 webuploader.js uploader.swf jQuery <!DOCTYPE html> <htm ...
- OpenGL ES 光照模型之——漫反射光(RenderMonkey测试,地球日出效果)
概述及目录(版权所有,请勿转载 http://www.cnblogs.com/feng-sc) 本文在上一篇(OpenGL ES 光照模型之——环境光照(RenderMonkey测试))环境光基础上, ...