列表侧滑删除(一)
来源:互联网 发布:天气json数据解析 编辑:程序博客网 时间:2024/06/03 21:54
今天为大家介绍下列表的策划删除功能,废话不多说,直接看效果图:
我们先坐下介绍:和QQ列表的侧滑删除功能很像
1.是个列表
2.每一个条目都可以向左滑动,并且滑动第二个条目时,第一个条目返回,显示“取消收藏”,也就是删除。
3.点击“取消收藏”,条目删除,并且不存在列表条目错乱问题。
接下来我们就逐一介绍:
1.使用ListView或者RecyclerView都可,不做介绍。
2.每一个条目都可以向左滑动,并且滑动第二个条目时,第一个条目返回,显示“取消收藏”
这里我用的是RecyclerView,通过图 我们可以看出是三fragment组成,并且每个fragment里都可以上拉加载,下拉刷新(这里对这一部分功能我们以后再做介绍),我们先看代码:这里的每一个条目(也就是列表的item)是一个自定义的item。
我们先看整体的代码,然后再介绍;
1.自定义SlidingButtonView 继承 HorizontalScrollView
/** * Created by MJJ on 2015/7/25. * 可以左滑显示删除的view */public class SlidingButtonView extends HorizontalScrollView { private TextView mTextView_Delete; private IonSlidingButtonListener mIonSlidingButtonListener; private int mScrollWidth; private Boolean isOpen = false; private Boolean once = false; public SlidingButtonView(Context context) { this(context, null); } public SlidingButtonView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingButtonView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.setOverScrollMode(OVER_SCROLL_NEVER); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (!once) {//如果是第一次 mTextView_Delete = (TextView) findViewById(R.id.tv_delete); once = true; } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { this.scrollTo(0, 0); //获取水平滚动条可以滑动的范围,即右侧按钮的宽度 mScrollWidth = mTextView_Delete.getWidth(); Log.i("asd", "mScrollWidth:" + mScrollWidth); } } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: if (mIonSlidingButtonListener != null) mIonSlidingButtonListener.onDownOrMove(this); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: //按滚动条被拖动距离判断关闭或打开菜单 changeScrollx(); return true; default: break; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); mTextView_Delete.setTranslationX(l - mScrollWidth); } /** * 按滚动条被拖动距离判断关闭或打开菜单 */ public void changeScrollx() { if (getScrollX() >= (mScrollWidth / 2)) {//拖动距离大于"取消"按钮的一半 this.smoothScrollTo(mScrollWidth, 0);//滑动至(mScrollWidth, 0) ,smoothScrollTo 与scrollTo相似 isOpen = true;//为打开状态 if (mIonSlidingButtonListener != null) mIonSlidingButtonListener.onMenuIsOpen(this);//菜单开启 } else {//拖动距离小于"取消"按钮的一半 this.smoothScrollTo(0, 0);//滑动至(0, 0) isOpen = false;//为关闭状态 } } /** * 打开菜单 */ public void openMenu() { if (isOpen) { return; } this.smoothScrollTo(mScrollWidth, 0); isOpen = true; if (mIonSlidingButtonListener != null) mIonSlidingButtonListener.onMenuIsOpen(this); } /** * 关闭菜单 */ public void closeMenu() { if (!isOpen) { return; } this.smoothScrollTo(0, 0); isOpen = false;//关闭状态 } public interface IonSlidingButtonListener { void onMenuIsOpen(View view);//菜单开启 void onDownOrMove(SlidingButtonView slidingButtonView);//点击或拖动菜单 } public void setSlidingButtonListener(IonSlidingButtonListener listener) { mIonSlidingButtonListener = listener; }}
我们看到SlidingButtonView继承了一个HorizontalScrollView 具体参考:
http://www.tuicool.com/articles/yQ3E7b
http://blog.csdn.net/lixiang_y/article/details/55102855
http://www.cnblogs.com/xiaoluo501395377/p/3460645.html
这里有一个方法:
public SlidingButtonView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.setOverScrollMode(OVER_SCROLL_NEVER); }
我们需要注意的就是setOverScrollMode(OVER_SCROLL_NEVER); 具体介绍看考:
http://blog.sina.com.cn/s/blog_5da93c8f0102uxxd.html
http://yangsongjing.iteye.com/blog/1973903
方法onMrasue 中:获取空间
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (!once) {//如果是第一次 mTextView_Delete = (TextView) findViewById(R.id.tv_delete); once = true; } }
方法onLayout 中:得到空间的宽,并且当changed时,不移动
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { this.scrollTo(0, 0); //获取水平滚动条可以滑动的范围,即右侧按钮的宽度 mScrollWidth = mTextView_Delete.getWidth(); Log.i("asd", "mScrollWidth:" + mScrollWidth); } }具体参考:onLayout: http://blog.csdn.net/hudashi/article/details/50913257 http://www.2cto.com/kf/201511/449947.html
scrollTo:http://blog.csdn.net/bigconvience/article/details/26697645
重写 onTouchEvent :在不同的动作中作出操作:
@Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: if (mIonSlidingButtonListener != null) mIonSlidingButtonListener.onDownOrMove(this); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: //按滚动条被拖动距离判断关闭或打开菜单 changeScrollx(); return true; default: break; } return super.onTouchEvent(ev); }
当操作为“点击”“滑动” 和 “抬起”“取消” 是不懂得状态中,在“点击”“滑动” 状态 中自定义监听方法onDownOrMove() , 在 “抬起”“取消” 状态中 自定义监听方法 onmenuIsOpen() 判断菜单是否为打开状态。
看监听方法:
public interface IonSlidingButtonListener { void onMenuIsOpen(View view);//菜单开启 void onDownOrMove(SlidingButtonView slidingButtonView);//点击或拖动菜单 } public void setSlidingButtonListener(IonSlidingButtonListener listener) { mIonSlidingButtonListener = listener; }通过changeScrollX();判断菜单是否为开启状态:
/** * 按滚动条被拖动距离判断关闭或打开菜单 */ public void changeScrollx() { if (getScrollX() >= (mScrollWidth / 2)) {//拖动距离大于"取消"按钮的一半 this.smoothScrollTo(mScrollWidth, 0);//滑动至(mScrollWidth, 0) ,smoothScrollTo 与scrollTo相似 isOpen = true;//为打开状态 if (mIonSlidingButtonListener != null) mIonSlidingButtonListener.onMenuIsOpen(this);//菜单开启 } else {//拖动距离小于"取消"按钮的一半 this.smoothScrollTo(0, 0);//滑动至(0, 0) isOpen = false;//为关闭状态 } }
2.看一下Adapter 的代码,列表条目的操作都是在adapter中完成的。
/** * 我的收藏列表 -- 产品 */public class MyCollect_ProductAdapter extends RecyclerView.Adapter<MyCollect_ProductAdapter.ViewHolder> implements SlidingButtonView.IonSlidingButtonListener { private Context mContext; private LayoutInflater mInflater; private List<MyCollectListBean.CollectListBean> mDatas; private SlidingButtonView mMenu = null; public MyCollect_ProductAdapter(Context context, List<MyCollectListBean.CollectListBean> lists) { mContext = context; mDatas = lists; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { mInflater = LayoutInflater.from(parent.getContext()); View view = mInflater.inflate(R.layout.item_mycollect_product, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { Glide.with(mContext).load(mDatas.get(position).product_photo).centerCrop().into(holder.iv_img); holder.tv_product_name.setText(mDatas.get(position).product_name); holder.tv_product_date.setText(mDatas.get(position).collect_time); holder.tv_factory_name.setText(mDatas.get(position).p_shop_name); holder.tv_product_price.setText("¥ " + mDatas.get(position).product_price); holder.tv_sale_num.setText("销售量: " + mDatas.get(position).product_count_order); //获取屏幕像素赋值给条目的宽 holder.rl_item.getLayoutParams().width = UIutils.getWindowDisplayMetrics(mContext).widthPixels; holder.rl_item.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(mContext, Classify_ProductDetailActivity.class); intent.putExtra("product_id", mDatas.get(position).content_id); mContext.startActivity(intent); } }); holder.tv_delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {// int realPos = holder.getLayoutPosition(); onLoadToCancleCollect(mDatas.get(position).product_id, position); } }); } @Override public int getItemCount() { return mDatas.size(); } public class ViewHolder extends RecyclerView.ViewHolder { RelativeLayout rl_item; ImageView iv_img; TextView tv_product_name; TextView tv_product_date; TextView tv_factory_name; TextView tv_product_price; TextView tv_sale_num; TextView tv_delete; public ViewHolder(View itemView) { super(itemView); rl_item = (RelativeLayout) itemView.findViewById(R.id.rl_item); iv_img = (ImageView) itemView.findViewById(R.id.iv_img); tv_product_name = (TextView) itemView.findViewById(R.id.tv_product_name); tv_product_date = (TextView) itemView.findViewById(R.id.tv_product_date); tv_factory_name = (TextView) itemView.findViewById(R.id.tv_factory_name); tv_product_price = (TextView) itemView.findViewById(R.id.tv_product_price); tv_sale_num = (TextView) itemView.findViewById(R.id.tv_sale_num); tv_delete = (TextView) itemView.findViewById(R.id.tv_delete); //获取监听 ((SlidingButtonView) itemView).setSlidingButtonListener(MyCollect_ProductAdapter.this); } } /** * 取消收藏 * * @param product_id 收藏 产品product_id * @param position 取消的位置position */ private void onLoadToCancleCollect(String product_id, final int position) { String user_id = SpUtils.getUserId(mContext); ServiceApi.getCancleCollect(user_id, product_id, "0", new MyString2Callback() { @Override public void onError(Call call, Exception e) { ToastUtils.showInternetErrorToast(); } @Override public void onResponse(Call call, String s) { BaseBean result = new Gson().fromJson(s, BaseBean.class); if (result.code == 0) { //取消成功 mDatas.remove(position); notifyItemRemoved(position); if (position != mDatas.size()) { notifyItemRangeChanged(position, mDatas.size() - position); } } else { ToastUtils.showToast(result.msg); } } }); } @Override public void onMenuIsOpen(View view) { //菜单开启,//mMenu 当菜单开启才会获得mMenu mMenu = (SlidingButtonView) view; } @Override public void onDownOrMove(SlidingButtonView slidingButtonView) {//点击或拖动菜单 if (menuIsOpen()) { //判断是否有菜单打开 ,有菜单是开启状态 if (mMenu != slidingButtonView) { //判断拖动的菜单是否是已开启的菜单 closeMenu();//关闭已开启的菜单 } } } /** * 关闭菜单 *关闭已开启的菜单 */ public void closeMenu() { mMenu.closeMenu(); //关闭菜单 ,调取SlidingButtonView中方法 mMenu = null; } /** * 判断是否有菜单打开 */ public Boolean menuIsOpen() { if (mMenu != null) { //mMenu 当已经有菜单是开启状态才会获得mMenu return true; } Log.i("asd", "mMenu为null"); return false; }}
3.对于点击“取消收藏”,条目删除,并且不存在列表条目错乱问题。解决的方法:
if (result.code == 0) { //取消成功 mDatas.remove(position); notifyItemRemoved(position); if (position != mDatas.size()) { notifyItemRangeChanged(position, mDatas.size() - position); }
具体介绍参考:http://blog.csdn.net/lijinweii/article/details/72636753
最后我们展示下xml,文件:item_mycollect_product.xml
<?xml version="1.0" encoding="utf-8"?><包名.view.SlidingButtonView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/slidingbt" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_delete" android:layout_width="80dp" android:layout_height="match_parent" android:layout_alignBottom="@id/rl_item" android:layout_alignTop="@+id/rl_item" android:layout_toRightOf="@+id/rl_item" android:background="@color/red" android:gravity="center" android:text="取消收藏" android:textColor="#000000" /> <RelativeLayout android:id="@+id/rl_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white"> <ImageView android:id="@+id/iv_img" android:layout_width="110dp" android:layout_height="90dp" android:layout_centerVertical="true" android:layout_margin="8dp" android:background="@drawable/error_img" android:scaleType="fitXY"/> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/iv_img" android:layout_alignTop="@+id/iv_img" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_toRightOf="@id/iv_img"> <TextView android:id="@+id/tv_product_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="8dp" android:layout_toLeftOf="@+id/tv_product_date" android:ellipsize="end" android:maxLines="1" android:text="@string/default_text" android:textColor="@color/black" android:textSize="14sp" /> <TextView android:id="@+id/tv_product_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/tv_product_name" android:layout_alignParentRight="true" android:text="@string/default_text" android:textColor="@color/tv_gray" android:textSize="11sp" /> <TextView android:id="@+id/tv_factory_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="@string/default_text" android:textColor="@color/tv_black_light" android:textSize="13sp" /> <TextView android:id="@+id/tv_product_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:minWidth="50dp" android:text="@string/default_text" android:textColor="@color/tv_orange" android:textSize="13sp" /> <TextView android:id="@+id/tv_sale_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/tv_product_price" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/tv_product_price" android:text="@string/default_text" android:textSize="13sp" /> </RelativeLayout> </RelativeLayout> </RelativeLayout></包名.view.SlidingButtonView>
我们的介绍就这些啦!你还有什么不明白的请告诉我哦。。。
- 列表侧滑删除(一)
- android侧滑删除列表
- 列表侧滑删除(二)
- 仿qq列表侧滑删除
- 列表侧滑删除和点击下滑
- 仿QQ列表侧滑删除的ListView
- Android列表侧滑删除就是这么简单
- 仿微信的列表滑动删除(一) 可滑动控件
- 仿QQ消息列表item横向滑动删除ListView中item侧滑删除
- 侧滑删除进阶(一)
- 仿QQ列表左滑删除效果
- Android 自定义左滑删除列表
- recycleview 使用侧滑删除 android 6.0机型出现item抖动;列表一屏以上,点击后面的item(需要滚动查看了) 然后马上会往上滚动回首个item,滚回第一项
- Android开发学习之仿手机QQ消息列表侧滑删除效果
- RecyclerView实现支持拖拽、删除、侧滑菜单的列表
- 云信demo如何修改为侧滑删除聊天列表
- Android Scroller详解,实现仿QQ列表item侧滑删除功能
- Blog删除文章列表
- Java中CAS详解
- Hadoop 学习研究(八): 多Job任务和hadoop中的全局变量
- Python报错——AttributeError: module 'PyQt5.QtGui' has no attribute 'QApplication'
- 各种自适应滤波器总结
- Codevs 1227方格取数 (费用流
- 列表侧滑删除(一)
- 将java的image对象转换成jpeg图片文件形式保存
- 65、66、67
- fastjson 解析json
- 文章标题JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Pat
- codeforces——797B——Odd sum
- 调用类自身常量
- Sum of Consecutive Prime Numbers UVA
- 高斯混合模型(GMM)