承接上一篇,上一篇中讲解了实现滑动的第五种方法,如果你还没读过,可点击下面链接:

http://www.cnblogs.com/fuly550871915/p/4985482.html

这篇文章现在来讲解最后一种方法,也可以说是实现滑动的终极大招!不过相比之前的方法,实现的过程要复杂一些,但是实现的效果当然也会徇丽多彩!

六、使用ViewDragHelper实现

(1)基础知识

使用ViewDragHelper可以实现多种多样的滑动效果,只要细心处理,足够满足你的各种拖动的需求了。下面来讲解一下使用ViewDragHelper的步骤。

步骤一、实例化

mViewDragHelper = ViewDragHelper.create(this, callback);

需要注意的是,ViewDragHelper通常定义在一个ViewGroup中。callback是个回调类,下面自会讲到。

步骤二、拦截事件

必须要将触摸事件传递给ViewDragHelper处理。按照下面的模板书写即可。如下:

public boolean onInterceptTouchEvent(android.view.MotionEvent ev)
{
//注意一定要将触摸事件拦截下来
return mViewDragHelper.shouldInterceptTouchEvent(ev);
} public boolean onTouchEvent(MotionEvent event)
{ //必须将触摸事件传递给mDragHleper
mViewDragHelper.processTouchEvent(event); return true;
}

步骤三、重写computeScroll

其实ViewDragHelper内部也是通过Scroller类实现平滑滑动的,因此它也要重写这个方法。按照下面的模板书写即可:

public void computeScroll() {

        if(mViewDragHelper.continueSettling(true))
{
ViewCompat.postInvalidateOnAnimation(this);
}
}

步骤四、处理回调的callback

在回调类ViewDragHelper.Callback中,系统定义了大量的监听方法来帮助我们处理各种事件。

首先创建这个callback,模板代码如下:

private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
//什么时候开始检测触摸事件
public boolean tryCaptureView(View child, int pointerId) {
return false;
}

}

下面就开始介绍几个常常被重写的方法

方法 tryCaptureView
写法如下:
//什么时候开始检测触摸事件
public boolean tryCaptureView(View child, int pointerId) { return mSecondView == child;
}
  该方法是告诉回调的callback什么时候开始检测触摸事件。因为ViewDragHelper定义在一个
ViewGroup中,比如你需要当触摸到第二个子view时,才开始检测触摸事件,就可以如上书写。
方法 clampViewPositionHorizontal
写法如下:
/**
* 水平方向上的移动,默认的返回值为0,此时将它修改为检测到的left
*/
public int clampViewPositionHorizontal(View child, int left, int dx) { return left;
}
   该方法控制水平方向的移动,默认返回为0,即不移动.如果你想让水平方向上发生移动,可以像上面那样进行书写。
方法 clampViewPositionVertical
写法如下:
/**
* 垂直方向上的移动,默认值也是0,在这里干脆直接让它返回0
*/
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
该方法的含义与clampViewPositionHorizontal一样
方法onViewReleased
写法如下:
/**
* 当手指抬起时或者说是拖动结束时会回调这个方法
*/
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel); }
注意:该方法在手指抬起或者说是拖动结束时调用。可以在此方法中写一些你需要处理的逻辑。
另外还有一些其他方法,介绍如下:
onViewCaptured() 这个事件在用户触摸到view后回调
onViewDragStateChanged() 这个事件在拖拽状态改变时回调,比如idle,dragging等状态
onViewPositionChanged() 这个事件在位置改变时回调,常用于滑动时更改scale进行缩放等效果。

至此,基本上使用ViewDragHelper进行滑动的方法就讲解完了。但是还要记得在ViewGroup中,要在onFinishInflate方法中将子view获取到。

另外,ViewDragHelper使用smoothSlideViewTo进行滑动,使用ViewCompat.postInvalidateOnAnmation方法进行刷新。这两个方法一定要同时使用!

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(2)代码实战

上面说了那么多,还没实践一下呢!现在就来写一个实际例子,这个例子基本上可以当做模板了,以后想要实现更复杂的功能,可以在此基础上修改。因此,要好好研究这个例子。

在写代码前先上一张最终的效果图,如下:

好了,效果很丑陋,但是足够说明问题了。开始看看代码是怎么写的吧。

