类 QQ 侧拉删除

1.侧拉删除_实现滑动

 1.初始化ViewDragHelper----*

[java]  view plain copy
  1. /** 
  2.  * 侧拉删除控件 
  3.  * @author poplar 
  4.  * 
  5.  */  
  6. public class SwipeLayout extends FrameLayout {  
  7.    
  8.     public SwipeLayout(Context context) {  
  9.         this(context, null);  
  10.     }  
  11.   
  12.     public SwipeLayout(Context context, AttributeSet attrs) {  
  13.         this(context, attrs, 0);  
  14.     }  
  15.   
  16.     public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {  
  17.         super(context, attrs, defStyle);  
  18.         //a.初始化ViewDragHelper  
  19.         mDragHelper = ViewDragHelper.create(this1.0f, mCallback);  
  20.     }  
  21.     ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {  
  22.            
  23.         @Override  
  24.         public boolean tryCaptureView(View view, int id) {  
  25.             return false;  
  26.         }  
  27.      }  
  28.      }  


2.传递触摸事件---*

[java]  view plain copy
  1.  // b. 传递触摸事件  
  2. @Override  
  3. public boolean onInterceptTouchEvent(android.view.MotionEvent ev) {  
  4.     return mDragHelper.shouldInterceptTouchEvent(ev);  
  5. };  
  6.   
  7. @Override  
  8. public boolean onTouchEvent(MotionEvent event) {  
  9.       
  10.     try {  
  11.         mDragHelper.processTouchEvent(event);  
  12.     } catch (Exception e) {  
  13.         e.printStackTrace();  
  14.     }  
  15.       
  16.     return true;  
  17. }  


3.通过layout方法把布局放在某个位置

(1)布局

     Button会拦截触摸事件,所以使用TextView

[html]  view plain copy
  1. <com.itheima.swipelayout.ui.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:id="@+id/sl"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="60dp"  
  5.     android:minHeight="60dp"  
  6.     android:background="#44000000" >  
  7.   
  8.     <LinearLayout  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="match_parent"  
  11.         android:orientation="horizontal" >  
  12.   
  13.         <TextView  
  14.             android:id="@+id/tv_call"  
  15.             android:layout_width="60dp"  
  16.             android:layout_height="match_parent"  
  17.             android:background="#666666"  
  18.             android:gravity="center"  
  19.             android:text="Call"  
  20.             android:textColor="#ffffff" />  
  21.   
  22.         <TextView  
  23.             android:id="@+id/tv_del"  
  24.             android:layout_width="60dp"  
  25.             android:layout_height="match_parent"  
  26.             android:background="#ff0000"  
  27.             android:gravity="center"  
  28.             android:text="Delete"  
  29.             android:textColor="#ffffff" />  
  30.     </LinearLayout>  
  31.   
  32.     <LinearLayout  
  33.         android:layout_width="match_parent"  
  34.         android:layout_height="match_parent"  
  35.         android:background="#44ffffff"  
  36.         android:gravity="center_vertical"  
  37.         android:orientation="horizontal" >  
  38.   
  39.         <ImageView  
  40.             android:id="@+id/iv_image"  
  41.             android:layout_width="40dp"  
  42.             android:layout_height="40dp"  
  43.             android:layout_marginLeft="15dp"  
  44.             android:src="@drawable/head_1" />  
  45.   
  46.         <TextView  
  47.             android:id="@+id/tv_name"  
  48.             android:layout_width="wrap_content"  
  49.             android:layout_height="wrap_content"  
  50.             android:layout_marginLeft="15dp"  
  51.             android:text="Name" />  
  52.     </LinearLayout>  
  53.   
  54. </com.itheima.swipelayout.ui.SwipeLayout>  



(2)找到子View的ID

[java]  view plain copy
  1. private View mBackView;  
  2.     private View mFrontView;  
  3.     @Override  
  4.     protected void onFinishInflate() {  
  5.         super.onFinishInflate();  
  6.         // 当xml被填充完毕时调用  
  7.         mBackView = getChildAt(0);  
  8.         mFrontView = getChildAt(1);  
  9.     }  


(3)获得控件宽高,可以在onMeasure方法中获得,最好在onSizeChanged方法

