Android recyclerView items的側滑刪除以及點選事件處理
阿新 • • 發佈:2018-12-17
最近專案中需要實現銀行卡側滑刪除以及選擇預設無法刪除的效果,需求效果圖如下:
其實就是一個自定義的列表實現,這裡我用的是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) {
//點選刪除操作,呼叫刪除方法或介面
}
});
以上是實現具體功能的主要程式碼塊,希望可以給需要的你提供一點點幫助!