侧拉删除
来源:互联网 发布: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
- 侧拉删除
- TableView侧拉删除
- 侧拉删除
- 侧拉删除
- 类 QQ 侧拉删除
- 仿QQ侧拉删除
- 自定义控件:侧拉删除
- 自定义侧拉删除(嵌套ListView)
- 自定义SwipeLayout侧拉删除控件
- Android开发之高仿QQ消息侧拉删除
- 侧滑删除,下拉刷新,上拉加载
- 条目的侧拉删除----仿照微信
- listview下拉刷新+上拉自动加载+侧滑删除
- 自定义侧拉删除(没有嵌套ListView)
- 鹅厂系列二 : 仿QQ侧拉删除
- 侧拉
- 侧拉
- 侧拉
- 关于laravel new no working一直卡着没反应问题
- 转换千分位显示
- Mozilla使用开源项目清单
- 05-树7 堆中的路径
- 【详解】Python统一解密改进版
- 侧拉删除
- Mysql自增异常
- mysql 重置 root 密码
- MYSQL my_print_defaults程序解析
- Android面试,IntentService的原理及使用
- linux安装nginx
- ECharts+百度地图网络拓扑图应用
- 网页乱码与设置utf-8乱码
- 金山云服务器,挂载硬盘