[java]  view plain copy
  1. @Override  
  2. protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  3.     super.onSizeChanged(w, h, oldw, oldh);  
  4.       
  5.     mHeight = mFrontView.getMeasuredHeight();  
  6.     mWidth = mFrontView.getMeasuredWidth();  
  7.       
  8.     mRange = mBackView.getMeasuredWidth();  
  9.       
  10. }  


(4)onLayout

[java]  view plain copy
  1. @Override  
  2.     protected void onLayout(boolean changed, int left, int top, int right,  
  3.             int bottom) {  
  4.         super.onLayout(changed, left, top, right, bottom);  
  5.         // 摆放位置  
  6.         layoutContent(false);  
  7.     }  
  8.       
  9.     private void layoutContent(boolean isOpen) {  
  10.         // 摆放前View----前View的位置决定后View的位置  
  11.         Rect frontRect = computeFrontViewRect(isOpen);  
  12.         mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);  
  13.         // 摆放后View  
  14.         Rect backRect = computeBackViewViaFront(frontRect);  
  15.         mBackView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom);  
  16.           
  17.         // 调整顺序, 把mFrontView前置  
  18.         bringChildToFront(mFrontView);  
  19.     }  
  20.       
  21.     //前View,用矩形封装位置  
  22.     private Rect computeFrontViewRect(boolean isOpen) {  
  23.         int left = 0;  
  24.         if(isOpen){//打开  
  25.             left = -mRange;  
  26.         }  
  27.         //关闭  
  28.         return new Rect(left, 0, left + mWidth, 0 + mHeight);  
  29.     }  
  30.       
  31.     //后View  
  32.      private Rect computeBackViewViaFront(Rect frontRect) {  
  33.         int left = frontRect.right;  
  34.         return new Rect(left, 0, left + mRange, 0 + mHeight);  
  35.     }  


 

4.重写监听CallBack

(1)onViewPositionChanged-----callBack

     因为后View隐藏了,不能拖拽,所以要把前View的偏移量传给后View

     把后View的也传递给前View

     让两个View首尾相连

[java]  view plain copy
  1. //因为后View隐藏了,不能拖拽,所以要把前View的偏移量传给后View  
  2.         //把后View的也传递给前View  
  3.         //让两个View首尾相连  
  4.         public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {  
  5.               
  6.             // 传递事件  
  7.             if(changedView == mFrontView){  
  8.                 mBackView.offsetLeftAndRight(dx);  
  9.             }else if (changedView == mBackView) {  
  10.                 mFrontView.offsetLeftAndRight(dx);  
  11.             }  
  12.               
  13.             //dispatchSwipeEvent();  
  14.               
  15.             // 兼容老版本  
  16.             invalidate();  
  17.               
  18.         };  


 

 

2.侧拉删除_回调

1.限定滑动范围--------CallBack中

[java]  view plain copy
  1. // 限定移动范围  
  2.         public int clampViewPositionHorizontal(View child, int left, int dx) {  
  3.               
  4.             // left    left代表控件的左上角横坐标  
  5.             if(child == mFrontView){  
  6.                 if(left > 0){  
  7.                     return 0;  
  8.                 }else if(left < -mRange){  
  9.                     return -mRange;  
  10.                 }  
  11.             }else if (child == mBackView) {  
  12.                 if(left > mWidth){  
  13.                     return mWidth;  
  14.                 }else if (left < mWidth - mRange) {  
  15.                     return mWidth - mRange;  
  16.                 }  
  17.             }  
  18.             return left;  
  19.         };  


2.当停止滑动时判断是否开启-------------CallBack中

[java]  view plain copy
  1. //当停止滑动时判断是否开启  
  2. public void onViewReleased(View releasedChild, float xvel, float yvel) {  
  3.           //速度为0  
  4.     if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) {  
  5.         open();  
  6.     }else if (xvel < 0) {//速度为负数,即向左滑动  
  7.         open();  
  8.     }else {//速度为正,即向右滑动  
  9.         close();  
  10.     }  
  11.   
  12. };  


3.开启和关闭和动画

