Android自定义控件仿ios下拉回弹效果

网上有很多类似的文章,大多数还是继承listview来实现(主要是listview.addHeaderView()和listview.addFooterView在listview的首尾添加view,也可以用上面的两个listview自带函数实现下拉刷新的功能,在这里不准备介绍,有兴趣的朋友可以去自己试试)。

在本文主要是给android的线性布局(相对布局、帧布局)加上下拉或者上拉回弹得效果。在ios中我们经常能看到,在一个页面中即使是只有一个控件,这一个控件只占整个页面的1/10不到,但是当我们下拉整个页面的时候还是会有回弹的效果(在这里我们暂不考虑这样的页面是否美观,只是就怎么实现进行分析),显然在android中我们不会为了实现这个只有一个item(而且不会变多)的页面而去用listview(listview的使用还是相对比较繁琐),我们会直接使用线性布局或者相对布局这些简易一些的viewgroup来实现。所以在这里我也为线性布局加上了下拉或者上拉回弹得效果。

实现流程:

1.新建一个类继承LinearLayout

2.在构造方法中实例化Scroller(用于滑动),GestureDetector(网上有很多实现方法是复写onTouchEvent方法,把onTouchEvent方法写的很长,我不太喜欢这种方式,也推荐大家多用手势,很好用哦);

3.覆写computeScroll(),onTouchEvent(MotionEvent event)(在这里把触摸屏幕的处理交给GestureDetector)
4.在computeScroll()里面完成实际的滚动

在开始具体的实现之前,先得介绍几个要用到的比较重要的函数

mScroller.getCurrX() //获取mScroller当前水平滚动的位置
mScroller.getCurrY() //获取mScroller当前竖直滚动的位置
mScroller.getFinalX() //获取mScroller最终停止的水平位置
mScroller.getFinalY() //获取mScroller最终停止的竖直位置
mScroller.setFinalX(int newX) //设置mScroller最终停留的水平位置,没有动画效果,直接跳到目标位置
mScroller.setFinalY(int newY) //设置mScroller最终停留的竖直位置,没有动画效果,直接跳到目标位置

//滚动,startX, startY为开始滚动的位置,dx,dy为滚动的偏移量, duration为完成滚动的时间
mScroller.startScroll(int startX, int startY, int dx, int dy) //使用默认完成时间250ms
mScroller.startScroll(int startX, int startY, int dx, int dy, int duration)

mScroller.computeScrollOffset() //返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。

上面的几个Scroller的方法,能够帮助我们实现滑动。

接下来还要介绍实现GestureDetector.OnGestureListener

因为我们在onTouchEvent中没有将MotionEvent.ACTION_UP交给GestureDetector,所以GestureDetector.OnGestureListener中的部分方法不会响应,还有在GestureDetector.OnGestureListener中要将down事件的返回值设为true,不然onscroll方法不会响应

接下来是具体实现:

public class SqqLinearLayout extends LinearLayout {
 private Scroller mScroller;
 private GestureDetector mGestureDetector; 

 public SqqLinearLayout (Context context) {
  this(context, null);
 } 

 public SqqLinearLayout (Context context, AttributeSet attrs) {
  super(context, attrs);
  mScroller = new Scroller(context);
  mGestureDetector = new GestureDetector(context, new GestureListenerImpl());
 } 

  //startScroll之后没有真正移动,会自动调用这个函数实现移动
 @Override
 public void computeScroll() {
  if (mScroller.computeScrollOffset()) { 

   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
   //必须执行postInvalidate()从而调用computeScroll()
   //其实,在此调用invalidate();亦可
   postInvalidate();
  }
  super.computeScroll();
 } 

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
  case MotionEvent.ACTION_UP :
  //手指抬起时回到最初位置
   prepareScroll(0, 0);
   break;
  default:
   //其余情况交给GestureDetector手势处理
   return mGestureDetector.onTouchEvent(event);
  }
  return super.onTouchEvent(event);
 } 

 class GestureListenerImpl implements GestureDetector.OnGestureListener {
 @Override
 public boolean onDown(MotionEvent e) {
  return true;
 }

 @Override
 public void onShowPress(MotionEvent e) {

 }

 @Override
 public boolean onSingleTapUp(MotionEvent e) {
  return false;
 }

 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
  int disY = (int) ((distanceY - 0.5)*0.65);
  beginScroll(0, disY);
  return false;
 }

 public void onLongPress(MotionEvent e) {

 }

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
  return false;
 }

 } 

 //滚动到目标位置
 protected void prepareScroll(int fx, int fy) {
  int dx = fx - mScroller.getFinalX();
  int dy = fy - mScroller.getFinalY();
  beginScroll(dx, dy,1000); //经测试1s是不错的
 } 

  //设置滚动的相对偏移
 protected void beginScroll(int dx, int dy) {
  mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); 

  //必须执行invalidate()从而调用computeScroll()
  //invalidate();
 //上面一句注释掉好像也没什么影响,暂时没有发现
 } 

  //设置滚动的相对偏移
 protected void beginScroll(int dx, int dy,int duration) {
  mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy,duration); 

  //必须执行invalidate()从而调用computeScroll()
  //invalidate();
 //上面一句注释掉好像也没什么影响,暂时没有发现
 } 

}

