Android ReboundScrollView仿IOS拖拽回弹效果

初衷:

其实github上有很多这种ScrollView的项目,但是不得不说功能太多太乱了,我就只是想要一个简单效果的ScrollView,另外监听下滑动距离而已,想想还是自己写了个。

这里先说下思路吧,如果不愿意看的朋友可以直接跳过这一步,看下面的代码:

Android 原生的ScrollView是不支持拉出屏幕外,并且也没有回弹效果的,用户友好度却不不太好,不知道为什么不那么设计。
我想做的事情正如上面所述:

1.希望能拉出屏幕外
2.松手后希望控件回弹

我的思路是对ScrollView的子View进行操作

所有View的滑动控制肯定都受着onTouchEvent控制,所以,理所应当的,我要关注的重点,也就是onTouchEvent这个方法。

回弹的效果,就牵涉到位置的计算,这里我的想法就用简单的TranslateAnimation来实现。

大体思路就是这样了,先把思路确定了,然后代码总是磨出来的。

贴代码:

import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.TranslateAnimation; import android.widget.ScrollView; public class ReboundScrollView extends ScrollView { private static final float MOVE_DELAY = 0.3f;//当拉出屏幕时的拖拽系数 private static final int ANIM_TIME = 300;//回弹耗时 private static final int FLING = 2;//fling 系数 private View childView; private boolean havaMoved; private Rect originalRect = new Rect(); private float startY; @Override protected void onFinishInflate() { super.onFinishInflate(); if (getChildCount() > 0) { childView = getChildAt(0); } } @Override public void fling(int velocityY) { super.fling(velocityY / 2); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (childView == null) return; originalRect.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom()); } public ReboundScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public ReboundScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ReboundScrollView(Context context) { super(context); } /** * 在触摸事件中, 处理上拉和下拉的逻辑 */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (childView == null) { return super.dispatchTouchEvent(ev); } int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: startY = ev.getY(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (!havaMoved) break; TranslateAnimation anim = new TranslateAnimation(0, 0, childView.getTop(), originalRect.top); anim.setDuration(ANIM_TIME); childView.startAnimation(anim); // 将标志位设回false havaMoved = false; resetViewLayout(); break; case MotionEvent.ACTION_MOVE: float nowY = ev.getY(); int deltaY = (int) (nowY - startY); int offset = (int) (deltaY * MOVE_DELAY); childView.layout(originalRect.left, originalRect.top + offset, originalRect.right, originalRect.bottom + offset); havaMoved = true; break; default: break; } return super.dispatchTouchEvent(ev); } public void resetViewLayout() { childView.layout(originalRect.left, originalRect.top, originalRect.right, originalRect.bottom); } }

把代码贴出来后,再来分析具体的实现:
首先是拉出屏幕,在MOVE的过程中,对于超出部分代码,我使用layout重置子View的位置。

第二个要实现的就是回弹了,拖出去总是要回来的:
这里我定义了一个Rect,在onLayout(boolean changed, int l, int t, int r, int b)方法中,记录下了ScrollView的初始位置,以便于重置回弹。

说了许多,看一下代码里的关键代码
MOVE的代码:

float nowY = ev.getY(); int deltaY = (int) (nowY - startY); int offset = (int) (deltaY * MOVE_DELAY); childView.layout(originalRect.left, originalRect.top + offset, originalRect.right, originalRect.bottom + offset); havaMoved = true;

这是MotionEvent.ACTION_MOVE的时候要做的,对chlidView的位置重新设置也就是lauout方法,这是基于originalRect的值来的,设定了相应的滑动系数,不然感觉实在是太灵敏了。

回弹的代码:

if (!havaMoved) break; TranslateAnimation anim = new TranslateAnimation(0, 0, childView.getTop(), originalRect.top); anim.setDuration(ANIM_TIME); childView.startAnimation(anim); // 将标志位设回false havaMoved = false; resetViewLayout(); ... ... public void resetViewLayout() { childView.layout(originalRect.left, originalRect.top, originalRect.right, originalRect.bottom); }

当手指 MotionEvent.ACTION_UP或者MotionEvent.ACTION_CANCEL的时候把clildView置于原位,然后设置动画,这就是回弹了。

补充:

这是个非常简单的回弹ScrollView,需要注意的是,我这里没有对在屏幕内正常移动和屏幕外移动作区分,那样就需要判断当前的移动是否需要我们重写了,也就是是否处于上拉,下拉的部分。没有做判断,我现在的代码就会导致你手势移动的距离和控件滚动的距离是不一样的。我是感觉如果你正常使用是不会注意到这一点的。但是不排除有这种需求。

下拉其实不太好判断,因为我这里操作的是ChildView,ScrollView在上拉过程中getScrollY()肯定是0,所以这一点,我也还没想好。不过上拉倒是比较简单。当childView.height <= ScrollView.height + getScrollY的时候就是上拉出屏幕的点了,这个应该能想通吧。

git地址:https://github.com/cjhandroid/ReboundScrollView

源码下载:http://xiazai.jb51.net/201611/yuanma/androidReboundScrollView(jb51.net).rar

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

时间: 2024-07-29 05:15:05

Android ReboundScrollView仿IOS拖拽回弹效果的相关文章

ios 像qq这样气泡可以拖拽的效果是如何实现的?

问题描述 ios 像qq这样气泡可以拖拽的效果是如何实现的? 有点好奇哈,倒是不知道如何实现,谢谢了-啊啊啊啊啊啊啊啊啊啊啊啊 解决方案 说下思路,监听点击与拖动事件,得到最新的坐标,再给view执行位移动画 解决方案二: 按压事件处理,让旗袍跟着用户触摸屏幕轨迹移动

Android开发仿映客送礼物效果_Android

这里写链接内容仿映客送小礼物的特效,顺便复习一下属性动画,话不多说先看效果图. 需求分析 可以看到整个动画有几部分组成,那我们就把每个部分拆分出来各个击破. 1.要显示那些内容以及内容间的位置关系? 可以看到我们要显示用户头像,昵称,礼物图标以及数量.所以这里我选择用FrameLayout来作为根布局. 2.需要哪些动画以及动画的执行顺序? a.首先是整体从左到右飞入并有一个回弹(translationX + OvershootInterpolator) b.然后是礼物从左到右飞入而且是一个带减

android ListView和GridView拖拽移位实现代码_Android

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

jQuery拖拽排序插件制作拖拽排序效果(附源码下载)_jquery

使用jquery拖拽排序插件制作拖拽排序效果是一款非常实用的鼠标拖拽布局插件.效果图如下: 效果演示         源码下载 html代码: <h1>水平拖拽</h1> <div class="demo"> <div class="item item1"><span>1</span></div> <div class="item item2"><

android ListView和GridView拖拽移位实现代码

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例: 首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点,我没有那么有才,我也是

Android开发仿映客送礼物效果

这里写链接内容仿映客送小礼物的特效,顺便复习一下属性动画,话不多说先看效果图. 需求分析 可以看到整个动画有几部分组成,那我们就把每个部分拆分出来各个击破. 1.要显示那些内容以及内容间的位置关系? 可以看到我们要显示用户头像,昵称,礼物图标以及数量.所以这里我选择用FrameLayout来作为根布局. 2.需要哪些动画以及动画的执行顺序? a.首先是整体从左到右飞入并有一个回弹(translationX + OvershootInterpolator) b.然后是礼物从左到右飞入而且是一个带减

Android实现仿通讯录侧边栏滑动SiderBar效果代码_Android

本文实例讲述了Android实现仿通讯录侧边栏滑动SiderBar效果代码.分享给大家供大家参考,具体如下: 之前看到某些应用的侧边栏做得不错,想想自己也弄一个出来,现在分享出来,当然里面还有不足的地方,请大家多多包涵. 先上图: 具体实现的代码如下: package com.freesonfish.listview_index; import android.content.Context; import android.graphics.Canvas; import android.grap

jquery实现鼠标拖拽滑动效果来选择数字的方法_jquery

本文实例讲述了jquery实现鼠标拖拽滑动效果来选择数字的方法.分享给大家供大家参考.具体如下: 这是使用jquery ui实现的一个精美实用的效果,可以通过鼠标拖拽滑动效果来选择数字 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns

Android实现仿gallery垂直滚动的效果

Android实现仿gallery垂直滚动的效果  效果图:  附件里是整个工程,如果喜欢可以下载看下.我感觉挺复杂的,如果需要的时候可以研究下,哈哈 实现垂直滚动的gallery.rar