Android ReboundScrollView仿IOS拖拽回弹效果

 更新时间:2016年11月11日 10:16:41   作者:jia-huan  
这篇文章主要为大家详细介绍了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

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

相关文章

  • 从源码分析Android的Glide库的图片加载流程及特点

    从源码分析Android的Glide库的图片加载流程及特点

    这篇文章主要介绍了从源码分析Android的Glide库的图片加载流程及特点,Glide库是Android下一款人气很高的多媒体资源管理库,特别是在处理gif加载方面受到众多开发者青睐,需要的朋友可以参考下
    2016-04-04
  • Android弹窗ListPopupWindow的简单应用详解

    Android弹窗ListPopupWindow的简单应用详解

    这篇文章主要为大家详细介绍了Android弹窗ListPopupWindow的简单应用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Kotlin中内置函数的用法和区别总结

    Kotlin中内置函数的用法和区别总结

    众所周知相比Java, Kotlin提供了不少高级语法特性。对于一个Kotlin的初学者来说经常会写出一些不够优雅的代码。下面这篇文章主要给大家介绍了关于Kotlin中内置函数的用法和区别的相关资料,需要的朋友可以参考下
    2018-06-06
  • Android中使用Service实现后台发送邮件功能实例

    Android中使用Service实现后台发送邮件功能实例

    这篇文章主要介绍了Android中使用Service实现后台发送邮件功能的方法,结合实例形式分析了Service实现邮件的发送、接收及权限控制相关技巧,需要的朋友可以参考下
    2016-01-01
  • Android Vibrator调节震动代码实例

    Android Vibrator调节震动代码实例

    这篇文章主要介绍了Android Vibrator调节震动代码实例,本文直接给出实现代码,代码中包含详细注释,需要的朋友可以参考下
    2015-05-05
  • Android编程实现自定义title功能示例

    Android编程实现自定义title功能示例

    这篇文章主要介绍了Android编程实现自定义title功能,结合具体实例形式分析了Android自定义title的具体实现步骤与相关操作技巧,需要的朋友可以参考下
    2017-03-03
  • Android DownloadProvider 源码详解

    Android DownloadProvider 源码详解

    这篇文章主要介绍了Android DownloadProvider 源码详解的相关资料,需要的朋友可以参考下
    2016-11-11
  • Android 如何使用SQLite保存数据

    Android 如何使用SQLite保存数据

    对于重复数据或结构化数据(例如联系信息),将数据保存到数据库是理想选择,SQL 数据库的主要原则之一是架构,即数据库组织方式的正式声明,本篇文章介绍在 Android 上使用 SQLite 数据库,感兴趣的朋友一起看看吧
    2024-03-03
  • android 仿微信demo——微信通讯录界面功能实现(移动端,服务端)

    android 仿微信demo——微信通讯录界面功能实现(移动端,服务端)

    本系列文章主要介绍了微信小程序-阅读小程序实例(demo),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能给你们提供帮助
    2021-06-06
  • Android自定义StickinessView粘性滑动效果

    Android自定义StickinessView粘性滑动效果

    这篇文章主要为大家详细介绍了Android自定义StickinessView粘性滑动效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03

最新评论