高仿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 ...
随机推荐
- "UX"将会是下一个Buzzword?
“用户体验非常重要”.“没有用户体验就没有产品”.“UX就是一切”.不知道从何时开始,用户体验(UX) 这个名词已经变得如此多见了,但是人们真正的认识.认清了什么是用户体验了吗?设计师们常挂在嘴边的用 ...
- stl学习记录(1)
Effective STL 中文版学习记录 条款4 判断容器是否为空 使用empty而不是size().size()操作在实现上不是一个时间常数操作条款5 尽量使用区间成员函数代替它们的单元素兄弟.S ...
- PTA第五次作业
#include<stdio.h> #include<math.h> int main () { int n,m,i,j,a; scanf("%d",&am ...
- 实现KbmMw web server 支持https
在以前的文章里面介绍过kbmmw 做web server. 前几天红鱼儿非要我给他做一个支持https 的web server. 其实kbmmw 支持https 有好几种方法: 1. 使用isapi ...
- 二进制搭建kubernetes多master集群【三、配置k8s master及高可用】
前面两篇文章已经配置好了etcd和flannel的网络,现在开始配置k8s master集群. etcd集群配置参考:二进制搭建kubernetes多master集群[一.使用TLS证书搭建etcd集 ...
- 2018.09.15 hdu1599find the mincost route(floyd求最小环)
传送门 floyd求最小环的板子题目. 就是枚举两个相邻的点求最小环就行了. 代码: #include<bits/stdc++.h> #define inf 0x3f3f3f3f3f3f ...
- 2018.07.07 BZOJ2212: Poi2011Tree Rotations(线段树合并)
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MB Description Byteasar the garde ...
- git将本地仓库强制替换掉远程仓库
$ git remote add origin <url> $ git push --force --set-upstream origin master
- iOS平台设置系统状态栏(通知栏、顶部状态栏)样式背景颜色或透明
5+App开发 状态栏 配置系统状态栏样式 iOS平台可支持对系统状态栏样式的配置,在应用manifest.json文件的plus->distribute->apple下添加UIStatu ...
- Java 连接 Memcached 服务
原文:http://www.runoob.com/memcached/java-memcached.html mac下安装和配置Memcached:http://www.pchou.info/open ...