Android ViewDragHelper使用方法详解
作者:难不难太难了 发布时间:2022-08-27 02:01:28
帮我们实现各种类型的复杂手势操作。其实例通过静态工厂创建ViewDragHelper一般用在一个自定义ViewGroup的内部。
初始化操作
private ViewDragHelper mDrragHelper;
public SlideViewGroup(@NonNull Context context) {
this(context,null);
}
public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);
}
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);第一个操作表示当前操作的对象,第二个参数为手势操作敏感度,
第三个参数为我们手势处理的毁掉接口
我们需要先在view事件分发时把手势操作交给ViewFragHelper
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
//交给viewdrag去拦截
//事件分发拦截
float x=0;
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
x =event.getX();
break;
// return false;
case MotionEvent.ACTION_MOVE:
if (STATE==0&getX()-x<0){
return mDrragHelper.shouldInterceptTouchEvent(event);
}else if (STATE==1){
return mDrragHelper.shouldInterceptTouchEvent(event);
}
break;
}
return false;
}
//boolean control=true;//控制downx的初始化
@Override
public boolean onTouchEvent(MotionEvent event) {
mDrragHelper.processTouchEvent(event);
//if (control)
float downX=0;
if (event.getAction()==MotionEvent.ACTION_DOWN){
downX=event.getRawX();
if (STATE==1){
//if (event.getRawX()>0&downX<leftWidth-rightViewWidth)
//close();
// Toast.makeText(this.getContext(), "leftWidth"+leftWidth+"rawx"+event.getRawX(), Toast.LENGTH_SHORT).show();
}
}
if (event.getAction()==MotionEvent.ACTION_UP){
//Toast.makeText(this.getContext(), "downx"+downX, Toast.LENGTH_SHORT).show();
//点击删除//&downX>leftWidth-rightViewWidth&downX<leftWidth-rightViewWidth/2
// Toast.makeText(this.getContext(), "删除1", Toast.LENGTH_SHORT).show();
if (STATE==1&event.getRawX()>leftWidth-rightViewWidth&event.getRawX()<leftWidth-rightViewWidth/2){
// Toast.makeText(this.getContext(), "删除2", Toast.LENGTH_SHORT).show();
if (skipListener!=null){
// Toast.makeText(this.getContext(), "删除3", Toast.LENGTH_SHORT).show();
skipListener.onDelete();
}
// Toast.makeText(this.getContext(), "删除", Toast.LENGTH_SHORT).show();
}
//点击删除&downX>leftWidth-rightViewWidth/2&downX<leftWidth-rightViewWidth
if (STATE==1&event.getRawX()>leftWidth-rightViewWidth/2&event.getRawX()<leftWidth){
// Toast.makeText(this.getContext(), "修改", Toast.LENGTH_SHORT).show();
if (skipListener!=null){
skipListener.onDefine();
}
}
}
return true;
}
重点在这两句
mDrragHelper.shouldInterceptTouchEvent(event);
mDrragHelper.processTouchEvent(event);
我们可以在onInterceptTouchEvent决定什么时候把事件交给我们的手势操作类
然后是回调类
private ViewDragHelper.Callback mCallback=new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==leftView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (left>=0)
return 0;
if (left<-rightViewWidth)
return -rightViewWidth;
return left;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight);
/* if (left<0&left>rightViewWidth/2){
mDrragHelper.smoothSlideViewTo(leftView,left,0);
mDrragHelper.smoothSlideViewTo(rightView,left,0);
}*/
/* if (left>=-(leftWidth+rightViewWidth)) {
rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight);
}
if (left<-(leftWidth+rightViewWidth)){
rightView.layout(leftWidth, 0, leftWidth + rightViewWidth, viewHeight);
}*/
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
Log.i("left xvel",xvel+"y"+yvel);
if (xvel<0){
open();/* mDrragHelper.smoothSlideViewTo(rightView,rightViewWidth/2,0);*/
}else if (leftView.getLeft()<-rightViewWidth/2)
{open();}else {
// Log.i("left open","open");
close();
}
}
@Override
public int getViewHorizontalDragRange(View child) {
return -rightViewWidth;
}
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
super.onEdgeTouched(edgeFlags, pointerId);
}
};
tryCaptureView的返回值表示我们允许操作的child
clampViewPositionHorizontal()方法的默认返回值为0,返回值代表水平移动的距离,也就是left值,当返回left值时,我们操作的view就会跟着我们的拖动而移动,当然还有数值方向的方法,如果需要也可以重写竖直操作的方法
onViewPositionChanged()方法就是当我们移动时就会回调这个方法,此处的left参数就是水平移动返回的left,dx就是水平距离相对变化
onViewRelased()方法就是手指抬起时(释放)时回调的方法,xvel每秒钟水平速度速度慢时为0,单位为像素,yvel为每秒钟竖直方向的速度。速度有正负之分
滑动边缘:
分为滑动左边缘还是右边缘:EDGE_LEFT和EDGE_RIGHT,下面的代码设置了可以处理滑动左边缘:
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
假如如上设置,onEdgeTouched方法会在左边缘滑动的时候被调用,这种情况下一般都是没有和子view接触的情况。
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
super.onEdgeTouched(edgeFlags, pointerId);
Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show();
}
如果你想在边缘滑动的时候根据滑动距离移动一个子view,可以通过实现onEdgeDragStarted方法,并在onEdgeDragStarted方法中手动指定要移动的子View
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
mDragHelper.captureChildView(mDragView2, pointerId);
}
滑动
手指在当前view的下边缘就可以滑动
下面看一个我在ontochEvent调用的方法
public void open(){
if (listener!=null){
listener.onOpen(this);
}
if (mDrragHelper.smoothSlideViewTo(leftView,-rightViewWidth,0))
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this);
STATE=1;
}
就是平滑滑动,
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this)
上面那个方法就是刷新布局(重绘操作)
然后会回调次viewgroup的computerScroll
@Override
public void computeScroll() {
if (mDrragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
其实滑动本身还是调用的scrollto跟据时间百分比移动,根据比例移动固定距离后就不移动了,所以我们需要重复刷新,需要判断临界条件,可能是时间可能是距离,可以点进continueSetting方法返回false代表动画完成,进去一看就明白了,需要判断滑动事件是否完成,如果完成就不再刷新,如果没完成就刷新。
来源:http://blog.csdn.net/m0_37402140/article/details/77840571


猜你喜欢
- 前言你一定会好奇:“老周,你去哪开飞机了?这么久没写博客了。”老周:“我买不起飞机,开了个铁矿,挖了一年半的石头。谁知铁矿垮了,压死了几条蜈
- 一、加密介绍本文采用对称式加密算法DES和非对称式加密算法RSA结合做数据传输加密的方式。先说一下对称式加密 DES:对称式加密即使用单钥密
- Intellij IDEA 公司 JetBrains 推出了一种新字体:JetBrains Mono,它是专为开发人员设计的。为什么说它是专
- 1 什么是cookie浏览器与WEB服务器之间是使用HTTP协议进行通信的,当某个用户发出页面请求时,WEB服务器只是简单的进行响应,然后就
- 策略模式的应用场景策略模式是否要使用,取决于业务场景是否符合,有没有必要。是否符合如果业务是处于不同的场景时,采取不同的处理方式的话,就满足
- /*最小树形图图模版-朱刘算法模版说明:点标号必须0-(N-1) 必须去除到自身的点(到自身的边的边权赋无限大)*/
- 今天跟大家聊聊我心目中的物流追踪效果,效果图如下,有需要的朋友,可以直接带走,实现也没有想象中的那么复杂,特别是左边那个时间轴线,没那么复杂
- class文件中的attributes_count和attributesattributes_count位于class文件中methods的
- 在Android Studio项目中引用第三方jar包的方法:步骤:1、在build.gradle文件中添加如下代码:备注:要添加在Andr
- Gson是Google的一个开源项目,可以将Java对象转换成JSON,也可能将JSON转换成Java对象。Gson里最重要的对象有2个Gs
- 这是一个及其常见的问题,网上已经有关于这个问题的很多讨论。但是我觉得都是不求甚解,有一些还是在误导别人。下面我来说下我对这三者的理解,如有错
- 这两天看到Hibernate的代理部分,第一反应是底层使用了反射,针对用户实体生成了代理类,后来反应过来了,反射没有任何可以产生新类的能力,
- 本文实例讲述了C#实现的文件上传下载工具类。分享给大家供大家参考,具体如下:这里给出的工具类是在VS2013环境下采用C#语言实现文件上传、
- 目前为止,我遇到使用Tomcat有三种情况:第一,使用Eclipse,在Eclipse中配置Tomcat。第二,直接在Tomcat中部署项目
- 1.建议设置窗体为双缓冲绘图,可有效避免界面刷时引起的闪烁this.SetStyle(ControlStyles.AllPaintingIn
- 在C#中用同一个dataset保存从数据库中取出的多张表:cmd.CommandText = "select * from tab
- 前言:仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置一:先看效果图字母索引搜索匹配二:功能分析1:汉字转拼音通讯
- 一. 项目需求我们做项目的时候,数据量比较大,单表千万级别的,需要分库分表,于是在网上搜索这方面的开源框架,最常见的就是mycat,shar
- 其实我们在社交网络上面所发出的任何信息, 都希望能够保留下来. 那么如何实现呢?数据持久化数据持久化, 就是将内存中的瞬时数据保存在存储设备
- 数据库事务是被当作单个工作单元的操作序列。这些操作要么全部完成或全部不成功。事务管理是面向企业应用程序,以确保数据的完整性和一致性RDBMS