[java]  view plain copy
  1. public void close() {  
  2.         Utils.showToast(getContext(), "Close");  
  3.         close(true);  
  4.     }  
  5.     public void close(boolean isSmooth){  
  6.         int finalLeft = 0;  
  7.         if(isSmooth){//是否平滑滑动  
  8.             //开始动画  
  9.             if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){  
  10.                 ViewCompat.postInvalidateOnAnimation(this);//界面重绘  
  11.             }  
  12.         }else {  
  13.             //直接跳转  
  14.             layoutContent(false);  
  15.         }  
  16.     }  
  17.   
  18.     public void open() {  
  19.         Utils.showToast(getContext(), "Open");  
  20.         open(true);  
  21.     }  
  22.     public void open(boolean isSmooth){  
  23.         int finalLeft = -mRange;  
  24.         if(isSmooth){  
  25.             //开始动画  
  26.             if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){  
  27.                 ViewCompat.postInvalidateOnAnimation(this);  
  28.             }  
  29.         }else {  
  30.             layoutContent(true);  
  31.         }  
  32.     }  
  33.       
  34.     @Override  
  35.     //持续动画-----模板代码直接用  
  36.     public void computeScroll() {  
  37.         super.computeScroll();  
  38.           
  39.         if(mDragHelper.continueSettling(true)){  
  40.             ViewCompat.postInvalidateOnAnimation(this);  
  41.         }  
  42.           
  43.     }  


4.回调监听

 (1)设定监听和状态

[java]  view plain copy
  1. private Status status = Status.Close;  
  2. private OnSwipeLayoutListener swipeLayoutListener;  
  3.   
  4. public Status getStatus() {  
  5.     return status;  
  6. }  
  7.   
  8. public void setStatus(Status status) {  
  9.     this.status = status;  
  10. }  
  11.   
  12. public OnSwipeLayoutListener getSwipeLayoutListener() {  
  13.     return swipeLayoutListener;  
  14. }  
  15.   
  16. public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {  
  17.     this.swipeLayoutListener = swipeLayoutListener;  
  18. }  
  19.   
  20. public static enum Status{  
  21.     Close, Open, Draging  
  22. }  
  23. public static interface OnSwipeLayoutListener {  
  24.       
  25.     void onClose(SwipeLayout mSwipeLayout);  
  26.     void onOpen(SwipeLayout mSwipeLayout);  
  27.     void onDraging(SwipeLayout mSwipeLayout);  
  28.     // 要去关闭  
  29.     void onStartClose(SwipeLayout mSwipeLayout);  
  30.     // 要去开启  
  31.     void onStartOpen(SwipeLayout mSwipeLayout);  
  32. }  


(2)监听位置

     onViewPositionChanged方法:每次界面变化都会调用,高频调用dispatchSwipeEvent

[java]  view plain copy
  1. public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {  
  2.               
  3.             // 传递事件  
  4.             if(changedView == mFrontView){  
  5.                 mBackView.offsetLeftAndRight(dx);  
  6.             }else if (changedView == mBackView) {  
  7.                 mFrontView.offsetLeftAndRight(dx);  
  8.             }  
  9.               
  10.             dispatchSwipeEvent();  
  11.               
  12.             // 兼容老版本  
  13.             invalidate();  
  14.               
  15.         };  


(3)状态的判断和变化

