編輯:關於Android編程
最近學習了如何做一個像QQ的左滑RecyclerView的item顯示選項的,主要是用到Scroller
定義好一些要用的的變量
重寫構造方法,把前兩個構造方法改為如下,使無論如何構造都要執行第三個構造方法
在第三個構造方法裡初始化Scroller
public class LeftSwipeMenuRecyclerView extends RecyclerView { //置頂按鈕 private TextView tvTop; //刪除按鈕 private TextView tvDelete; //item相應的布局 private LinearLayout mItemLayout; //菜單的最大寬度 private int mMaxLength; //上一次觸摸行為的x坐標 private int mLastX; //上一次觸摸行為的y坐標 private int mLastY; //當前觸摸的item的位置 private int mPosition; //是否在垂直滑動列表 private boolean isDragging; //item是在否跟隨手指移動 private boolean isItemMoving; //item是否開始自動滑動 private boolean isStartScroll; //左滑菜單狀態 0:關閉 1:將要關閉 2:將要打開 3:打開 private int mMenuState; private static int MENU_CLOSED = 0; private static int MENU_WILL_CLOSED = 1; private static int MENU_OPEN = 2; private static int MENU_WILL_OPEN = 3; //實現彈性滑動,恢復 private Scroller mScroller; //item的事件監聽 private OnItemActionListener mListener; public LeftSwipeMenuRecyclerView(Context context) { this(context, null); } public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScroller = new Scroller(context, new LinearInterpolator()); }
event主要有以下幾個Action
ACTION_DOWN 手指接觸到屏幕 ACTION_MOVE 手指在屏幕滑動 ACTION_UP 手指離開屏幕一開始肯定要獲取x和y的相對坐標
int x= (int) event.getX(); int y= (int) event.getY();
然後接下來分別處理3個不同的行為
case MotionEvent.ACTION_DOWN: if (mMenuState == MENU_CLOSED) { //根據坐標獲得view View view = findChildViewUnder(x, y); if (view == null) { return false; } //獲得這個view的ViewHolder RVAdapter.Holder holder = (RVAdapter.Holder) getChildViewHolder(view); //獲得這個view的position mPosition = holder.getAdapterPosition(); //獲得這個view的整個布局 mItemLayout = holder.llLayout; //獲得這個view的刪除按鈕 tvDelete = holder.tvDelete; //這個view的整個置頂按鈕 tvTop = holder.tvTop; //兩個按鈕的寬度 mMaxLength = tvDelete.getWidth() + tvTop.getWidth(); //設置刪除按鈕點擊監聽 tvDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mItemLayout.scrollTo(0, 0); mMenuState =MENU_CLOSED; mListener.OnItemDelete(mPosition); } }); //設置置頂按鈕點擊監聽 tvTop.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mItemLayout.scrollTo(0, 0); mMenuState =MENU_CLOSED; mListener.OnItemTop(mPosition); } }); //如果是打開狀態,點擊其他就把當前menu關閉掉 } else if (mMenuState == MENU_OPEN) { mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200); invalidate(); mMenuState = MENU_CLOSED; //該點擊無效 return false; } else { return false; } break;
case MotionEvent.ACTION_MOVE: //計算偏移量 int dx = mLastX - x; int dy = mLastY - y; //當前滑動的x int scrollx = mItemLayout.getScrollX(); if (Math.abs(dx) > Math.abs(dy)) { isItemMoving = true; //超出左邊界則始終保持不動 if (scrollx + dx <= 0) { mItemLayout.scrollTo(0, 0); //滑動無效 return false; //超出右邊界則始終保持不動 } else if (scrollx + dx >= mMaxLength) { mItemLayout.scrollTo(mMaxLength, 0); //滑動無效 return false; } //菜單隨著手指移動 mItemLayout.scrollBy(dx, 0); //如果水平移動距離大於30像素的話,recyclerView不會上下滑動 }else if (Math.abs(dx) > 30){ return true; } //如果菜單正在打開就不能上下滑動 if (isItemMoving){ mLastX = x; mLastY = y; return true; } break;
case MotionEvent.ACTION_UP: //手指抬起時判斷是否點擊,靜止且有Listener才能點擊 if (!isItemMoving && !isDragging && mListener != null) { mListener.OnItemClick(mPosition); } isItemMoving = false; //等一下要移動的距離 int deltaX = 0; int upScrollx = mItemLayout.getScrollX(); //滑動距離大於1/2menu長度就自動展開,否則就關掉 if (upScrollx >= mMaxLength / 2) { deltaX = mMaxLength - upScrollx; mMenuState = MENU_WILL_OPEN; } else if (upScrollx < mMaxLength / 2) { deltaX = -upScrollx; mMenuState = MENU_WILL_CLOSED; } //知道我們為什麼不直接把mMenuState賦值為MENU_OPEN或者MENU_CLOSED嗎?因為滑動時有時間的,我們可以在滑動完成時才把狀態改為已經完成 mScroller.startScroll(upScrollx, 0, deltaX, 0, 200); isStartScroll = true; //刷新界面 invalidate(); break;
之後還要在onTouchEvent方法裡刷新坐標
//只有更新mLastX,mLastY數據才會准確 mLastX = x; mLastY = y; return super.onTouchEvent(e);
public void computeScroll() { //判斷scroller是否完成滑動 if (mScroller.computeScrollOffset()) { mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //這個很重要 invalidate(); //如果已經完成就改變狀態 } else if (isStartScroll) { isStartScroll = false; if (mMenuState == MENU_WILL_CLOSED) { mMenuState = MENU_CLOSED; } if (mMenuState == MENU_WILL_OPEN) { mMenuState = MENU_OPEN; } } }
@Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); //是否在上下滑動 isDragging = state == SCROLL_STATE_DRAGGING; }
//設置Listener public void setOnItemActionListener(OnItemActionListener onItemActionListener) { this.mListener = onItemActionListener; }
這個Listener是要自己新建的
public interface OnItemActionListener { void OnItemClick(int position); void OnItemTop(int position); void OnItemDelete(int position); }
這裡只展示回調實現部分,我這裡用的List是LinkedList,可以在第一位添加數據
rv.setOnItemActionListener(new OnItemActionListener() { //點擊 @Override public void OnItemClick(int position) { Toast.makeText(MainActivity.this,"Click"+position,Toast.LENGTH_SHORT).show(); } //置頂 @Override public void OnItemTop(int position) { //獲得當前位置的內容 String temp =list.get(position); //移除這個item list.remove(position); //把它添加到第一個 list.addFirst(temp); //更新數據源 adapter.notifyDataSetChanged(); } //刪除 @Override public void OnItemDelete(int position) { list.remove(position); //更新數據源 adapter.notifyDataSetChanged(); } });
Adapter和布局的代碼太簡單我就不放出來了,大家可以到源碼裡看看有什麼
效果圖如下所述:布局<?xml version=1.0 encoding=utf-8?><LinearLayoutxmlns:andro
本文實例為大家分享了打飛機游戲BOSS以及勝利失敗頁面設計的Android代碼,具體內容如下修改子彈類:public class Bullet { //子彈圖片資源 pu
一.MVP理論簡介1.為何要在android中引入MVP??在Android項目中,Activity和Fragment占據了大部分的開發工作。而MVP設計模式可以優化Ac
效果圖源碼KqwOpenCVBlurDemo亮區擴張,也叫膨脹,要實現這樣的效果,我們可以選取一個合適大小的核,用被核覆蓋的最大值代替錨點像素。膨脹可以用來融合可能被分割