版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 结合中西医疗技术的探索
- 化工安全生产与环境保护管理措施研究
- 石河子大学《债法》2022-2023学年第一学期期末试卷
- 石河子大学《土木工程材料》2022-2023学年第一学期期末试卷
- 石河子大学《人力资源管理》2023-2024学年第一学期期末试卷
- 石河子大学《当代国际共产主义运动》2023-2024学年第一学期期末试卷
- 沈阳理工大学《运动控制基础》2022-2023学年期末试卷
- 沈阳理工大学《汽车构造》2022-2023学年第一学期期末试卷
- 造价年终总结汇报
- 沈阳理工大学《工程力学》2023-2024学年第一学期期末试卷
- 《中国当代文艺思潮》第二章主体论文艺思潮
- 北理c语言上机答案(全)
- 大学生创新思维与创新能力培养的实践探索模板课件
- DB63-T 1674-2018+多年冻土区+公路隧道技术规范
- 双向情感障碍
- 统编语文教材的主要特点和教学建议(课堂PPT)课件
- 胃溃疡 演示文稿课件
- 腹腔镜胆囊切除术后胆瘘
- ESD的防护常识幻灯片
- 传感器课程设计基于的温度测量系统
- 苏武传 省赛获奖-完整版课件
评论
0/150
提交评论