[java]  view plain copy
  1. protected void dispatchSwipeEvent() {  
  2.           
  3.         if(swipeLayoutListener != null){  
  4.             swipeLayoutListener.onDraging(this);  
  5.         }  
  6.           
  7.         // 记录上一次的状态  
  8.         Status preStatus = status;  
  9.         // 更新当前状态  
  10.         status = updateStatus();  
  11.         if (preStatus != status && swipeLayoutListener != null) {  
  12.             if (status == Status.Close) {  
  13.                 swipeLayoutListener.onClose(this);  
  14.             } else if (status == Status.Open) {  
  15.                 swipeLayoutListener.onOpen(this);  
  16.             } else if (status == Status.Draging) {  
  17.                 if(preStatus == Status.Close){  
  18.                     swipeLayoutListener.onStartOpen(this);  
  19.                 }else if (preStatus == Status.Open) {  
  20.                     swipeLayoutListener.onStartClose(this);  
  21.                 }  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     private Status updateStatus() {  
  27.           
  28.         int left = mFrontView.getLeft();  
  29.         if(left == 0){  
  30.             return Status.Close;  
  31.         }else if (left == -mRange) {  
  32.             return Status.Open;  
  33.         }  
  34.         return Status.Draging;  
  35.     }  


 

 

 

3.侧拉删除_放入ListView

1.SwipeLayout完整

[java]  view plain copy
  1. /** 
  2.  * 侧拉删除控件 
  3.  * @author poplar 
  4.  * 
  5.  */  
  6. public class SwipeLayout extends FrameLayout {  
  7.     private Status status = Status.Close;  
  8.     private OnSwipeLayoutListener swipeLayoutListener;  
  9.       
  10.     public Status getStatus() {  
  11.         return status;  
  12.     }  
  13.   
  14.     public void setStatus(Status status) {  
  15.         this.status = status;  
  16.     }  
  17.   
  18.     public OnSwipeLayoutListener getSwipeLayoutListener() {  
  19.         return swipeLayoutListener;  
  20.     }  
  21.   
  22.     public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {  
  23.         this.swipeLayoutListener = swipeLayoutListener;  
  24.     }  
  25.   
  26.     public static enum Status{  
  27.         Close, Open, Draging  
  28.     }  
  29.     public static interface OnSwipeLayoutListener {  
  30.           
  31.         void onClose(SwipeLayout mSwipeLayout);  
  32.         void onOpen(SwipeLayout mSwipeLayout);  
  33.         void onDraging(SwipeLayout mSwipeLayout);  
  34.         // 要去关闭  
  35.         void onStartClose(SwipeLayout mSwipeLayout);  
  36.         // 要去开启  
  37.         void onStartOpen(SwipeLayout mSwipeLayout);  
  38.     }  
  39.       
  40.     public SwipeLayout(Context context) {  
  41.         this(context, null);  
  42.     }  
  43.   
  44.     public SwipeLayout(Context context, AttributeSet attrs) {  
  45.         this(context, attrs, 0);  
  46.     }  
  47.   
  48.     public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {  
  49.         super(context, attrs, defStyle);  
  50.           
  51.         mDragHelper = ViewDragHelper.create(this1.0f, mCallback);  
  52.     }  
  53.     ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {  
  54.         // c. 重写监听  
  55.         @Override  
  56.         public boolean tryCaptureView(View view, int id) {  
  57.             return true;  
  58.         }  
  59.           
  60.         // 限定移动范围  
  61.         public int clampViewPositionHorizontal(View child, int left, int dx) {  
  62.               
  63.             // left  
  64.             if(child == mFrontView){  
  65.                 if(left > 0){  
  66.                     return 0;  
  67.                 }else if(left < -mRange){  
  68.                     return -mRange;  
  69.                 }  
  70.             }else if (child == mBackView) {  
  71.                 if(left > mWidth){  
  72.                     return mWidth;  
  73.                 }else if (left < mWidth - mRange) {  
  74.                     return mWidth - mRange;  
  75.                 }  
  76.             }  
  77.             return left;  
  78.         };  
  79.           
  80.         public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {  
  81.               
  82.             // 传递事件  
  83.             if(changedView == mFrontView){  
  84.                 mBackView.offsetLeftAndRight(dx);  
  85.             }else if (changedView == mBackView) {  
  86.                 mFrontView.offsetLeftAndRight(dx);  
  87.             }  
  88.               
  89.             dispatchSwipeEvent();  
  90.               
  91.             // 兼容老版本  
  92.             invalidate();  
  93.               
  94.         };  
  95.           
  96.         public void onViewReleased(View releasedChild, float xvel, float yvel) {  
  97.   
  98.             if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) {  
  99.                 open();  
  100.             }else if (xvel < 0) {  
  101.                 open();  
  102.             }else {  
  103.                 close();  
  104.             }  
  105.   
  106.         };  
  107.           
  108.     };  
  109.     private ViewDragHelper mDragHelper;  
  110.     private View mBackView;  
  111.     private View mFrontView;  
  112.     private int mHeight;  
  113.     private int mWidth;  
  114.     private int mRange;  
  115.       
  116.     // b. 传递触摸事件  
  117.     @Override  
  118.     public boolean onInterceptTouchEvent(android.view.MotionEvent ev) {  
  119.         return mDragHelper.shouldInterceptTouchEvent(ev);  
  120.     };  
  121.       
  122.     protected void dispatchSwipeEvent() {  
  123.           
  124.         if(swipeLayoutListener != null){  
  125.             swipeLayoutListener.onDraging(this);  
  126.         }  
  127.           
  128.         // 记录上一次的状态  
  129.         Status preStatus = status;  
  130.         // 更新当前状态  
  131.         status = updateStatus();  
  132.         if (preStatus != status && swipeLayoutListener != null) {  
  133.             if (status == Status.Close) {  
  134.                 swipeLayoutListener.onClose(this);  
  135.             } else if (status == Status.Open) {  
  136.                 swipeLayoutListener.onOpen(this);  
  137.             } else if (status == Status.Draging) {  
  138.                 if(preStatus == Status.Close){  
  139.                     swipeLayoutListener.onStartOpen(this);  
  140.                 }else if (preStatus == Status.Open) {  
  141.                     swipeLayoutListener.onStartClose(this);  
  142.                 }  
  143.             }  
  144.         }  
  145.     }  
  146.   
  147.     private Status updateStatus() {  
  148.           
  149.         int left = mFrontView.getLeft();  
  150.         if(left == 0){  
  151.             return Status.Close;  
  152.         }else if (left == -mRange) {  
  153.             return Status.Open;  
  154.         }  
  155.         return Status.Draging;  
  156.     }  
  157.   
  158.     public void close() {  
  159.         Utils.showToast(getContext(), "Close");  
  160.         close(true);  
  161.     }  
  162.     public void close(boolean isSmooth){  
  163.         int finalLeft = 0;  
  164.         if(isSmooth){  
  165.             //开始动画  
  166.             if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){  
  167.                 ViewCompat.postInvalidateOnAnimation(this);  
  168.             }  
  169.         }else {  
  170.             layoutContent(false);  
  171.         }  
  172.     }  
  173.   
  174.     public void open() {  
  175.         Utils.showToast(getContext(), "Open");  
  176.         open(true);  
  177.     }  
  178.     public void open(boolean isSmooth){  
  179.         int finalLeft = -mRange;  
  180.         if(isSmooth){  
  181.             //开始动画  
  182.             if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){  
  183.                 ViewCompat.postInvalidateOnAnimation(this);  
  184.             }  
  185.         }else {  
  186.             layoutContent(true);  
  187.         }  
  188.     }  
  189.       
  190.     @Override  
  191.     public void computeScroll() {  
  192.         super.computeScroll();  
  193.           
  194.         if(mDragHelper.continueSettling(true)){  
  195.             ViewCompat.postInvalidateOnAnimation(this);  
  196.         }  
  197.           
  198.     }  
  199.   
  200.     @Override  
  201.     public boolean onTouchEvent(MotionEvent event) {  
  202.           
  203.         try {  
  204.             mDragHelper.processTouchEvent(event);  
  205.         } catch (Exception e) {  
  206.             e.printStackTrace();  
  207.         }  
  208.           
  209.         return true;  
  210.     }  
  211.       
  212.     @Override  
  213.     protected void onLayout(boolean changed, int left, int top, int right,  
  214.             int bottom) {  
  215.         super.onLayout(changed, left, top, right, bottom);  
  216.         // 摆放位置  
  217.         layoutContent(false);  
  218.     }  
  219.       
  220.     private void layoutContent(boolean isOpen) {  
  221.         // 摆放前View  
  222.         Rect frontRect = computeFrontViewRect(isOpen);  
  223.         mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);  
  224.         // 摆放后View  
  225.         Rect backRect = computeBackViewViaFront(frontRect);  
  226.         mBackView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom);  
  227.           
  228.         // 调整顺序, 把mFrontView前置  
  229.         bringChildToFront(mFrontView);  
  230.     }  
  231.   
  232.     private Rect computeBackViewViaFront(Rect frontRect) {  
  233.         int left = frontRect.right;  
  234.         return new Rect(left, 0, left + mRange, 0 + mHeight);  
  235.     }  
  236.   
  237.     private Rect computeFrontViewRect(boolean isOpen) {  
  238.         int left = 0;  
  239.         if(isOpen){  
  240.             left = -mRange;  
  241.         }  
  242.         return new Rect(left, 0, left + mWidth, 0 + mHeight);  
  243.     }  
  244.   
  245.     @Override  
  246.     protected void onFinishInflate() {  
  247.         super.onFinishInflate();  
  248.         // 当xml被填充完毕时调用  
  249.         mBackView = getChildAt(0);  
  250.         mFrontView = getChildAt(1);  
  251.     }  
  252.       
  253.     @Override  
  254.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  255.         super.onSizeChanged(w, h, oldw, oldh);  
  256.           
  257.         mHeight = mFrontView.getMeasuredHeight();  
  258.         mWidth = mFrontView.getMeasuredWidth();  
  259.           
  260.         mRange = mBackView.getMeasuredWidth();  
  261.           
  262.     }  
  263.   
  264. }  


 

