編輯:關於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和布局的代碼太簡單我就不放出來了,大家可以到源碼裡看看有什麼

Android中EditText顯示明文與密碼的兩種方式
效果圖如下所述:布局<?xml version=1.0 encoding=utf-8?><LinearLayoutxmlns:andro
打飛機游戲終極BOSS Android實戰打飛機游戲完結篇
本文實例為大家分享了打飛機游戲BOSS以及勝利失敗頁面設計的Android代碼,具體內容如下修改子彈類:public class Bullet { //子彈圖片資源 pu
MVP架構實踐
一.MVP理論簡介1.為何要在android中引入MVP??在Android項目中,Activity和Fragment占據了大部分的開發工作。而MVP設計模式可以優化Ac
OpenCV實現圖像亮區擴張
效果圖源碼KqwOpenCVBlurDemo亮區擴張,也叫膨脹,要實現這樣的效果,我們可以選取一個合適大小的核,用被核覆蓋的最大值代替錨點像素。膨脹可以用來融合可能被分割