侧拉删除

来源:互联网 发布:apache cxf 3.0.4下载 编辑:程序博客网 时间:2024/05/17 09:15

1.侧拉删除_实现滑动

 1.初始化ViewDragHelper----*

/** * 侧拉删除控件 * @author poplar * */public class SwipeLayout extends FrameLayout { public SwipeLayout(Context context) {this(context, null);}public SwipeLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);//a.初始化ViewDragHelpermDragHelper = ViewDragHelper.create(this, 1.0f, mCallback);}ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() { @Overridepublic boolean tryCaptureView(View view, int id) {return false;} } }


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

 // b. 传递触摸事件@Overridepublic boolean onInterceptTouchEvent(android.view.MotionEvent ev) {return mDragHelper.shouldInterceptTouchEvent(ev);};@Overridepublic boolean onTouchEvent(MotionEvent event) {try {mDragHelper.processTouchEvent(event);} catch (Exception e) {e.printStackTrace();}return true;}


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

(1)布局

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

<com.itheima.swipelayout.ui.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/sl"    android:layout_width="match_parent"    android:layout_height="60dp"    android:minHeight="60dp"    android:background="#44000000" >    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:orientation="horizontal" >        <TextView            android:id="@+id/tv_call"            android:layout_width="60dp"            android:layout_height="match_parent"            android:background="#666666"            android:gravity="center"            android:text="Call"            android:textColor="#ffffff" />        <TextView            android:id="@+id/tv_del"            android:layout_width="60dp"            android:layout_height="match_parent"            android:background="#ff0000"            android:gravity="center"            android:text="Delete"            android:textColor="#ffffff" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#44ffffff"        android:gravity="center_vertical"        android:orientation="horizontal" >        <ImageView            android:id="@+id/iv_image"            android:layout_width="40dp"            android:layout_height="40dp"            android:layout_marginLeft="15dp"            android:src="@drawable/head_1" />        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="15dp"            android:text="Name" />    </LinearLayout></com.itheima.swipelayout.ui.SwipeLayout>



(2)找到子View的ID

private View mBackView;private View mFrontView;   @Overrideprotected void onFinishInflate() {super.onFinishInflate();// 当xml被填充完毕时调用mBackView = getChildAt(0);mFrontView = getChildAt(1);}


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

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mHeight = mFrontView.getMeasuredHeight();mWidth = mFrontView.getMeasuredWidth();mRange = mBackView.getMeasuredWidth();}


(4)onLayout

@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);// 摆放位置layoutContent(false);}private void layoutContent(boolean isOpen) {// 摆放前View----前View的位置决定后View的位置Rect frontRect = computeFrontViewRect(isOpen);mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);// 摆放后ViewRect backRect = computeBackViewViaFront(frontRect);mBackView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom);// 调整顺序, 把mFrontView前置bringChildToFront(mFrontView);}//前View,用矩形封装位置    private Rect computeFrontViewRect(boolean isOpen) {int left = 0;if(isOpen){//打开left = -mRange;}//关闭return new Rect(left, 0, left + mWidth, 0 + mHeight);}//后View private Rect computeBackViewViaFront(Rect frontRect) {int left = frontRect.right;return new Rect(left, 0, left + mRange, 0 + mHeight);}


 

4.重写监听CallBack

(1)onViewPositionChanged-----callBack

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

     把后View的也传递给前View

     让两个View首尾相连

//因为后View隐藏了,不能拖拽,所以要把前View的偏移量传给后View//把后View的也传递给前View//让两个View首尾相连public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {// 传递事件if(changedView == mFrontView){mBackView.offsetLeftAndRight(dx);}else if (changedView == mBackView) {mFrontView.offsetLeftAndRight(dx);}//dispatchSwipeEvent();// 兼容老版本invalidate();};


 

 

2.侧拉删除_回调

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

// 限定移动范围public int clampViewPositionHorizontal(View child, int left, int dx) {// left    left代表控件的左上角横坐标if(child == mFrontView){if(left > 0){return 0;}else if(left < -mRange){return -mRange;}}else if (child == mBackView) {if(left > mWidth){return mWidth;}else if (left < mWidth - mRange) {return mWidth - mRange;}}return left;};


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

//当停止滑动时判断是否开启public void onViewReleased(View releasedChild, float xvel, float yvel) {            //速度为0if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) {open();}else if (xvel < 0) {//速度为负数,即向左滑动open();}else {//速度为正,即向右滑动close();}};


3.开启和关闭和动画