2.ListView 

(1)ListView中item布局

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <com.itheima.swipelayout.ui.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/sl"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="60dp"  
  6.     android:minHeight="60dp"  
  7.     android:background="#44000000" >  
  8.   
  9.     <LinearLayout  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="match_parent"  
  12.         android:orientation="horizontal" >  
  13.   
  14.         <TextView  
  15.             android:id="@+id/tv_call"  
  16.             android:layout_width="60dp"  
  17.             android:layout_height="match_parent"  
  18.             android:background="#666666"  
  19.             android:gravity="center"  
  20.             android:text="Call"  
  21.             android:textColor="#ffffff" />  
  22.   
  23.         <TextView  
  24.             android:id="@+id/tv_del"  
  25.             android:layout_width="60dp"  
  26.             android:layout_height="match_parent"  
  27.             android:background="#ff0000"  
  28.             android:gravity="center"  
  29.             android:text="Delete"  
  30.             android:textColor="#ffffff" />  
  31.     </LinearLayout>  
  32.   
  33.     <LinearLayout  
  34.         android:layout_width="match_parent"  
  35.         android:layout_height="match_parent"  
  36.         android:background="#44ffffff"  
  37.         android:gravity="center_vertical"  
  38.         android:orientation="horizontal" >  
  39.   
  40.         <ImageView  
  41.             android:id="@+id/iv_image"  
  42.             android:layout_width="40dp"  
  43.             android:layout_height="40dp"  
  44.             android:layout_marginLeft="15dp"  
  45.             android:src="@drawable/head_1" />  
  46.   
  47.         <TextView  
  48.             android:id="@+id/tv_name"  
  49.             android:layout_width="wrap_content"  
  50.             android:layout_height="wrap_content"  
  51.             android:layout_marginLeft="15dp"  
  52.             android:text="Name" />  
  53.     </LinearLayout>  
  54.   
  55. </com.itheima.swipelayout.ui.SwipeLayout>  


