【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果_第1页
【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果_第2页
【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果_第3页
【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果_第4页
【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

本篇文章为大家展示了Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。创建自定义ViewGroup:package

com.maxi.viewdraghelpertest.widget;

import

android.content.Context;

import

android.support.v4.widget.ViewDragHelper;

import

android.util.AttributeSet;

import

android.view.View;

import

android.widget.LinearLayout;

public

class

DragHelperLayout

extends

LinearLayout{

private

ViewDragHelper

mDragHelper;

@SuppressWarnings("static-access")

public

DragHelperLayout(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

//

TODO

Auto-generated

constructor

stub

/*

*

创建带回调接口的ViewDragHelper

*/

mDragHelper

=

ViewDragHelper.create(this,

10.0f,new

DragHelperCallback());//

参数一:该类生成的对象(当前的ViewGroup)

//

参数二:敏感度(越大越敏感)

}

class

DragHelperCallback

extends

ViewDragHelper.Callback

{

@Override

public

boolean

tryCaptureView(View

arg0,

int

arg1)

{

//

TODO

Auto-generated

method

stub

return

false;

}

}

}然后将触摸事件传递给ViewDragHelper:@Override

public

boolean

onInterceptTouchEvent(MotionEvent

event)

{

return

mDragHelper.shouldInterceptTouchEvent(event);//是否应该打断MotionEvent的传递

}

@Override

public

boolean

onTouchEvent(MotionEvent

event)

{

mDragHcessTouchEvent(event);

return

true;

}接着我们开始实现DragHelperCallback,这个ViewDragHelper.Callback回调中可以对ViewGroup中的一些View进行操作,在此我们只对本项目涉及到的相关用法做解析,详细点请自行查阅资料。class

DragHelperCallback

extends

ViewDragHelper.Callback

{

@Override

public

boolean

tryCaptureView(View

arg0,

int

arg1)

{

//

TODO

Auto-generated

method

stub

return

true;

//返回true表示可以捕捉ViewGroup中的View

}

/*

*

(non-Javadoc)

*

@see

android.support.v4.widget.ViewDragHelper.Callback#clampViewPositionVertical(android.view.View,

int,

int)

*

限定View竖直方向上的活动区域,防止滑出ViewGroup

*/

@Override

public

int

clampViewPositionVertical(View

child,

int

top,

int

dy)

{

int

topBound

=

getPaddingTop();

int

bottomBound

=

getHeight()

-

child.getHeight()

-

topBound;

int

newHeight

=

Math.min(Math.max(top,

topBound),

bottomBound);

return

newHeight;

}

}在上面的代码段中我已经做了注释,在clampViewPositionVertical中我们对View的竖直方向活动区域做了限制,防止滑出ViewGroup,当然你可以直接returntop;不过为了效果我先这么限定一下。还有一个clampViewPositionHorizontal方法,同样是对其水平边界进行控制的,先不多说啦。这个时候咱们自定义的ViewGroup初期已经完成,先去试试水。在activity_main.xml中加入<RelativeLayout

xmlns:android="/apk/res/android"

xmlns:tools="/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.maxi.viewdraghelpertest.MainActivity"

>

<com.maxi.viewdraghelpertest.widget.DragHelperLayout

android:id="@+id/dhl"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:background="@android:color/darker_gray"

>

<TextView

android:layout_width="match_parent"

android:layout_height="100dp"

android:background="@android:color/holo_blue_bright"

/>

<TextView

android:layout_width="match_parent"

android:layout_height="100dp"

android:background="@android:color/holo_orange_dark"

/>

</com.maxi.viewdraghelpertest.widget.DragHelperLayout>

</RelativeLayout>运行后的效果:大家是不是都急了,做个拖动加载怎么搞起这东西了,不要急,这才刚刚开始,大家想想拖动加载是不是就是两个View在同一个ViewGroup里通过ViewDragHelper的滑动操作然后实现的?是不是有思路的?没有思路也没关系,咱慢慢来,想要两个View相关联,就是拖动一个View然后另一个View跟着它走该怎么实现呢?首先我们需要ViewDragHelper回调里的另一个方法onViewPositionChanged,该方法是在View位置发生改变时回调的。为的就是在上面的View上拉的时候让下面的View跟着往上走。来看看我们的实现方法:首先先将两个View初始化:private

View

t1,

t2;

/*

*

(non-Javadoc)

*

@see

android.view.View#onFinishInflate()

*

初始化两个View

*/

@Override

protected

void

onFinishInflate()

{

t1

=

getChildAt(0);

t2

=

getChildAt(1);

}得到两个View后我们在回调中判断哪个位置发生了改变,@Override

public

void

onViewPositionChanged(View

changedView,

int

left,

int

top,

int

dx,

int

dy)

{

//

TODO

Auto-generated

method

stub

int

childIndex

=

1;

if

(changedView

==

t2)

{

childIndex

=

2;

}

viewFollowChanged(childIndex,

top);

}上面的代码段中有个方法viewFollowChanged,主要实现的就是View跟着动。private