新建一个项目。然后自定义一个DragViewGroup继承自ViewGroup,在它的里面使用ViewDragHelper愉快的定制吧。如下:

package com.example.testdragview;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout; public class DragViewGroup extends FrameLayout{ private ViewDragHelper mViewDragHelper; private View mFirstView;
private View mSecondView; private int mFirstViewWidth; public DragViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); mViewDragHelper = ViewDragHelper.create(this, callback);
} public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
mViewDragHelper = ViewDragHelper.create(this, callback);
} public DragViewGroup(Context context) {
super(context);
mViewDragHelper = ViewDragHelper.create(this, callback);
} /**
* 关于mDragHelper的拖动等操作都在这个类里面操作
*/
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { //什么时候开始检测触摸事件
public boolean tryCaptureView(View child, int pointerId) { return mSecondView == child;
} /**
* 水平方向上的移动,默认的返回值为0,此时将它修改为检测到的left
*/
public int clampViewPositionHorizontal(View child, int left, int dx) { return left;
} /**
* 垂直方向上的移动,默认值也是0,在这里干脆直接让它返回0
*/
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
} /**
* 当手指抬起时或者说是拖动结束时会回调这个方法
*/
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel); if(mSecondView.getLeft() <100)
{//如果第二个view的left小于500像素,就不显示第一个view。下面的代码就相当于此 mViewDragHelper.smoothSlideViewTo(mSecondView, 0, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}else
{//显示第一个view mViewDragHelper.smoothSlideViewTo(mSecondView, 300, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
} } }; /**
* 布局加载完成后调用
* 在这个方法里获取子view
*/
protected void onFinishInflate() {
super.onFinishInflate(); mFirstView = getChildAt(0);
mSecondView = getChildAt(1);
} /**
* 子view的大小改变后回调该方法
* 在这个方法里获取到mFirstView的宽度
*/
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh); mFirstViewWidth = mFirstView.getMeasuredWidth();
} public boolean onInterceptTouchEvent(android.view.MotionEvent ev)
{
//注意一定要将触摸事件拦截下来
return mViewDragHelper.shouldInterceptTouchEvent(ev);
} public boolean onTouchEvent(MotionEvent event)
{ //必须将触摸事件传递给mDragHleper
mViewDragHelper.processTouchEvent(event); return true;
} public void computeScroll() { if(mViewDragHelper.continueSettling(true))
{
ViewCompat.postInvalidateOnAnimation(this);
}
} }

结合前面的基础知识和代码中的注释,应该很好理解了。就是在DragViewGroup里面使用ViewDragHelper定义了一个拖动的效果而已!值得注意的是在onReleased方法中,我们做了这样子的一个设定,即当mSecondView的左边距小于100像素时,就将mSecondView移动到初始位置(造成的效果仍然是遮挡出mFirstView,即关闭mFirstView);当其左边与大于100像素,就将其移动的距离左边300像素的位置(当然是相对于它的ViewGroup的左边距了)。

下面我们建立建立两个用来填充到DragViewGroup中的布局,分别命名为layout1.xml和layout2.xml。如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="#ff0000"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="你好啊,我是第一个view"
android:textSize="30sp"/> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="#FFFF80"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="拖动我,赶紧拖动我"
android:textSize="30sp"/> </LinearLayout>

下面就修改activity_main.xml中的代码,将这两个子布局放进DragViewGroup中吧,如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <com.example.testdragview.DragViewGroup
android:layout_width="match_parent"
android:layout_height="match_parent"
> <include layout = "@layout/layout1"/>
<include layout = "@layout/layout2"/> </com.example.testdragview.DragViewGroup> </LinearLayout>

就这样子,所有的工作都完成了,运行程序吧。效果和上面贴出来的图一样。好了,要想掌握好ViewDragHelper,还需要多加练习。

至此,android中实现view滑动的六种方法都讲完了!