(2)MyAdapter

[java]  view plain copy
  1. public class MyAdapter extends BaseAdapter {  
  2.   
  3.     protected static final String TAG = "TAG";  
  4.   
  5.   
  6.     public MyAdapter(Context context) {  
  7.         super();  
  8.         this.context = context;  
  9.           
  10.         opendItems = new ArrayList<SwipeLayout>();  
  11.     }  
  12.   
  13.     private Context context;  
  14.     private ArrayList<SwipeLayout> opendItems;  
  15.       
  16.     @Override  
  17.     public int getCount() {  
  18.         return NAMES.length;  
  19.     }  
  20.   
  21.     @Override  
  22.     public Object getItem(int position) {  
  23.         return NAMES[position];  
  24.     }  
  25.   
  26.     @Override  
  27.     public long getItemId(int position) {  
  28.         // TODO Auto-generated method stub  
  29.         return position;  
  30.     }  
  31.   
  32.     @Override  
  33.     public View getView(int position, View convertView, ViewGroup parent) {  
  34.           
  35.         View view = convertView;  
  36.         if(convertView == null){  
  37.             view = View.inflate(context, R.layout.item_list, null);  
  38.               
  39.         }  
  40.         ViewHolder mHolder = ViewHolder.getHolder(view);  
  41.           
  42.         SwipeLayout sl = (SwipeLayout)view;  
  43.         sl.setSwipeLayoutListener(new OnSwipeLayoutListener() {  
  44.               
  45.             @Override  
  46.             public void onStartOpen(SwipeLayout mSwipeLayout) {  
  47.                 Log.d(TAG, "onStartOpen");  
  48.   
  49.                 // 要去开启时,先遍历所有已打开条目, 逐个关闭  
  50.                   
  51.                 for (SwipeLayout layout : opendItems) {  
  52.                     layout.close();  
  53.                 }  
  54.                   
  55.                 opendItems.clear();  
  56.             }  
  57.               
  58.             @Override  
  59.             public void onStartClose(SwipeLayout mSwipeLayout) {  
  60.                 Log.d(TAG, "onStartClose");  
  61.             }  
  62.               
  63.             @Override  
  64.             public void onOpen(SwipeLayout mSwipeLayout) {  
  65.                 Log.d(TAG, "onOpen");  
  66.                 // 添加进集合  
  67.                 opendItems.add(mSwipeLayout);  
  68.             }  
  69.             @Override  
  70.             public void onDraging(SwipeLayout mSwipeLayout) {  
  71.             }  
  72.               
  73.             @Override  
  74.             public void onClose(SwipeLayout mSwipeLayout) {  
  75.                 Log.d(TAG, "onClose");  
  76.                 // 移除集合  
  77.                 opendItems.remove(mSwipeLayout);  
  78.             }  
  79.         });  
  80.         return view;  
  81.     }  
  82.       
  83.     static class ViewHolder {  
  84.         TextView tv_call;  
  85.         TextView tv_del;  
  86.   
  87.         public static ViewHolder getHolder(View view) {  
  88.             Object tag = view.getTag();  
  89.             if(tag == null){  
  90.                 ViewHolder viewHolder = new ViewHolder();  
  91.                 viewHolder.tv_call = (TextView)view.findViewById(R.id.tv_call);  
  92.                 viewHolder.tv_del = (TextView)view.findViewById(R.id.tv_del);  
  93.                 tag = viewHolder;  
  94.                 view.setTag(tag);  
  95.             }  
  96.             return (ViewHolder)tag;  
  97.         }  
  98.     }  
  99.   
  100. }  