public void close() {Utils.showToast(getContext(), "Close");close(true);}public void close(boolean isSmooth){int finalLeft = 0;if(isSmooth){//是否平滑滑动//开始动画if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ViewCompat.postInvalidateOnAnimation(this);//界面重绘}}else {    //直接跳转layoutContent(false);}}public void open() {Utils.showToast(getContext(), "Open");open(true);}public void open(boolean isSmooth){int finalLeft = -mRange;if(isSmooth){//开始动画if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ViewCompat.postInvalidateOnAnimation(this);}}else {layoutContent(true);}}@Override//持续动画-----模板代码直接用public void computeScroll() {super.computeScroll();if(mDragHelper.continueSettling(true)){ViewCompat.postInvalidateOnAnimation(this);}}


4.回调监听

 (1)设定监听和状态

private Status status = Status.Close;private OnSwipeLayoutListener swipeLayoutListener;public Status getStatus() {return status;}public void setStatus(Status status) {this.status = status;}public OnSwipeLayoutListener getSwipeLayoutListener() {return swipeLayoutListener;}public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {this.swipeLayoutListener = swipeLayoutListener;}public static enum Status{Close, Open, Draging}public static interface OnSwipeLayoutListener {void onClose(SwipeLayout mSwipeLayout);void onOpen(SwipeLayout mSwipeLayout);void onDraging(SwipeLayout mSwipeLayout);// 要去关闭void onStartClose(SwipeLayout mSwipeLayout);// 要去开启void onStartOpen(SwipeLayout mSwipeLayout);}


(2)监听位置

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

public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {// 传递事件if(changedView == mFrontView){mBackView.offsetLeftAndRight(dx);}else if (changedView == mBackView) {mFrontView.offsetLeftAndRight(dx);}dispatchSwipeEvent();// 兼容老版本invalidate();};


(3)状态的判断和变化

protected void dispatchSwipeEvent() {if(swipeLayoutListener != null){swipeLayoutListener.onDraging(this);}// 记录上一次的状态Status preStatus = status;// 更新当前状态status = updateStatus();if (preStatus != status && swipeLayoutListener != null) {if (status == Status.Close) {swipeLayoutListener.onClose(this);} else if (status == Status.Open) {swipeLayoutListener.onOpen(this);} else if (status == Status.Draging) {if(preStatus == Status.Close){swipeLayoutListener.onStartOpen(this);}else if (preStatus == Status.Open) {swipeLayoutListener.onStartClose(this);}}}}private Status updateStatus() {int left = mFrontView.getLeft();if(left == 0){return Status.Close;}else if (left == -mRange) {return Status.Open;}return Status.Draging;}


 

 

 

3.侧拉删除_放入ListView

1.SwipeLayout完整

/** * 侧拉删除控件 * @author poplar * */public class SwipeLayout extends FrameLayout {private Status status = Status.Close;private OnSwipeLayoutListener swipeLayoutListener;public Status getStatus() {return status;}public void setStatus(Status status) {this.status = status;}public OnSwipeLayoutListener getSwipeLayoutListener() {return swipeLayoutListener;}public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {this.swipeLayoutListener = swipeLayoutListener;}public static enum Status{Close, Open, Draging}public static interface OnSwipeLayoutListener {void onClose(SwipeLayout mSwipeLayout);void onOpen(SwipeLayout mSwipeLayout);void onDraging(SwipeLayout mSwipeLayout);// 要去关闭void onStartClose(SwipeLayout mSwipeLayout);// 要去开启void onStartOpen(SwipeLayout mSwipeLayout);}public SwipeLayout(Context context) {this(context, null);}public SwipeLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mDragHelper = ViewDragHelper.create(this, 1.0f, mCallback);}ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {// c. 重写监听@Overridepublic boolean tryCaptureView(View view, int id) {return true;}// 限定移动范围public int clampViewPositionHorizontal(View child, int left, int dx) {// leftif(child == mFrontView){if(left > 0){return 0;}else if(left < -mRange){return -mRange;}}else if (child == mBackView) {if(left > mWidth){return mWidth;}else if (left < mWidth - mRange) {return mWidth - mRange;}}return left;};public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {// 传递事件if(changedView == mFrontView){mBackView.offsetLeftAndRight(dx);}else if (changedView == mBackView) {mFrontView.offsetLeftAndRight(dx);}dispatchSwipeEvent();// 兼容老版本invalidate();};public void onViewReleased(View releasedChild, float xvel, float yvel) {if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) {open();}else if (xvel < 0) {open();}else {close();}};};private ViewDragHelper mDragHelper;private View mBackView;private View mFrontView;private int mHeight;private int mWidth;private int mRange;// b. 传递触摸事件@Overridepublic boolean onInterceptTouchEvent(android.view.MotionEvent ev) {return mDragHelper.shouldInterceptTouchEvent(ev);};protected void dispatchSwipeEvent() {if(swipeLayoutListener != null){swipeLayoutListener.onDraging(this);}// 记录上一次的状态Status preStatus = status;// 更新当前状态status = updateStatus();if (preStatus != status && swipeLayoutListener != null) {if (status == Status.Close) {swipeLayoutListener.onClose(this);} else if (status == Status.Open) {swipeLayoutListener.onOpen(this);} else if (status == Status.Draging) {if(preStatus == Status.Close){swipeLayoutListener.onStartOpen(this);}else if (preStatus == Status.Open) {swipeLayoutListener.onStartClose(this);}}}}private Status updateStatus() {int left = mFrontView.getLeft();if(left == 0){return Status.Close;}else if (left == -mRange) {return Status.Open;}return Status.Draging;}public void close() {Utils.showToast(getContext(), "Close");close(true);}public void close(boolean isSmooth){int finalLeft = 0;if(isSmooth){//开始动画if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ViewCompat.postInvalidateOnAnimation(this);}}else {layoutContent(false);}}public void open() {Utils.showToast(getContext(), "Open");open(true);}public void open(boolean isSmooth){int finalLeft = -mRange;if(isSmooth){//开始动画if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ViewCompat.postInvalidateOnAnimation(this);}}else {layoutContent(true);}}@Overridepublic void computeScroll() {super.computeScroll();if(mDragHelper.continueSettling(true)){ViewCompat.postInvalidateOnAnimation(this);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {try {mDragHelper.processTouchEvent(event);} catch (Exception e) {e.printStackTrace();}return true;}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);// 摆放位置layoutContent(false);}private void layoutContent(boolean isOpen) {// 摆放前ViewRect frontRect = computeFrontViewRect(isOpen);mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);// 摆放后ViewRect backRect = computeBackViewViaFront(frontRect);mBackView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom);// 调整顺序, 把mFrontView前置bringChildToFront(mFrontView);}private Rect computeBackViewViaFront(Rect frontRect) {int left = frontRect.right;return new Rect(left, 0, left + mRange, 0 + mHeight);}private Rect computeFrontViewRect(boolean isOpen) {int left = 0;if(isOpen){left = -mRange;}return new Rect(left, 0, left + mWidth, 0 + mHeight);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();// 当xml被填充完毕时调用mBackView = getChildAt(0);mFrontView = getChildAt(1);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mHeight = mFrontView.getMeasuredHeight();mWidth = mFrontView.getMeasuredWidth();mRange = mBackView.getMeasuredWidth();}}


 

2.ListView 

(1)ListView中item布局

<?xml version="1.0" encoding="utf-8"?><com.itheima.swipelayout.ui.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/sl"    android:layout_width="match_parent"    android:layout_height="60dp"    android:minHeight="60dp"    android:background="#44000000" >    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:orientation="horizontal" >        <TextView            android:id="@+id/tv_call"            android:layout_width="60dp"            android:layout_height="match_parent"            android:background="#666666"            android:gravity="center"            android:text="Call"            android:textColor="#ffffff" />        <TextView            android:id="@+id/tv_del"            android:layout_width="60dp"            android:layout_height="match_parent"            android:background="#ff0000"            android:gravity="center"            android:text="Delete"            android:textColor="#ffffff" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#44ffffff"        android:gravity="center_vertical"        android:orientation="horizontal" >        <ImageView            android:id="@+id/iv_image"            android:layout_width="40dp"            android:layout_height="40dp"            android:layout_marginLeft="15dp"            android:src="@drawable/head_1" />        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="15dp"            android:text="Name" />    </LinearLayout></com.itheima.swipelayout.ui.SwipeLayout>


(2)MyAdapter

public class MyAdapter extends BaseAdapter {protected static final String TAG = "TAG";public MyAdapter(Context context) {super();this.context = context;opendItems = new ArrayList<SwipeLayout>();}private Context context;private ArrayList<SwipeLayout> opendItems;@Overridepublic int getCount() {return NAMES.length;}@Overridepublic Object getItem(int position) {return NAMES[position];}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = convertView;if(convertView == null){view = View.inflate(context, R.layout.item_list, null);}ViewHolder mHolder = ViewHolder.getHolder(view);SwipeLayout sl = (SwipeLayout)view;sl.setSwipeLayoutListener(new OnSwipeLayoutListener() {@Overridepublic void onStartOpen(SwipeLayout mSwipeLayout) {Log.d(TAG, "onStartOpen");// 要去开启时,先遍历所有已打开条目, 逐个关闭for (SwipeLayout layout : opendItems) {layout.close();}opendItems.clear();}@Overridepublic void onStartClose(SwipeLayout mSwipeLayout) {Log.d(TAG, "onStartClose");}@Overridepublic void onOpen(SwipeLayout mSwipeLayout) {Log.d(TAG, "onOpen");// 添加进集合opendItems.add(mSwipeLayout);}@Overridepublic void onDraging(SwipeLayout mSwipeLayout) {}@Overridepublic void onClose(SwipeLayout mSwipeLayout) {Log.d(TAG, "onClose");// 移除集合opendItems.remove(mSwipeLayout);}});return view;}static class ViewHolder {TextView tv_call;TextView tv_del;public static ViewHolder getHolder(View view) {Object tag = view.getTag();if(tag == null){ViewHolder viewHolder = new ViewHolder();viewHolder.tv_call = (TextView)view.findViewById(R.id.tv_call);viewHolder.tv_del = (TextView)view.findViewById(R.id.tv_del);tag = viewHolder;view.setTag(tag);}return (ViewHolder)tag;}}}


 

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

 

0 0
原创粉丝点击