开源控件学习之-侧滑listview进行删除(一)(自定义listview)
2016-01-05 14:52
441 查看
最近工作的项目中需要用到listview的侧滑删除。
参考了网上的一些项目做出了更改,这里做出一篇笔记,希望对看到的人有一些帮助。
实现步骤一:定义自定义控件SlideListView
实现步骤三:listItem的布局文件如下:
实现步骤四:在我们的activity中进行调用:
在步骤四中需要注意的是,我们需要initSlideMode,不然我在自定义的控件中会抛出空指针错误。
此时,有的人可能会在listview的adapter中添加我们item的点击事件,这样我们就不可以进行滑动了。这里牵涉到事件机制。
推荐关注的文章:
http://blog.csdn.net/liyuanjinglyj/article/details/48550489 http://blog.csdn.net/jiangwei0910410003/article/details/17504315 http://blog.csdn.net/guolin_blog/article/details/9097463/ http://blog.csdn.net/xiaanming/article/details/21696315注意事项:1 左、右侧滑出菜单的ListView(划出后选择进行操作,本项目主要是进行删除);2 使用请注意与ListView的Item的布局配合;3 该效果的实现是基于在Item的布局中通过设置PaddingLeft和PaddingRight来隐藏左右菜单的, 所以使用此ListView时,请务必在布局Item时使用PaddingLeft和PaddingRight。
好了。当做对这个问题处理的笔记,也希望对看到的人真心有帮助。
参考了网上的一些项目做出了更改,这里做出一篇笔记,希望对看到的人有一些帮助。
实现步骤一:定义自定义控件SlideListView
/** * Created by Anthony on 16/1/4. */ public class SlideListView extends ListView { /** * 禁止侧滑模式 */ public static int MOD_FORBID = 0; /** * 从左向右滑出菜单模式 */ public static int MOD_LEFT = 1; /** * 从右向左滑出菜单模式 */ public static int MOD_RIGHT = 2; /** * 左右均可以滑出菜单模式 */ public static int MOD_BOTH = 3; /** * 当前的模式 */ private int mode = MOD_FORBID; /** * 左侧菜单的长度 */ private int leftLength = 0; /** * 右侧菜单的长度 */ private int rightLength = 0; /** * 当前滑动的ListView position */ private int slidePosition; /** * 手指按下X的坐标 */ private int downY; /** * 手指按下Y的坐标 */ private int downX; /** * ListView的item */ private View itemView; /** * 滑动类 */ private Scroller scroller; /** * 认为是用户滑动的最小距离 */ private int mTouchSlop; /** * 判断是否可以侧向滑动 */ private boolean canMove = false; /** * 标示是否完成侧滑 */ private boolean isSlided = false; public SlideListView(Context context) { this(context, null); } public SlideListView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); scroller = new Scroller(context); //getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件,如viewpager就是用这个距离来判断用户是否翻页 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } /** * 初始化菜单的滑出模式 * * @param mode */ public void initSlideMode(int mode) { this.mode = mode; } /** * 处理我们拖动ListView item的逻辑 */ @Override public boolean onTouchEvent(MotionEvent ev) { final int action = ev.getAction(); int lastX = (int) ev.getX(); switch (action) { case MotionEvent.ACTION_DOWN: System.out.println("touch-->" + "down"); //当前模式不允许滑动,则直接返回,交给ListView自身去处理 if (this.mode == MOD_FORBID) { return super.onTouchEvent(ev); } // 如果处于侧滑完成状态,侧滑回去,并直接返回 if (isSlided) { scrollBack(); return false; } // 假如scroller滚动还没有结束,我们直接返回 if (!scroller.isFinished()) { return false; } downX = (int) ev.getX(); downY = (int) ev.getY(); //通过当前位置xy值获取当前在第几个item slidePosition = pointToPosition(downX, downY); // 无效的position, 不做任何处理 if (slidePosition == AdapterView.INVALID_POSITION) { return super.onTouchEvent(ev); } // 获取我们点击的item view itemView = getChildAt(slidePosition - getFirstVisiblePosition()); /*此处根据设置的滑动模式,自动获取左侧或右侧菜单的长度*/ if (this.mode == MOD_BOTH) { this.leftLength = -itemView.getPaddingLeft(); this.rightLength = -itemView.getPaddingRight(); } else if (this.mode == MOD_LEFT) { this.leftLength = -itemView.getPaddingLeft(); } else if (this.mode == MOD_RIGHT) { this.rightLength = - itemView.getPaddingRight(); } break; case MotionEvent.ACTION_MOVE: System.out.println("touch-->" + "move"); if (!canMove && slidePosition != AdapterView.INVALID_POSITION && (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev .getY() - downY) < mTouchSlop)) { int offsetX = downX - lastX; if (offsetX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) { /*从右向左滑*/ canMove = true; } else if (offsetX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) { /*从左向右滑*/ canMove = true; } else { canMove = false; } /*此段代码是为了避免我们在侧向滑动时同时触发ListView的OnItemClickListener事件*/ MotionEvent cancelEvent = MotionEvent.obtain(ev); cancelEvent .setAction(MotionEvent.ACTION_CANCEL | (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); onTouchEvent(cancelEvent); } if (canMove) { //设置此属性,可以在侧向滑动时,保持ListView不会上下滚动 requestDisallowInterceptTouchEvent(true); // 手指拖动itemView滚动, deltaX大于0向左滚动,小于0向右滚 int deltaX = downX - lastX; if (deltaX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) { /*向左滑*/ itemView.scrollTo(deltaX, 0); } else if (deltaX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) { /*向右滑*/ itemView.scrollTo(deltaX, 0); } else { itemView.scrollTo(0, 0); } return true; // 拖动的时候ListView不滚动 } case MotionEvent.ACTION_UP: System.out.println("touch-->" + "up"); if (canMove) { canMove = false; scrollByDistanceX(); } break; } // 否则直接交给ListView来处理onTouchEvent事件 return super.onTouchEvent(ev); } /** * 根据手指滚动itemView的距离来判断是滚动到开始位置还是向左或者向右滚动 */ private void scrollByDistanceX() { /*当前模式不允许滑动,则直接返回*/ if (this.mode == MOD_FORBID) { return; } if (itemView.getScrollX() > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)) { /*从右向左滑*/ if (itemView.getScrollX() >= rightLength / 2) { scrollLeft(); } else { // 滚回到原始位置 scrollBack(); } } else if (itemView.getScrollX() < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)) { /*从左向右滑*/ if (itemView.getScrollX() <= -leftLength / 2) { scrollRight(); } else { // 滚回到原始位置 scrollBack(); } } else { // 滚回到原始位置 scrollBack(); } } /** * 往右滑动,getScrollX()返回的是左边缘的距离,就是以View左边缘为原点到开始滑动的距离,所以向右边滑动为负值 */ private void scrollRight() { isSlided = true; final int delta = (leftLength + itemView.getScrollX()); // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item scroller.startScroll(itemView.getScrollX(), 0, -delta, 0, Math.abs(delta)); postInvalidate(); // 刷新itemView } /** * 向左滑动,根据上面我们知道向左滑动为正值 */ private void scrollLeft() { isSlided = true; final int delta = (rightLength - itemView.getScrollX()); // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item scroller.startScroll(itemView.getScrollX(), 0, delta, 0, Math.abs(delta)); postInvalidate(); // 刷新itemView } /** * 滑动会原来的位置 */ private void scrollBack() { isSlided = false; scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(), 0, Math.abs(itemView.getScrollX())); postInvalidate(); // 刷新itemView } /** * 通常是用mScroller记录/计算View滚动的位置, * 再重写View的computeScroll(),完成实际的滚动。 */ @Override public void computeScroll() { // 调用startScroll的时候scroller.computeScrollOffset()返回true, if (scroller.computeScrollOffset()) { // 让ListView item根据当前的滚动偏移量进行滚动 itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY()); postInvalidate(); } } /** * 提供给外部调用,用以将侧滑出来的滑回去 */ public void slideBack() { this.scrollBack(); } }实现步骤二:整体activity的布局如下,也就是一个listview:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.test.view.SlideListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="#dddbdb" android:dividerHeight="1.0px" android:drawSelectorOnTop="true" android:listSelector="@drawable/list_item_selector" android:scrollbars="none" /> </RelativeLayout>
实现步骤三:listItem的布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="@color/bg_channel" android:paddingRight="-90dp" android:orientation="horizontal" android:layout_height="@dimen/size100"> <RelativeLayout android:id="@+id/layout_content" android:layout_height="@dimen/size100" android:layout_centerVertical="true" android:layout_width="fill_parent"> <TextView android:id="@+id/txt_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/size10" android:ellipsize="end" android:lines="1" android:textColor="@color/vtibet_black" android:textSize="16sp" /> </RelativeLayout> <LinearLayout android:id="@+id/layout_right" android:layout_width="90dp" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:id="@+id/delete_item" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/tomato" android:clickable="true"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:text="删除" android:textColor="@color/white" android:textSize="15sp"/> </RelativeLayout> </LinearLayout> </LinearLayout>对于listItem,我们主要通过的是PaddingRight来实现的把我们的id为layout_right的控件隐藏。这也是下拉刷新的实现原理之一,通过padding设置为负数来隐藏我们的一些控件。然后需要将我们的item上面的delete的布局的clickable置为true,不然你会发现无法点击item上面的删除键。
实现步骤四:在我们的activity中进行调用:
list_view = (SlideListView) view.findViewById(R.id.list_view); list_view.initSlideMode(SlideListView.MOD_RIGHT); list_view.setOnItemClickListener(this); list_view.setOnItemLongClickListener(this);
......在自己的adapter的getView中:
<pre name="code" class="html"> final RelativeLayout delete_item = (RelativeLayout) convertView.findViewById(R.id.delete_item); delete_item.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { delete(item.getId(), position);//删除数据 } });......
在步骤四中需要注意的是,我们需要initSlideMode,不然我在自定义的控件中会抛出空指针错误。
此时,有的人可能会在listview的adapter中添加我们item的点击事件,这样我们就不可以进行滑动了。这里牵涉到事件机制。
推荐关注的文章:
http://blog.csdn.net/liyuanjinglyj/article/details/48550489 http://blog.csdn.net/jiangwei0910410003/article/details/17504315 http://blog.csdn.net/guolin_blog/article/details/9097463/ http://blog.csdn.net/xiaanming/article/details/21696315注意事项:1 左、右侧滑出菜单的ListView(划出后选择进行操作,本项目主要是进行删除);2 使用请注意与ListView的Item的布局配合;3 该效果的实现是基于在Item的布局中通过设置PaddingLeft和PaddingRight来隐藏左右菜单的, 所以使用此ListView时,请务必在布局Item时使用PaddingLeft和PaddingRight。
好了。当做对这个问题处理的笔记,也希望对看到的人真心有帮助。
<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'宋体';font-size:12.0pt;">
相关文章推荐
- 虚拟视频驱动程序vivi.c源码分析[转]
- POJ2104 K-th Number
- jmeter名词解释之时间(Elapsed Time/ Latency Time/Connection Time)
- 常用 Git 命令清单
- Python之IPython开发实践
- Django开发博客(四)——建立文章列表
- XCode的一些调试技巧
- HDU 5514 Frogs(容斥)
- Python之IPython开发实践
- [web安全] web安全小知识点汇总
- 调试一个MFC的点云可视化(PCL)程序
- lintcode 中等题:partition array 数组划分
- Android:图形
- LeetCode106 Construct Binary Tree from Inorder and Postorder Traversal
- php视频直播
- JQuery DataTables学习
- Instance Three: SELECT * FROM DATABASE
- Mongodb 权限管理
- 《swift2.0 官方教程中文版》 第2章-23泛型
- 表的聚合函数