以上主要主要摘自http://blog.csdn.net/u012360634/article/details/49663557
 

优化:监听ListView滚动时关闭所有打开的

接下来是原创解决方法

1.解决listview的上下拉动和自定义view的左右拉动时的事件冲突

在自定义view初始化的时候,也初始化手势监听器

      public leftDeleteView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// a.初始化
		viewDragHelper = ViewDragHelper.create(this, 1.0f, mCallback);
		gestureDetector = new GestureDetector(context, getstureListener);
	}

	GestureDetector.SimpleOnGestureListener getstureListener = new GestureDetector.SimpleOnGestureListener() {
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			// 当横向移动距离大于等于纵向时,返回true
			return Math.abs(distanceX) >= Math.abs(distanceY);
		}
	};
然后在onInterceptTouchEvent中根据上下和左右的位移差来判断是否对触摸事件进行拦截

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// 决定当前的SwipeLayout是否要把touch事件拦截下来,直接交由自己的onTouchEvent处理
		// 返回true则为拦截
		return viewDragHelper.shouldInterceptTouchEvent(ev) & gestureDetector.onTouchEvent(ev);
	}
如果返回的时true的话,那么就会进入该view的 onTouchEvent方法中,我们再在这个方法中 上下和左右的位移差判断是否响应触摸事件

@Override
	public boolean onTouchEvent(MotionEvent event) {

		// 当处理touch事件时,不希望被父类onInterceptTouchEvent的代码所影响。
		// 比如处理向右滑动关闭已打开的条目时,如果进行以下逻辑,则不会在关闭的同时引发左边菜单的打开。

		switch (MotionEventCompat.getActionMasked(event)) {
		case MotionEvent.ACTION_DOWN:
			mDownX = event.getRawX();
			break;
		case MotionEvent.ACTION_MOVE:

			float deltaX = event.getRawX() - mDownX;
			//viewDragHelper.getTouchSlop()//viewDragHelper向上滑动的距离
			//Log.i("xuqunxing", "deltaX:"+deltaX+",heigh:"+ viewDragHelper.getTouchSlop());
			if (Math.abs(deltaX)> viewDragHelper.getTouchSlop()) {
				Log.i("xuqunxing", "requestDisallowInterceptTouchEvent");
				// 请求父级View不拦截touch事件
				requestDisallowInterceptTouchEvent(true);
			}
			break;
		case MotionEvent.ACTION_UP:
			mDownX = 0;
		default:
			break;
		}
		viewDragHelper.processTouchEvent(event);
		return true;// 设置为true才能触摸到,才能拖动
	}
这样就解决了,源码地址:http://download.csdn.net/detail/iblue007/9369406

最后上图

类 QQ 侧拉删除_第1张图片





你可能感兴趣的:(类 QQ 侧拉删除)