我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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          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) {   mDragHelper.processTouchEvent(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     }          @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,当然你可以直接return top;不过为了效果我先这么限定一下。还有一个clampViewPositionHorizontal方法,同样是对其水平边界进行控制的,先不多说啦。这个时候咱们自定义的ViewGroup初期已经完成,先去试试水。

在activity_main.xml中加入

<RelativeLayout 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"   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>

运行后的效果:

Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

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

private View t1, t2;  @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方法里限制的边界去掉吧,暂时先return top;这样试一下是不是有点像拖动加载了,呵呵哒,可是第一个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());     }

Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

已经大致成型了,然后就是拖动的时候将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里的返回值,return child.getTop() + (finalTop - child.getTop()) / num;num值越大越粘滞。

然后淘宝第一个View是可以滑动的滑动到最底部然后才把手势事件交给ViewDragHelper处理的。这块试想如果用ScrollView的话,手势事件肯定会优先被它消费,这样肯定达不到我们想要的效果,所以在此我们需要对ScrollView进行自定义,大致的实现思路是当用户用户从触发屏幕开始判断是不是ScrollView在最底端,如果在最底端然后判断手势是否是向上滑动的如果也是则满足条件将touch事件交给父View就可以了,即requestDisallowInterceptTouchEvent该方法。然后自定义的ViewGroup中的onInterceptTouchEvent方法也要做相应修改,这里用GestureDetectorCompat处理事件,其回调用来判断是否是上下滑动。先声明private GestureDetectorCompat gestureDC;然后再gestureDC = new GestureDetectorCompat(context,new YSlideDetector());

class YSlideDetector extends SimpleOnGestureListener {    @Override   public boolean onScroll(MotionEvent e1, MotionEvent e2,       float distanceX, float distanceY) {     // TODO Auto-generated method stub     return Math.abs(distanceY) > Math.abs(distanceX);//Y方向绝对值大于X方向,上下滑动   } }<pre name="code" class="java">  @Override public boolean onInterceptTouchEvent(MotionEvent event) {   boolean is_y_slide = gestureDC.onTouchEvent(event);   boolean shouldIntercept = mDragHelper.shouldInterceptTouchEvent(event);   int action = event.getActionMasked();   if (action == MotionEvent.ACTION_DOWN) {     mDragHelper.processTouchEvent(event);// action_down时就让mDragHelper开始工作,否则有时候导致异常   }   return shouldIntercept && is_y_slide; }

上述内容就是Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android中怎么利用ViewDragHelper实现一个淘宝拖动加载效果

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

怎么在android中利用ProgressDialog实现一个加载效果

怎么在android中利用ProgressDialog实现一个加载效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。先自定义一个类继承ProgressDialogpubli
2023-05-31

Android中利用动态加载实现手机淘宝的节日特效

相信去年圣诞节打开过手机淘宝的童鞋都会对当时的特效记忆犹新吧:全屏飘雪,旁边还有个小雪人来控制八音盒背景音乐的播放,让人有种身临其境的感觉,甚至忍不住想狠狠购物了呢(误),大概就是下面这个样子滴:嗯,确实很炫,那么我们一步步去分析是如何实现
2022-06-06

怎么在Android应用中实现一个加载数据帧动画效果

这期内容当中小编将会给大家带来有关怎么在Android应用中实现一个加载数据帧动画效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。实现步骤:1、xml布局
2023-05-31

怎么在Android中利用ViewPager实现一个屏幕滑动效果

本篇文章给大家分享的是有关怎么在Android中利用ViewPager实现一个屏幕滑动效果,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。创建View创建一个在之后作为fragm
2023-05-30

怎么在Android中实现一个仿微软系统加载动画效果

怎么在Android中实现一个仿微软系统加载动画效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。实现步骤:初始化五个圆球分别设置中心点,方便画圆利用ValueAnimat
2023-06-14

Android中怎么利用EasyBarrage实现一个弹幕效果

Android中怎么利用EasyBarrage实现一个弹幕效果,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。概述EasyBarrage是Android平台的一种轻量级弹幕效
2023-05-30

如何在Android中利用ConstraintLayout实现一个动画效果

这篇文章将为大家详细讲解有关如何在Android中利用ConstraintLayout实现一个动画效果,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。xml布局: