ViewDragHelper实现QQ侧滑效果

ViewDragHelper实现QQ侧滑效果,第1张

概述前言      侧滑的实现方式有很多方式来实现,这次总结的ViewDragHelper就是其中一种方式,ViewDragHelper是2013年谷歌I/O大会发布的新的控件,为了解决界面控件拖拽问题。下面就是自

前言

       侧滑的实现方式有很多方式来实现,这次总结的VIEwDragHelper就是其中一种方式,VIEwDragHelper是2013年谷歌I/O大会发布的新的控件,为了解决界面控件拖拽问题。下面就是自己学习写的一个实现类似于QQ侧滑效果的实现。
activity_main.xml:

<com.yctc.drag.DragLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:ID="@+ID/dl" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:background="@drawable/bg" tools:context=".MainActivity" > <linearLayout  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:orIEntation="vertical"  androID:paddingBottom="50dp"  androID:paddingleft="10dp"  androID:paddingRight="50dp"  androID:paddingtop="50dp" >  <ImageVIEw   androID:layout_wIDth="50dp"   androID:layout_height="50dp"   androID:src="@drawable/head" />  <ListVIEw   androID:ID="@+ID/lv_left"   androID:layout_wIDth="match_parent"   androID:layout_height="match_parent" >  </ListVIEw> </linearLayout> <com.yctc.drag.MylinearLayout  androID:ID="@+ID/mll"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:background="#ffffff"  androID:orIEntation="vertical" >  <relativeLayout   androID:layout_wIDth="match_parent"   androID:layout_height="50dp"   androID:background="#18B6EF"   androID:gravity="center_vertical" >   <ImageVIEw    androID:ID="@+ID/iv_header"    androID:layout_wIDth="30dp"    androID:layout_height="30dp"    androID:layout_marginleft="15dp"    androID:src="@drawable/head" />   <TextVIEw    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:layout_centerHorizontal="true"    androID:text="header" />  </relativeLayout>  <ListVIEw   androID:ID="@+ID/lv_main"   androID:layout_wIDth="match_parent"   androID:layout_height="match_parent" >  </ListVIEw> </com.yctc.drag.MylinearLayout></com.yctc.drag.DragLayout>


DragLayout.Java:

