高仿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 ...
随机推荐
- 2018.10.15 bzoj4445: [Scoi2015]小凸想跑步(半平面交)
传送门 话说去年的省选计算几何难度跟前几年比起来根本不能做啊(虽然去年考的时候并没有学过计算几何) 这题就是推个式子然后上半平面交就做完了. 什么? 怎么推式子? 先把题目的概率转换成求出可行区域. ...
- Django介绍(3)
https://www.cnblogs.com/yuanchenqi/articles/5786089.html
- Java生成HTML文件
实例HTML文件<html> <head> <title>###title###</title> <meta http-equiv="C ...
- csdn获得积分
常规方式获取可用分 1.每天只要回复就可以获得10个可用分.注:回复后的第2天发放. 2.每周回复量大于10个帖子,将获得30可用分.注:下一周的周二发放. 3.本周获得技术专家分30分以上,将获得4 ...
- Hive 1.2.1&Spark&Sqoop安装指南
目录 目录 1 1. 前言 1 2. 约定 2 3. 服务端口 2 4. 安装MySQL 2 4.1. 安装MySQL 2 4.2. 创建Hive元数据库 4 5. 安装步骤 5 5.1. 下载Hiv ...
- Activity生命流程
做Android的同学说起 Activity,那绝对是熟悉的不能再熟悉了,但是越熟悉的东西往往越陌生.我们真的了解她吗?她是我们所认识的那样吗?或许是,或许不是!了解与否, 让我们往下看.首先借And ...
- hdu 2190 悼念512汶川大地震遇难同胞——重建希望小学
题目 这道题拿到的时候拼凑了一会,感觉挺难的,然后博客说是:递推,我觉得递推其实就是找规律. 这是别人的思路:对于n米的长度,可以是由n-1长度加1而来,对于增加的1,只有三块1*1的砖一种铺法: 还 ...
- node 命令行
问题起源于,想用node执行命令行的命令. 结论如下:两种情况 1.node本身的命令(node app.js):使用child_process模块的四个方法 2.命令行的命令(包括1,还有java) ...
- java web开发过程中的“\”指的是什么,如何区分
- java poi 获取单元格值时间
完整帮助类:JAVA poi 帮助类 /* * poi特殊日期格式:数字格式化成-yyyy年MM月dd日,格式 * */ private static ArrayList<String> ...