android中实现view可以滑动的六种方法续篇(二)的更多相关文章

  1. android中实现view可以滑动的六种方法续篇(一)

    承接上一篇,如果你没有读过前四章方法,可以点击下面的链接: http://www.cnblogs.com/fuly550871915/p/4985053.html 下面开始讲第五中方法. 五.利用Sc ...

  2. android中实现view可以滑动的六种方法

    在android开发中,经常会遇到一个view需要它能够支持滑动的需求.今天就来总结实现其滑动的六种方法.其实每一种方法的 思路都是一样的,即:监听手势触摸的坐标来实现view坐标的变化,从而实现vi ...

  3. Android View体系(二)实现View滑动的六种方法

    1.View的滑动简介 View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理.其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统 ...

  4. 详解实现Android中实现View滑动的几种方式

    注: 本文提到的所有三种滑动方式的完整demo:ScrollDemo 1. 关于View我们需要知道的 (1)什么是View? Android中的View类是所有UI控件的基类(Base class) ...

  5. Android 中的View与ViewGroup

    Android重点知识--View和ViewGroup与自定义控件 作者:丁明祥 邮箱:2780087178@qq.com 一.基础 ViewGroup 参考资料: Android 手把手教您自定义V ...

  6. android中的坐标系以及获取坐标的方法

    android中有两种坐标系,分别称之为Android坐标系和视图坐标系.而对应的也有一些相关的方法可以获取坐标系中的 坐标值.只有搞清楚这些区别,才能在实现的时候不至于出错或者得不到你想要的效果. ...

  7. MVC中视图View向控制器传值的方法

    MVC中视图View向控制器传值的方法步骤如下: 1.index页面: 页面中只需要一个触发事件的按钮

  8. android中Bitmap的放大和缩小的方法

    android中Bitmap的放大和缩小的方法 时间 2013-06-20 19:02:34  CSDN博客原文  http://blog.csdn.net/ada168855/article/det ...

  9. Android 自己定义View须要重写ondraw()等方法

    Android  自己定义View须要重写ondraw()等方法.这篇博客给大家说说自己定义View的写法,须要我们继承View,然后重写一些 方法,方法多多,看你须要什么方法 首先写一个自己定义的V ...

随机推荐

  1. [python]在场景中理解装饰器

    原来我也自己通过查资料,来学习python的装饰器,但是效果不好.因为没有接触过需要用到装饰器的场景,所以 一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.v ...

  2. Hekaton的神话与误解

    最近这段时间,我花了很多时间来更好的理解Hekaton——SQL Sever 2014里的全新内存表技术.我看了很多文章,了解了Haktaon的各种内部数据存储结构(主要是哈希索引和Bw-tree). ...

  3. Django项目--web聊天室

    需求 做一个web聊天室,主要练习前端ajax与后台的交互: 一对一聊天和群组聊天 添加用户为好友 搜索并添加群组 管理员可以审批用户加群请求,群管理员可以有多个,群管理员可以删除,添加禁言群友 与聊 ...

  4. Django--models表操作

    需求 models对表的增删改查 知识点 1.基础操作 1.1  增 方法一 1 models.Tb1.objects.create(c1='xx', c2='oo')  #增加一条数据 1 2 di ...

  5. Spring基础——小的知识点

    一.整合多个配置文件 在 Spring Config 文件中,可以使用 <import> 标签将别的配置文件引入到一个文件中,进行配置文件的集成.该标签和 <bean> 标签同 ...

  6. sprint3冲刺总结

    维持了一个多月的sprint3次总结终于结束了,我们小组也顺利的完成了我们的项目,总的来说这次完成的项目还是有一定的质量的,无论是外貌形象包装还是功能来说都达到了我们当初所设定的目标,美中不足的就是时 ...

  7. nodejs+express+jade给我baby做个小相册

    去年年底迎来了my little star.从此人生多了一个最重要的牵挂.生了宝宝全家人都太忙了.最近宝宝稍微大点了,终于有空可以研究下技术了.这是14年第一帖.废话不多了.开始吧 1.安装NTVS ...

  8. 设计模式--原型(Prototype)模式

    写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自 ...

  9. 一个SpringMVC简单Demo中出现的错误

    最近在学springmvc 一个简答的Springmvc配置包括如下步骤: 1.在 web.xml 文件中配置 DispatcherServlet (该中央控制器相当于 MVC 模式中的 C),还可以 ...

  10. PHP异常与错误处理机制

    先区别一下php中错误 与 异常的概念吧 PHP错误:是属于php程序自身的问题,一般是由非法的语法,环境问题导致的,使得编译器无法通过检查,甚至无法运行的情况.平时遇到的warming.notice ...