为ListView添加炫酷的Item中带侧滑的删除,原理是利用item布局中的padding(Left和Right)属性为负值,来把删除的按钮隐藏在屏幕外。然后通过自定义ListView重写其中的OnTouchEvent通过手指坐标点的计算来处理事件,实现itemView的滚动,达到滑动出现删除菜单,本例中仅实现右向左滑出现删除按钮,大家可以根据自己需求,参照自定义ListView中事件处理做出左侧滑,右侧滑出现菜单,当然不仅仅局限于删除。更多灵活用法期待发觉。
首先上自定义的ListSlideView代码,其中有有详细注释,我就不废话了!(该ListView参考以前项目里面的事件分发处理判断,具体参考了哪位大神的写法已无法考究,感谢最原先的作者的同时也请见谅,如见可联系博主,把参考出处加上)
ListSlideView:
/** * ListSlideView.java * 2015 下午3:00:24 */ package com.example.slideviewtest; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Scroller; /** * @note 自定义的listView,集成自系统的ListView,对list的OnTouchEnvent事件分发进行了拦截处理(最关键的地方, * 也是通过该方式实现了控制屏幕外布局的拖拽) 需要配合Item的布局文件来实现 * @author blank * @time 下午3:00:24 * @version V1.0 */ public class ListSlideView extends ListView { /** 禁止侧滑模式 */ public static int MODE_FORBID = 0; /** 从右向左滑出菜单模式 */ public static int MODE_RIGHT = 1; /** 当前的模式 */ private int mode = MODE_FORBID; /** 右侧菜单的长度 */ 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 ListSlideView(Context context) { this(context, null); } public ListSlideView(Context context, AttributeSet attrs) { this(context, attrs, 0); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideMode); mode = a.getInt(R.styleable.SlideMode_mode, 0); } public ListSlideView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideMode); mode = a.getInt(R.styleable.SlideMode_mode, 0); scroller = new Scroller(context); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } /** * 处理我们拖动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"); /* 默认不处理当前View的事件,即没有侧滑菜单 */ if (this.mode == MODE_FORBID) { return super.onTouchEvent(ev); } // 侧滑状态判断 if (isSlided) { scrollBack(); return false; } // 滚动是否结束 if (!scroller.isFinished()) { return false; } downX = (int) ev.getX(); downY = (int) ev.getY(); slidePosition = pointToPosition(downX, downY); // 无效的position if (slidePosition == AdapterView.INVALID_POSITION) { return super.onTouchEvent(ev); } itemView = getChildAt(slidePosition - getFirstVisiblePosition()); /* 右侧菜单的长度 */ if (this.mode == MODE_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 == MODE_RIGHT) { /* 从右向左滑 */ 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); // 根据X坐标的差可以得到手指滑动方向,本例子可以根据自己的需要去灵活修改(左边划出菜单,右边划出菜单,或者左右均可) int deltaX = downX - lastX; if (deltaX > 0 && this.mode == MODE_RIGHT) { /* X坐标差大于0手指向右滑动 */ itemView.scrollTo(deltaX, 0); } else { itemView.scrollTo(0, 0); } return true; } case MotionEvent.ACTION_UP: System.out.println("touch-->" + "up"); if (canMove) { canMove = false; scrollByDistanceX(); } break; } return super.onTouchEvent(ev); } /** * 根据手指滚动itemView的距离来判断是滚动到开始位置还是向左或者向右滚动 */ private void scrollByDistanceX() { /* 当前模式不允许滑动,则直接返回 */ if (this.mode == MODE_FORBID) { return; } if (itemView.getScrollX() > 0 && this.mode == MODE_RIGHT) { /* 从右向左滑 */ if (itemView.getScrollX() >= rightLength / 2) { scrollLeft(); } else { // 滚回原始位置 scrollBack(); } } else { // 滚回原始位置 scrollBack(); } } /** * 向左滑动 */ 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 } @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(); } }
为了兼容以前的ListView添加了是否需要侧滑的自定义控件属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SlideMode"> <attr name="mode"> <enum name="forbid" value="0"></enum> <enum name="right" value="1"></enum> </attr> </declare-styleable> </resources>
ItemView的布局:
<?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="match_parent" android:background="@android:color/white" android:gravity="center_vertical" android:orientation="horizontal" android:paddingBottom="10dp" android:paddingRight="-90dp" android:paddingTop="10dp" android:weightSum="1" > <LinearLayout android:layout_width="0dp" android:layout_height="96dp" android:layout_weight="0.35" android:orientation="vertical" > <ImageView android:id="@+id/imgIcon" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:scaleType="fitXY" android:src="@drawable/images" /> <TextView android:id="@+id/tvPrice" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="$128.5" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="96dp" android:layout_weight="0.65" android:orientation="vertical" android:padding="5dp" > <TextView android:id="@+id/tvName" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:text="HP 14-P010NR 14 TOUCHSCREEN SLATEBOOK, NIVIDIA TE" android:textStyle="bold" /> <RatingBar android:id="@+id/ratingBar" style="?android:attr/ratingBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" /> </LinearLayout> <TextView android:id="@+id/tvDelete" android:layout_width="90dp" android:layout_height="96dp" android:layout_centerInParent="true" android:layout_marginRight="-5dp" android:background="@android:color/holo_red_light" android:gravity="center" android:text="Delete" android:textColor="@android:color/white" android:textSize="15sp" /> </LinearLayout>
package com.example.slideviewtest; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; /** * @author blank * @time 下午4:01:07 * @version V1.0 */ public class SlideViewAdapter extends BaseAdapter { private Context mContext; private LayoutInflater layoutInflr; private int itemtype = 1; private OnRemoveListener mRemoveListener; public int getItemtype() { return itemtype; } public void setItemtype(int itemtype) { this.itemtype = itemtype; } public SlideViewAdapter( Context context) { this.mContext = context; this.layoutInflr = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void setRemoveListener(OnRemoveListener removeListener) { this.mRemoveListener = removeListener; } class Viewlayout { private TextView mDelete;// 隐藏的侧滑删除按钮 } @Override public int getCount() { // TODO Auto-generated method stub return 10; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { Viewlayout icom_view; if (convertView == null) { icom_view = new Viewlayout(); convertView = layoutInflr.inflate(R.layout.item_product_listview, null); icom_view.mDelete = (TextView) convertView .findViewById(R.id.tvDelete); convertView.setTag(icom_view); } else { icom_view = (Viewlayout) convertView.getTag(); } icom_view.mDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if(mRemoveListener!=null){mRemoveListener.onRemoveItem(position);} } }); return convertView; } public interface OnRemoveListener { void onRemoveItem(int position); } }
来2张效果图:
源码下载地址:http://download.csdn.net/detail/q849340003/8959897
版权声明:本文为博主原创文章,未经博主允许不得转载。
【android自定义控件】android ListView添加侧滑删除
原文地址:http://blog.csdn.net/q849340003/article/details/47276801