上面实现了线性布局的下拉回弹效果,相对布局的实现和上面一样,只是继承的是RelativeLayout。所以抱着不写重复代码的准则,在下一篇我会做个优化,将线性布局和相对布局的下拉刷新写到一个类中,具体的线性布局和相对布局作为参数或者其他的形式。当然这还只是个想法,不知道能不能很好的实现。

项目下载地址:Android自定义控件仿ios下拉回弹效果

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

(0)

相关推荐

  • Android ScrollView的顶部下拉和底部上拉回弹效果

    要实现ScrollView的回弹效果,需要对其进行触摸事件处理.先来看一下简单的效果: 根据Android的View事件分发处理机制,下面对dispatchTouchEvent进行详细分析: 在加载布局完成之后,获取ScrollView的第一个子元素,保存它的参数,left top right bottom参数,根据顶部下拉操作和底部上拉操作进行子View的布局参数根据滑动距离改变,ACTION_UP的时候判断是否存在回弹,如果需要则进行动画回弹到原来的位置,可以添加一个回弹结束监听,比如监听回

  • Android自定义ScrollView实现放大回弹效果

    背景 在很多项目中我们都会用到ScrollView这个控件,因为ScrollView能够在屏幕内容多时下上滑动以适配加载的内容.但是ScrollView滑动时效果感觉太死板了,这个时候我们如果给它添加一个回弹的动画效果,会让界面交互更加舒服,提升用户体验效果. 自定义ScrollView 1.创建一个类,继承ScrollView并重写相应的构造函数 public class ZoomInScrollView extends ScrollView { public ZoomInScrollView

  • Android ScrollView实现横向和竖向拖动回弹效果

    本文实例为大家分享了Android ScrollView实现拖动回弹效果的具体代码,供大家参考,具体内容如下 原理 在android2.3版本中,View类中新增了一个方法:overScrollBy.通过覆盖该方法,就可以达到阻尼回弹的效果. 示例1.竖向滚动 public class ReboundScrollView extends ScrollView{ private static final int MAX_SCROLL = 200; private static final floa

  • Android RecyclerView上拉加载更多功能回弹实现代码

    实现原理是使用RecyclerView的OnTouchListener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的View,我们设置其高度为0 我们通过LinearLayoutManager的 findLastVisibleItemPosition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新. 回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时

  • android仿QQ个人主页下拉回弹效果

    先看效果: 效果不错吧! 进入主题之前,先了解ImageView的scaleType的center_crop,网络上说的已经很清楚了 : 以下抄自网络: 1.Android:scaleType="centerCrop" 以填满整个ImageView为目的,将原图的中心对准ImageView的中心,等比例放大原图,直到填满ImageView为止(指的是ImageView的宽和高都要填满),原图超过ImageView的部分作裁剪处理. 均衡的缩放图像(保持图像原始比例),使图片的两个坐标(

  • Android编程ViewPager回弹效果实例分析

    本文实例讲述了Android编程ViewPager回弹效果.分享给大家供大家参考,具体如下: 其实在我们很多应用中都看到当ViewPager滑到第一页或者最后一页的时候,如果再滑动的时候,就会有一个缓冲的过程,也就是回弹效果.之前在研究回弹效果的时候,也顺便实现了ViewPager的回弹效果,其实也很简单,一下是实现代码,注释比较少: package com.freesonfish.viewpager_2; import android.content.Context; import andro

  • Android仿IOS回弹效果 支持任何控件

    本文实例为大家分享了Android仿IOS回弹效果的具体代码,供大家参考,具体内容如下 效果图: 导入依赖: dependencies { // ... compile 'me.everything:overscroll-decor-android:1.0.4' } RecyclerView 支持线性布局和网格布局管理器(即所有原生Android布局).可以轻松适应支持自定义布局管理器. RecyclerView recyclerView = (RecyclerView) findViewByI

  • Android 实现ViewPager边界回弹效果实例代码

    废话不多说了,直接给大家贴代码了,具体代码如下所示: public class BounceBackViewPager extends ViewPager { private int currentPosition = 0; private Rect mRect = new Rect();//用来记录初始位置 private boolean handleDefault = true; private float preX = 0f; private static final float RATI

  • Android界面上拉下拉的回弹效果实例代码

    废话不多说,具体代码如下所示: public class MyScrollView extends ScrollView { private View childView; public MyScrollView(Context context) { super(context); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public MyScrollView(Co

  • Android ReboundScrollView仿IOS拖拽回弹效果

    初衷: 其实github上有很多这种ScrollView的项目,但是不得不说功能太多太乱了,我就只是想要一个简单效果的ScrollView,另外监听下滑动距离而已,想想还是自己写了个. 这里先说下思路吧,如果不愿意看的朋友可以直接跳过这一步,看下面的代码: Android 原生的ScrollView是不支持拉出屏幕外,并且也没有回弹效果的,用户友好度却不不太好,不知道为什么不那么设计. 我想做的事情正如上面所述: 1.希望能拉出屏幕外 2.松手后希望控件回弹 我的思路是对ScrollView的子

  • Android自定义ScrollView实现放大回弹效果实例代码

    1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下: 2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果图如下: 3,自定义ScrollView 第一步:创建一个类,继承自ScrollView,重写相应的构造函数 public class ZoomInScrollView extends ScrollView { public ZoomInScrollView(Context context) { t

随机推荐