void

viewFollowChanged(int

viewIndex,

int

posTop)

{

viewH

=

t1.getMeasuredHeight();

if

(viewIndex

==

1)

{

int

offsetTopBottom

=

viewH

+

t1.getTop()

-

t2.getTop();

t2.offsetTopAndBottom(offsetTopBottom);

}

else

if

(viewIndex

==

2)

{

int

offsetTopBottom

=

t2.getTop()

-

viewH

-

t1.getTop();

t1.offsetTopAndBottom(offsetTopBottom);

}

invalidate();

}

在运行是不是发现没有被点击拖动的View会跟着View一起移动,像一个整体双宿双飞。图我就不加了,大家运行看吧。因为我们要获取View的实际大小所以需要以下代码段的支持:@Override

protected

void

onMeasure(int

widthMeasureSpec,

int

heightMeasureSpec)

{

measureChildren(widthMeasureSpec,

heightMeasureSpec);

int

maxWidth

=

MeasureSpec.getSize(widthMeasureSpec);

int

maxHeight

=

MeasureSpec.getSize(heightMeasureSpec);

setMeasuredDimension(

resolveSizeAndState(maxWidth,

widthMeasureSpec,

0),

resolveSizeAndState(maxHeight,

heightMeasureSpec,

0));

}

public

static

int

resolveSizeAndState(int

size,

int

measureSpec,

int

childMeasuredState)

{

int

result

=

size;

int

specMode

=

MeasureSpec.getMode(measureSpec);

int

specSize

=

MeasureSpec.getSize(measureSpec);

switch

(specMode)

{

case

MeasureSpec.UNSPECIFIED:

result

=

size;

break;

case

MeasureSpec.AT_MOST:

if

(specSize

<

size)

{

result

=

specSize

|

MEASURED_STATE_TOO_SMALL;

}

else

{

result

=

size;

}

break;

case

MeasureSpec.EXACTLY:

result

=

specSize;

break;

}

return

result

|

(childMeasuredState

&

MEASURED_STATE_MASK);

}然后我们可以尝试将两个View满屏,android:layout_height="match_parent",把clampViewPositionVertical方法里限制的边界去掉吧,暂时先returntop;这样试一下是不是有点像拖动加载了,呵呵哒,可是第一个View下拉的时候由于上面没有View怎么办?我们可以在clampViewPositionVertical中将它限定边界啊!@Override

public

int

clampViewPositionVertical(View

child,

int

top,

int

dy)

{

int

slideTop

=

top;

if

(child

==

t1)

{

if

(top

>

0)

{

slideTop

=

0;

}

}

else

if

(child

==

t2)

{

if

(top

<

0)

{

slideTop

=

0;

}

}

return

child.getTop()

+

(slideTop

-

child.getTop());

}已经大致成型了,然后就是拖动的时候将View自动置顶或置底,因为自动置顶或置底是在滑动松开之后,所以就需要用到ViewDragHelper回调里的onViewReleased方法,该方法就是在滑动松开之后调用,接下来实现它:@Override

public

void

onViewReleased(View

releasedChild,

float

xvel,

float

yvel)

{

putStickOrDown(releasedChild);//

滑动松开后,需要置顶或置底

}

private

void

putStickOrDown(View

releasedChild,

float

yvel)

{

int

finalTop

=

0;

//

默认是粘到最顶端

if

(releasedChild

==

t1)

{

//

滑动第一个view松开

if

(yvel

<

0)//灵敏度自己调吧

finalTop

=

-viewH;

}

else

{

//

滑动第二个view松开

if

(yvel

>

0)//同上

finalTop

=

viewH;

}

if

(mDragHelper.smoothSlideViewTo(releasedChild,

0,

finalTop))

{

ViewCompat.postInvalidateOnAnimation(this);//

会在下一个Frame开始的时候,发起一些invalidate操作

}

}

@Override

public

void

computeScroll()

{

if

(mDragHelper.continueSettling(true))

{

ViewCompat.postInvalidateOnAnimation(this);

}

}ok,是可以自动置顶或置底了。对了,那种拖动粘滞效果可以设置clampViewPositionVertical里的返回值,returnchild.getTop()+(finalTop-child.getTop())/num;num值越大越粘滞。然后淘宝第一个View是可以滑动的滑动到最底部然后才把手势事件交给ViewDragHelper处理的。这块试想如果用ScrollView的话,手势事件肯定会优先被它消费,这样肯定达不到我们想要的效果,所以在此我们需要对ScrollView进行自定义,大致的实现思路是当用户用户从触发屏幕开始判断是不是ScrollView在最底端,如果在最底端然后判断手势是否是向上滑动的如果也是则满足条件将touch事件交给父View就可以了,即requestDisallowInterceptTouchEvent该方法。然后自定义的ViewGroup中的onInterceptTouchEvent方法也要做相应修改,这里用GestureDetectorCompat处理事件,其回调用来判断是否是上下滑动。先声明p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论