1. 程式人生 > >Android recyclerView items的側滑刪除以及點選事件處理

Android recyclerView items的側滑刪除以及點選事件處理

最近專案中需要實現銀行卡側滑刪除以及選擇預設無法刪除的效果,需求效果圖如下:

在這裡插入圖片描述 其實就是一個自定義的列表實現,這裡我用的是recyclerView首先需要自定義DeleteBankRecyclerView繼承RecyclerView,需要注意的是item的點選和滑動事件的處理。 程式碼如下:

 @Override
    public boolean onTouchEvent(MotionEvent e) {

        mVelocityTracker.addMovement(e);
        //獲取當前座標
        int x = (int) e.getX();
        int y = (int) e.getY();

        switch (e.getAction()){
            case MotionEvent.ACTION_DOWN:
                //刪除圖片還沒開啟的狀態
                if (status == CLOSE) {
                    //尋找對應座標點下的V
                    View view = findChildViewUnder(x, y);
                    if (view == null) {
                        return false;
                    }
                    //通過BankMsgViewHolder獲取對應的子View,詳情可以看程式碼
                    BankMsgListAdapter.BankMsgViewHolder viewHolder = (BankMsgListAdapter.BankMsgViewHolder) getChildViewHolder(view);

                    mItemView = viewHolder.itemView.findViewById(R.id.item_layout);
                    rlBankMsg = (RelativeLayout) viewHolder.itemView.findViewById(R.id.rl_bank_msg);//item的內容
                    ivDefaultIcon = (ImageView) viewHolder.itemView.findViewById(R.id.iv_default_icon);//預設選擇框
                    mPosition = viewHolder.getAdapterPosition();
                    mDeleteView = (TextView) viewHolder.itemView.findViewById(R.id.item_delete);
                    if(isForbidSideSlip){
                        mDeleteView.setVisibility(GONE);
                    }
                    mMaxLength = mDeleteView.getWidth();

                    mDeleteView.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            //返回原點
                            mItemView.scrollTo(0,0);
                            status = CLOSE;
                            if (mListener!=null)
                                mListener.onDeleteClick(mPosition);
                        }
                    });
                    //當刪除圖片已經完全顯示的時候
                }else if (status == OPEN){
                    //從當前view的偏移點mItemView.getScrollX(),位移-mMaxLength長度單位
                    // 時間DEFAULT_TIMEms,向左移動為正數
                    mScroller.startScroll(mItemView.getScrollX(),0,-mMaxLength,0,DEFAULT_TIME);
                    //重新整理下一幀動畫
                    invalidate();
                    status = CLOSE;
                    return false;
                }else {
                    return false;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //獲取上次的落點與當前的座標之間的差值
                int dx = mLastX - x;
                int dy = mLastY - y;

                int scrollX = mItemView.getScrollX();
                //水平滑動距離大於垂直距離
                if (Math.abs(dx)>Math.abs(dy) && !isForbidSideSlip){
                    isHorMoving = true;
                    //向左滑動,直至顯示刪除按鈕,向左滑動的最大距離不超過刪除按鈕的寬度
                    if (scrollX+dx>=mMaxLength){
                        mItemView.scrollTo(mMaxLength,0);
                        return true;
                        //向右滑動,直至刪除按鈕不顯示,向右滑動的最大距離不超過初始位置
                    }else if (scrollX+dx<=0){
                        mItemView.scrollTo(0,0);
                        return true;
                    }
                    
                    //如果在圖片還未完全顯示的狀態下,那麼手指滑動多少,圖片就移動多少
                    mItemView.scrollBy(dx,0);
                    //mItemView.scrollTo(dx+scrollX,0);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!isHorMoving && !isVerMoving && mListener!=null){

                    mListener.onItemClick(mItemView,ivDefaultIcon,mPosition);
                }
                isHorMoving = false;

                mVelocityTracker.computeCurrentVelocity(1000);//計算手指滑動的速度
                float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左為負)
                float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度

                int upScrollX = mItemView.getScrollX();
                int deltaX = 0 ;

                //向右滑動速度為正數
                //滑動速度快的狀態下擡起手指,計算所需偏移量
                if (Math.abs(xVelocity)>Math.abs(yVelocity) && Math.abs(xVelocity)>=VELOCITY && !isForbidSideSlip){
                    //向右隱藏
                    if (xVelocity >= VELOCITY){
                        deltaX = -upScrollX;
                        status = CLOSING;
                    }else if (xVelocity <= -VELOCITY){
                        deltaX = mMaxLength - upScrollX;
                        status = OPENING;
                    }
                    //滑動速度慢的狀態下擡起手指,如果滑動距離大於1/2的圖片寬度,計算偏移量
                    //不夠的話恢復原點
                }else {
                    if(!isForbidSideSlip){
                        if (upScrollX >= mMaxLength/2){
                            deltaX = mMaxLength - upScrollX;
                            status = OPENING;
                        }else {
                            deltaX = -upScrollX;
                            status = CLOSING;
                        }
                    }

                }

                mScroller.startScroll(upScrollX,0,deltaX,0,DEFAULT_TIME);
                isStartScroll = true;
                invalidate();

                mVelocityTracker.clear();
                break;
        }
        mLastX = x;
        mLastY = y;
        return super.onTouchEvent(e);
    }

    @Override
    public void computeScroll() {
        //滾動是否完成,true表示還未完成
        if (mScroller.computeScrollOffset()){
            mItemView.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            invalidate();
            //有滑動,並且在滑動結束的時候
        }else if (isStartScroll){
            isStartScroll = false;
            if (status == CLOSING)
                status = CLOSE;

            if (status == OPENING)
                status = OPEN;
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        mVelocityTracker.recycle();
        super.onDetachedFromWindow();
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        isVerMoving = state == SCROLL_STATE_DRAGGING;
    }

    //禁止側滑
    public void forbidSideSlip(){

        this.isForbidSideSlip = true;

    }


//    public void setOnItemClickListener(OnItemClickListener listener){
//        this.mListener = listener;
//    }
public void setOnItemClickListener(OnItemClickListener listener){
    this.mListener = listener;
}

    public interface OnItemClickListener {
        /**
         * item點選回撥
         *
         * @param view
         * @param position
         */
        void onItemClick(View view,ImageView imageView, int position);

        /**
         * 刪除按鈕回撥
         *
         * @param position
         */
        void onDeleteClick(int position);
    }

需要說明的是 OnItemClickListener 下面的兩個方法是自定義的,為了方便對item的事件處理。 自定義view之後,就是佈局當中的應用,程式碼如下:

 <com.geexfinance.view.addBankMsgView.DeleteBankRecyclerView
            android:id="@+id/rc_bank_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

除了主佈局還需要一個adapter,去展示item的具體佈局如下:

public class BankMsgListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext;
    private LayoutInflater mInflater;
    private List<BankCardListBean> mList;//BankCardListBean可以根據自己要求設定
    private String num;
    private boolean isOnlySelectBankCard;

    public BankMsgListAdapter(Context context, List<BankCardListBean> list,boolean isOnlySelectBankCard) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mList = list;
        this.isOnlySelectBankCard = isOnlySelectBankCard;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new BankMsgViewHolder(mInflater.inflate(R.layout.adapter_bank_msg_list_item,parent,false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if(holder instanceof BankMsgViewHolder){
            BankCardListBean bankCardListBean = mList.get(position);
            String bankCode = bankCardListBean.getcBankCode();
            if(!StringUtils.isEmpty(bankCode)){
                int drawable = BankUtil.logoForBankCode(bankCode);
                if (drawable != 0) {
                    ((BankMsgViewHolder) holder).ivBankIcon.setImageResource(drawable);
                }
            }
            String cardNo = bankCardListBean.getcCardNo();
            if (!StringUtils.isEmpty(cardNo) && cardNo.length()>4){
                num = cardNo.substring(cardNo.length()-4,cardNo.length());
            }
            String bankName = bankCardListBean.getcBankName();
            if (!StringUtils.isEmpty(bankName)){
                ((BankMsgViewHolder)holder).tvBankName.setText(bankName + "("+ num +")");
            }

            if(isOnlySelectBankCard){
                ((BankMsgViewHolder)holder).ivDefaultIcon.setVisibility(View.GONE);
                ((BankMsgViewHolder)holder).tvWordDefault.setVisibility(View.GONE);
            }else {
                ((BankMsgViewHolder)holder).ivDefaultIcon.setVisibility(View.VISIBLE);
                ((BankMsgViewHolder)holder).tvWordDefault.setVisibility(View.VISIBLE);
                Boolean aDefault = bankCardListBean.getnDefault();
                if (aDefault){
                    ((BankMsgViewHolder)holder).ivDefaultIcon.setImageResource(R.drawable.yixuan);
                }else {
                    ((BankMsgViewHolder)holder).ivDefaultIcon.setImageResource(R.drawable.weixuan);
                }
            }


        }

    }

    @Override
    public int getItemCount() {
        return mList != null ? mList.size() : 0;
    }


    public class BankMsgViewHolder extends RecyclerView.ViewHolder {


        private final TextView itemDelete;//刪除按鈕
        private final ImageView ivBankIcon;//銀行圖示
        private final TextView tvBankName;//銀行名稱
        private final ImageView ivDefaultIcon;//預設圖示
        private final RelativeLayout rlBankMsg;//item的內容佈局
        private final TextView tvWordDefault;

        public BankMsgViewHolder(View inflate) {
            super(inflate);
            rlBankMsg = (RelativeLayout) inflate.findViewById(R.id.rl_bank_msg);
            tvBankName = (TextView) inflate.findViewById(R.id.tv_bank_name);
            ivBankIcon = (ImageView) inflate.findViewById(R.id.iv_bank_icon);
            ivDefaultIcon = (ImageView) inflate.findViewById(R.id.iv_default_icon);
            itemDelete = (TextView) inflate.findViewById(R.id.item_delete);
            tvWordDefault = (TextView) inflate.findViewById(R.id.tv_word_default);
            itemView.setTag(this);

        }
    }
    public void removeItem(int position) {
        mList.remove(position);
        notifyItemRemoved(position);
    }
}

item的具體佈局:

 <LinearLayout
        android:id="@+id/item_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RelativeLayout
    android:id="@+id/rl_bank_msg"
    android:layout_width="match_parent"
    android:layout_height="50dp">
    <ImageView
        android:id="@+id/iv_bank_icon"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_marginLeft="15dp"
        android:layout_centerVertical="true"/>
    <TextView
        android:id="@+id/tv_bank_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toEndOf="@+id/iv_bank_icon"
        android:layout_centerVertical="true"
        android:text="---"
        android:textColor="#000000"
        android:textSize="15dp" />
    <ImageView
        android:id="@+id/iv_default_icon"
        android:layout_toStartOf="@+id/tv_word_default"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true" />
    <TextView
        android:id="@+id/tv_word_default"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="15dp"
        android:text="預設"/>
</RelativeLayout>


    <TextView
        android:id="@+id/item_delete"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:background="@drawable/red"
        android:gravity="center"
        android:text="刪除"
        android:textColor="#ffffff"
        android:textSize="20sp" />
</LinearLayout>

然後初始化佈局,實現相應的方法如下

  rc_bank_list.setOnItemClickListener(new DeleteBankRecyclerView.OnItemClickListener() {

            @Override
            public void onItemClick(View view, ImageView imageView, int position) {
           // 點選操作
            }

            @Override
            public void onDeleteClick(int position) {
             //點選刪除操作,呼叫刪除方法或介面
            }
        });

以上是實現具體功能的主要程式碼塊,希望可以給需要的你提供一點點幫助!