列表侧滑删除(一)

来源:互联网 发布:天气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>

奋斗奋斗我们的介绍就这些啦!你还有什么不明白的请告诉我哦。。。


阅读全文
1 0
原创粉丝点击