public class DragLayout extends FrameLayout { private static final String TAG = "TAG"; private VIEwDragHelper mDragHelper; private VIEwGroup mleftContent; private VIEwGroup mMainContent; private OnDragStatuschangelistener mListener; private Status mStatus = Status.Close; /**  * 状态枚举  */ public static enum Status {  Close,Open,Draging; } public interface OnDragStatuschangelistener{  voID onClose();  voID onopen();  voID onDraging(float percent); } public Status getStatus() {  return mStatus; } public voID setStatus(Status mStatus) {  this.mStatus = mStatus; } public voID setDragStatusListener(OnDragStatuschangelistener mListener){  this.mListener = mListener; } public DragLayout(Context context) {  this(context,null); } public DragLayout(Context context,AttributeSet attrs) {  this(context,attrs,0); } public DragLayout(Context context,AttributeSet attrs,int defStyle) {  super(context,defStyle);  // a.初始化 (通过静态方法)   mDragHelper = VIEwDragHelper.create(this,mCallback); } VIEwDragHelper.Callback mCallback = new VIEwDragHelper.Callback() {  // c. 重写事件  // 1. 根据返回结果决定当前child是否可以拖拽  // child 当前被拖拽的VIEw  // pointerID 区分多点触摸的ID  @OverrIDe  public boolean tryCaptureVIEw(VIEw child,int pointerID) {   Log.d(TAG,"tryCaptureVIEw: " + child);   return true;  };  @OverrIDe  public voID onVIEwCaptured(VIEw capturedChild,int activePointerID) {   Log.d(TAG,"onVIEwCaptured: " + capturedChild);   // 当capturedChild被捕获时,调用.   super.onVIEwCaptured(capturedChild,activePointerID);  }  @OverrIDe  public int getVIEwHorizontalDragRange(VIEw child) {   // 返回拖拽的范围,不对拖拽进行真正的限制. 仅仅决定了动画执行速度   return mRange;  }  // 2. 根据建议值 修正将要移动到的(横向)位置 (重要)  // 此时没有发生真正的移动  public int clampVIEwpositionHorizontal(VIEw child,int left,int dx) {   // child: 当前拖拽的VIEw   // left 新的位置的建议值,dx 位置变化量   // left = oldleft + dx;   Log.d(TAG,"clampVIEwpositionHorizontal: "      + "oldleft: " + child.getleft() + " dx: " + dx + " left: " +left);   if(child == mMainContent){    left = fixleft(left);   }   return left;  }  // 3. 当VIEw位置改变的时候,处理要做的事情 (更新状态,伴随动画,重绘界面)  // 此时,VIEw已经发生了位置的改变  @OverrIDe  public voID onVIEwpositionChanged(VIEw changedVIEw,int top,int dx,int dy) {   // changedVIEw 改变位置的VIEw   // left 新的左边值   // dx 水平方向变化量   super.onVIEwpositionChanged(changedVIEw,left,top,dx,dy);   Log.d(TAG,"onVIEwpositionChanged: " + "left: " + left + " dx: " + dx);   int newleft = left;   if(changedVIEw == mleftContent){    // 把当前变化量传递给mMainContent    newleft = mMainContent.getleft() + dx;   }   // 进行修正   newleft = fixleft(newleft);   if(changedVIEw == mleftContent) {    // 当左面板移动之后,再强制放回去.    mleftContent.layout(0,0 + mWIDth,0 + mHeight);    mMainContent.layout(newleft,newleft + mWIDth,0 + mHeight);   }   // 更新状态,执行动画   dispatchDragEvent(newleft);   // 为了兼容低版本,每次修改值之后,进行重绘   invalIDate();  }  // 4. 当VIEw被释放的时候,处理的事情(执行动画)  @OverrIDe  public voID onVIEwReleased(VIEw releasedChild,float xvel,float yvel) {   // VIEw releasedChild 被释放的子VIEw    // float xvel 水平方向的速度,向右为+   // float yvel 竖直方向的速度,向下为+   Log.d(TAG,"onVIEwReleased: " + "xvel: " + xvel + " yvel: " + yvel);   super.onVIEwReleased(releasedChild,xvel,yvel);   // 判断执行 关闭/开启   // 先考虑所有开启的情况,剩下的就都是关闭的情况   if(xvel == 0 && mMainContent.getleft() > mRange / 2.0f){    open();   }else if (xvel > 0) {    open();   }else {    close();   }  }  @OverrIDe  public voID onVIEwDragStateChanged(int state) {   // Todo auto-generated method stub   super.onVIEwDragStateChanged(state);  } }; /**  * 根据范围修正左边值  * @param left  * @return  */ private int fixleft(int left) {  if(left < 0){   return 0;  }else if (left > mRange) {   return mRange;  }  return left; } protected voID dispatchDragEvent(int newleft) {  float percent = newleft * 1.0f/ mRange;  //0.0f -> 1.0f  Log.d(TAG,"percent: " + percent);  if(mListener != null){   mListener.onDraging(percent);  }  // 更新状态,执行回调  Status preStatus = mStatus;  mStatus = updateStatus(percent);  if(mStatus != preStatus){   // 状态发生变化   if(mStatus == Status.Close){    // 当前变为关闭状态    if(mListener != null){     mListener.onClose();    }   }else if (mStatus == Status.Open) {    if(mListener != null){     mListener.onopen();    }   }  }//  * 伴随动画:  animVIEws(percent); } private Status updateStatus(float percent) {  if(percent == 0f){   return Status.Close;  }else if (percent == 1.0f) {   return Status.Open;  }  return Status.Draging; } private voID animVIEws(float percent) {  //  > 1. 左面板: 缩放动画,平移动画,透明度动画     // 缩放动画 0.0 -> 1.0 >>> 0.5f -> 1.0f >>> 0.5f * percent + 0.5f   //  mleftContent.setScaleX(0.5f + 0.5f * percent);   //  mleftContent.setScaleY(0.5f + 0.5f * percent);     VIEwHelper.setScaleX(mleftContent,evaluate(percent,0.5f,1.0f));     VIEwHelper.setScaleY(mleftContent,0.5f + 0.5f * percent);     // 平移动画: -mWIDth / 2.0f -> 0.0f     VIEwHelper.setTranslationX(mleftContent,-mWIDth / 2.0f,0));     // 透明度: 0.5 -> 1.0f     VIEwHelper.setAlpha(mleftContent,1.0f));  //  > 2. 主面板: 缩放动画     // 1.0f -> 0.8f     VIEwHelper.setScaleX(mMainContent,1.0f,0.8f));     VIEwHelper.setScaleY(mMainContent,0.8f));  //  > 3. 背景动画: 亮度变化 (颜色变化)     getBackground().setcolorFilter((Integer)evaluatecolor(percent,color.BLACK,color.@R_502_3318@),Mode.SRC_OVER); } /**  * 估值器  * @param fraction  * @param startValue  * @param endValue  * @return  */ public float evaluate(float fraction,Number startValue,Number endValue) {  float startfloat = startValue.floatValue();  return startfloat + fraction * (endValue.floatValue() - startfloat); } /**  * 颜色变化过度  * @param fraction  * @param startValue  * @param endValue  * @return  */ public Object evaluatecolor(float fraction,Object startValue,Object endValue) {  int startInt = (Integer) startValue;  int startA = (startInt >> 24) & 0xff;  int startR = (startInt >> 16) & 0xff;  int startG = (startInt >> 8) & 0xff;  int startB = startInt & 0xff;  int endInt = (Integer) endValue;  int endA = (endInt >> 24) & 0xff;  int endR = (endInt >> 16) & 0xff;  int endG = (endInt >> 8) & 0xff;  int endB = endInt & 0xff;  return (int)((startA + (int)(fraction * (endA - startA))) << 24) |    (int)((startR + (int)(fraction * (endR - startR))) << 16) |    (int)((startG + (int)(fraction * (endG - startG))) << 8) |    (int)((startB + (int)(fraction * (endB - startB)))); } @OverrIDe public voID computeScroll() {  super.computeScroll();  // 2. 持续平滑动画 (高频率调用)  if(mDragHelper.continueSettling(true)){   // 如果返回true,动画还需要继续执行   VIEwCompat.postInvalIDateOnAnimation(this);  } } public voID close(){  close(true); } /**  * 关闭  */ public voID close(boolean isSmooth) {  int finalleft = 0;  if(isSmooth){   // 1. 触发一个平滑动画   if(mDragHelper.smoothSlIDeVIEwTo(mMainContent,finalleft,0)){    // 返回true代表还没有移动到指定位置,需要刷新界面.    // 参数传this(child所在的VIEwGroup)    VIEwCompat.postInvalIDateOnAnimation(this);   }  }else {   mMainContent.layout(finalleft,finalleft + mWIDth,0 + mHeight);  } } public voID open(){  open(true); } /**  * 开启  */ public voID open(boolean isSmooth) {  int finalleft = mRange;  if(isSmooth){   // 1. 触发一个平滑动画   if(mDragHelper.smoothSlIDeVIEwTo(mMainContent,0 + mHeight);  } } private int mHeight; private int mWIDth; private int mRange; // b.传递触摸事件 @OverrIDe public boolean onIntercepttouchEvent(MotionEvent ev) {  // 传递给mDragHelper  return mDragHelper.shouldIntercepttouchEvent(ev); } @OverrIDe public boolean ontouchEvent(MotionEvent event) {  try {   mDragHelper.processtouchEvent(event);  } catch (Exception e) {   e.printstacktrace();  }  // 返回true,持续接受事件  return true; } @OverrIDe protected voID onFinishInflate() {  super.onFinishInflate();  // Github  // 写注释  // 容错性检查 (至少有俩子VIEw,子VIEw必须是VIEwGroup的子类)  if(getChildCount() < 2){   throw new IllegalStateException("布局至少有俩孩子. Your VIEwGroup must have 2 children at least.");  }  if(!(getChildAt(0) instanceof VIEwGroup && getChildAt(1) instanceof VIEwGroup)){   throw new IllegalArgumentException("子VIEw必须是VIEwGroup的子类. Your children must be an instance of VIEwGroup");  }  mleftContent = (VIEwGroup) getChildAt(0);  mMainContent = (VIEwGroup) getChildAt(1); } @OverrIDe protected voID onSizeChanged(int w,int h,int olDW,int oldh) {  super.onSizeChanged(w,h,olDW,oldh);  // 当尺寸有变化的时候调用  mHeight = getMeasuredHeight();  mWIDth = getMeasureDWIDth();  // 移动的范围  mRange = (int) (mWIDth * 0.6f); }}

MylineatLayout.java:

public class MylinearLayout extends linearLayout { private DragLayout mDragLayout; public MylinearLayout(Context context) {  super(context); } public MylinearLayout(Context context,AttributeSet attrs) {  super(context,attrs); } public voID setDraglayout(DragLayout mDragLayout){  this.mDragLayout = mDragLayout; } @OverrIDe public boolean onIntercepttouchEvent(MotionEvent ev) {  // 如果当前是关闭状态,按之前方法判断  if(mDragLayout.getStatus() == Status.Close){   return super.onIntercepttouchEvent(ev);  }else {   return true;  } } @OverrIDe public boolean ontouchEvent(MotionEvent event) {  // 如果当前是关闭状态,按之前方法处理  if(mDragLayout.getStatus() == Status.Close){   return super.ontouchEvent(event);  }else {   // 手指抬起,执行关闭 *** 作   if(event.getAction() == MotionEvent.ACTION_UP){    mDragLayout.close();   }   return true;  } }}

MainActivity.java:

public class MainActivity extends Activity { private static final String TAG = "TAG"; @OverrIDe protected voID onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  requestwindowFeature(Window.FEATURE_NO_Title);  setContentVIEw(R.layout.activity_main);  final ListVIEw mleftList = (ListVIEw) findVIEwByID(R.ID.lv_left);  final ListVIEw mMainList = (ListVIEw) findVIEwByID(R.ID.lv_main);  final ImageVIEw mheaderImage = (ImageVIEw) findVIEwByID(R.ID.iv_header);  MylinearLayout mlinearLayout = (MylinearLayout) findVIEwByID(R.ID.mll);  // 查找Draglayout,设置监听  DragLayout mDragLayout = (DragLayout) findVIEwByID(R.ID.dl);  // 设置引用  mlinearLayout.setDraglayout(mDragLayout);  mDragLayout.setDragStatusListener(new OnDragStatuschangelistener() {   @OverrIDe   public voID onopen() {    Utils.showToast(MainActivity.this,"onopen");    // 左面板ListVIEw随机设置一个条目    Random random = new Random();    int nextInt = random.nextInt(50);    mleftList.smoothScrollToposition(nextInt);   }   @OverrIDe   public voID onDraging(float percent) {    Log.d(TAG,"onDraging: " + percent);// 0 -> 1    // 更新图标的透明度    // 1.0 -> 0.0    VIEwHelper.setAlpha(mheaderImage,1 - percent);   }   @OverrIDe   public voID onClose() {    Utils.showToast(MainActivity.this,"onClose");    // 让图标晃动//    mheaderImage.setTranslationX(translationX)    ObjectAnimator mAnim = ObjectAnimator.offloat(mheaderImage,"translationX",15.0f);    mAnim.setInterpolator(new CycleInterpolator(4));    mAnim.setDuration(500);    mAnim.start();   }  });  mleftList.setAdapter(new ArrayAdapter<String>(this,androID.R.layout.simple_List_item_1,Cheeses.sCheeseStrings){   @OverrIDe   public VIEw getVIEw(int position,VIEw convertVIEw,VIEwGroup parent) {    VIEw vIEw = super.getVIEw(position,convertVIEw,parent);    TextVIEw mText = ((TextVIEw)vIEw);    mText.setTextcolor(color.WHITE);    return vIEw;   }  });  mMainList.setAdapter(new ArrayAdapter<String>(this,Cheeses.nameS))   }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的ViewDragHelper实现QQ侧滑效果全部内容,希望文章能够帮你解决ViewDragHelper实现QQ侧滑效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1144660.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存