ListView侧滑删除的实现,SlideDeleteListView,针对ScrollView嵌套ListView视图和手势冲突优化
来源:互联网 发布:撕名牌衣服淘宝网 编辑:程序博客网 时间:2024/04/26 03:31
1.先假设一个ListView的Item子布局message_item.xml是这样的:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="62dp" android:background="@drawable/common_list_item_bg" android:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeight" android:orientation="horizontal"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_icon_read_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="15dp" android:src="@drawable/ic_msg_unread" /> <TextView android:id="@+id/tv_msg_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="15dp" android:layout_toRightOf="@id/iv_icon_read_status" android:text="订单预定成功;订单号6607967" android:textColor="@color/common_text" android:textSize="14sp" /> <TextView android:id="@+id/tv_msg_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="15dp" android:text="前天 13:21" android:textColor="@color/text_smoke" android:textSize="12sp" /> </RelativeLayout> <TextView android:id="@+id/tv_btn_delete" android:layout_width="70dp" android:layout_height="match_parent" android:background="@color/red" android:clickable="true" android:gravity="center" android:text="删除" android:textColor="@color/white" android:textSize="17sp" /></LinearLayout>前面的RelativeLayout里的内容就是大家常见的ListView的Item视图,后面的TextView就是我们主角删除按钮,这里把它也作为Item的子布局内容了。从布局里可以看出,删除按钮TextView已经被RelativeLayout挤到最右边,而不在屏幕显示区域内。此时该Item的长度实际长度是屏幕的长度+删除的按钮的长度(这里是70dp)。
2.下面我们自定义ListView----->SlideDeleteListView 这里注意一点,就是尽量不要在任何自定义View中传入某布局,那么以后修改或用于别的项目,其要求发生了一些变化,还要针对被改变的布局修改逻辑代码,这是我个人的一种开发思想,大家听听就好了。
/** * 构造方法,实例化入口,初始化相关数据或实例 * * @param context * @param attrs * @param defStyleAttr */public SlideDeleteListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);// 窗口管理器WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);// 新建显示度量尺DisplayMetrics metrics = new DisplayMetrics();// 对度量尺进行包装,附参wm.getDefaultDisplay().getMetrics(metrics);// 初始化屏幕宽度参数mSreeenWidth = metrics.widthPixels;}
SlideDeleteListView构造方法中获取屏幕宽度mSreeenWidth
/** * 手势操作 * * @param ev * @return */@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:// 按压onActionDowm(ev);break;case MotionEvent.ACTION_MOVE:// 移动return onActionMove(ev);case MotionEvent.ACTION_UP:// 释放onActionUp(ev);break;}return super.onTouchEvent(ev);}重写SlideDeleteListView手势事件
/** * 手指按下逻辑 */private void onActionDowm(MotionEvent e) {if (isBtnDelShow) {resetItemView();}mDownX = (int) e.getX();mDownY = (int) e.getY();// 获得被按下位置的itemInteger currentPosition = pointToPosition(mDownX, mDownY);if (-1 == currentPosition) {return;}itemViewGroup = (ViewGroup) getChildAt(currentPosition - getFirstVisiblePosition());// 获得删除按钮的宽度,删除按钮属于第二个子View(上述布局中能看得出来),position为1mBtnDelWidth = itemViewGroup.getChildAt(1).getLayoutParams().width;/* 将第一个子View也就是我们常见的Item显示的View的宽固定为屏幕同宽度 */params = (LinearLayout.LayoutParams) itemViewGroup.getChildAt(0).getLayoutParams();params.width = mSreeenWidth;itemViewGroup.getChildAt(0).setLayoutParams(params);}
手指按下的时候,把刚才那个item常见显示的视图RelativeLayout宽度成屏幕的宽度,以及获得删除按钮TextView 的宽度,isBtnDelShow为flag,用于标记删除是否处于显示状态,若显示,点击时重置下Item显示状态(即不显示删除按钮的视图状态),Integer currentPosition = pointToPosition(mDownX, mDownY),currentPosition 为-1时表示手指点击点是在item之间的分割线上,不作逻辑处理。itemViewGroup即Item的布局,itemViewGroup.getChildAt(0)为Item子View,即上述的RelativeLayout。
/** * 手指移动逻辑 */private boolean onActionMove(MotionEvent e) {int nowX = (int) e.getX();int nowY = (int) e.getY();// 判断是否为偏向左右的滑动if (Math.abs(nowX - mDownX) > Math.abs(nowY - mDownY)) {// 左右滑动请求消费该事件,防止上下滑动以及被ScrollView嵌套的手势冲突requestDisallowInterceptTouchEvent(true);// 判断是否为向左滑动if (nowX < mDownX) {int srollX = mDownX - nowX;// 判断左滑距离是否超过删除按钮宽if (srollX >= mBtnDelWidth) {srollX = mBtnDelWidth;}params.leftMargin = -srollX;itemViewGroup.getChildAt(0).setLayoutParams(params);}// 消费掉该移动事件return true;}return super.onTouchEvent(e);}这里的思路就是判定左滑时,并根据左滑的绝对距离(即手指向左边滑动的实际水平距离),实时设定RelativeLayout视图的MarginLeft为相应距离的负值以达到感觉item布局像是被手指划走的效果,删除按钮也随即从左边逐渐显示出来。注意下requestDisallowInterceptTouchEvent(true)这行代码的注释,手指点击的位置是在ListView上,且是左右滑,为了避免手势冲突,不让父View即ScrollView拦截该手势事件。
/** * 手指释放逻辑 */ private void onActionUp(MotionEvent e) { //判断手指释放后,删除按钮是否已显示超过其宽度的一半 if (-params.leftMargin >= mBtnDelWidth / 2) { params.leftMargin = -mBtnDelWidth; isBtnDelShow = true; } else { //恢复滑动前的视图状态 resetItemView(); } itemViewGroup.getChildAt(0).setLayoutParams(params); }
/** * 重写该方法是用来应对ScrollView嵌套显示不全的问题 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 获得ScrollView或其子类对象,这里视情况而定,可能不需要只需要一个getParent()或多次,视自己的布局层次而定 Object object = getParent().getParent(); if (object instanceof ScrollView) {// 是ScrollView或其子类 /*解决与ScrollView的布局冲突,让ListView完全显示*/ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } else { // 没有ScrollView嵌套,正常super的方法 super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
/** * 重置itemView,恢复原显示状态 */public void resetItemView() {params.leftMargin = 0;itemViewGroup.getChildAt(0).setLayoutParams(params);isBtnDelShow = false;}看注释。
3.在适配器Adapter中获取该ListView对象,当删除按钮显示时,点击删除,删除集合里对应的数据,ListView对象再调用上述的resetItemView()方法,再调用adapter的notifyDataSetChanged()方法更新界面。
holder.tv_btn_delete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {items.remove(items.get(position));lv_messages.resetItemView();notifyDataSetChanged();}});
效果图:
OK,实现方式的核心代码已贴上,如果还有什么不懂的地方或有更好的建议欢迎留言。Demo源码下载
- ListView侧滑删除的实现,SlideDeleteListView,针对ScrollView嵌套ListView视图和手势冲突优化
- ListView侧滑删除的实现,SlideDeleteListView,针对ScrollView嵌套ListView视图和手势冲突优化
- 针对ListView item的侧滑删除和支持下拉时HeaderView缩放的ListView、ScrollView
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- 【Android界面实现】解决ScrollView中嵌套Listview,Listview中嵌套Listview显示不完整和滑动冲突的问题
- listview嵌套listview ScrollView嵌套listview 的冲突问题
- ScrollView嵌套ListView冲突
- ScrollView和ListView滚动手势冲突解决方法
- ScrollView和Listview嵌套冲突问题解决
- Listview和scrollview嵌套冲突问题
- 解决ScrollView嵌套ListView和GridView冲突
- Android编程笔记 GridView、ListView和ScrollView的嵌套冲突
- 解决ScrollView嵌套ListView和GridView冲突的方法
- 解决ScrollView嵌套ListView和GridView冲突的方法
- 解决ScrollView嵌套ListView和GridView冲突的方法
- 解决ScrollView嵌套ListView和GridView冲突的方法
- 来自前端的一个上中下居中的小技巧
- C#控制台基础 判断指定目录下的文件是否存在
- Unity客户端架构-GlobalGenerator
- 第三周-项目2 建设“顺序表”算法库
- WebMvcConfigurerAdapter
- ListView侧滑删除的实现,SlideDeleteListView,针对ScrollView嵌套ListView视图和手势冲突优化
- 逻辑回归(推荐系统)
- 堆空间与栈空间
- Android中内容观察者的使用---- ContentObserver类详解
- ubuntu sublime text 2
- 二分查找
- 高清播放之滤镜 – MadVR
- 堆栈的区别及增长方向
- Spring mvc使用注解@ResponseBody Ajax请求返回json报406错误