1. 程式人生 > >安卓開發 類似於扣扣 刪除訊息 時,滑動調出選項的功能實現

安卓開發 類似於扣扣 刪除訊息 時,滑動調出選項的功能實現

package com.example.sjd.danmu; import android.content.Context; import android.graphics.Color; import android.support.v4.view.ViewConfigurationCompat; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import
android.view.ViewGroup; import android.widget.Scroller; /** * Created by sjd on 2017/2/15. */ public class ScrollerLayout extends ViewGroup { private static final String TAG = "ScrollerLayout"; Scroller mScroller; int touchSlop; private int vLeft; private int vRight; /** * 手機按下時的螢幕座標
*/ private float mXDown; /** * 手機當時所處的螢幕座標 */ private float mXMove; /** * 上次觸發ACTION_MOVE事件時的螢幕座標 */ private float mXLastMove; private int dx; public ScrollerLayout(Context context, AttributeSet attrs) { super(context, attrs); mScroller=new Scroller(context); ViewConfiguration viewConfiguration=ViewConfiguration.get
(context); touchSlop= viewConfiguration.getScaledPagingTouchSlop(); setBackgroundColor(Color.GREEN); } public ScrollerLayout(Context context) { super(context,null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); for (int i = 0; i < getChildCount(); i++) { measureChild(getChildAt(i),widthMeasureSpec,heightMeasureSpec); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if(changed){ for (int i = 0; i < getChildCount(); i++) { View v= getChildAt(i); if(i==1){ v.layout(getWidth(), 0, (i + 2) * v.getMeasuredWidth(), v.getMeasuredHeight()); }else { v.layout(i * v.getMeasuredWidth(), 0, (i + 1) * v.getMeasuredWidth(), v.getMeasuredHeight()); } Log.i(TAG, "onLayout:"+ i*v.getMeasuredWidth() +" " + (i+1)*v.getMeasuredWidth() + " " + v.getMeasuredHeight() ); } vLeft=getChildAt(0).getLeft(); vRight=getChildAt(getChildCount()-1).getRight(); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "onInterceptTouchEvent:1 "); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mXDown = ev.getRawX(); mXLastMove = mXDown; break; case MotionEvent.ACTION_MOVE: mXMove = ev.getRawX(); float diff = Math.abs(mXMove - mXDown); mXLastMove = mXMove; // 當手指拖動值大於TouchSlop值時,認為應該進行滾動,攔截子控制元件的事件 if (diff > touchSlop) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "onTouchEvent: "); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: return true; case MotionEvent.ACTION_MOVE: mXMove = event.getRawX(); int scrolledX = (int) (mXLastMove - mXMove); if (getScrollX() + scrolledX < vLeft) { scrollTo(vLeft, 0); Log.i(TAG, "onTouchEvent1: "+vLeft); return true; } else if (getScrollX() + getWidth() + scrolledX > vRight) { scrollTo(vRight - getWidth(), 0); Log.i(TAG, "onTouchEvent2: "+(vRight - getWidth())); return true; } scrollBy(scrolledX, 0); Log.i(TAG, "onTouchEvent3: "+scrolledX); mXLastMove = mXMove; break; case MotionEvent.ACTION_UP: // 當手指擡起時,根據當前的滾動值來判定應該滾動到哪個子控制元件的介面 int targetIndex = (getScrollX() + getWidth() / 2) / getWidth(); dx = targetIndex * getWidth() - getScrollX(); // 第二步,呼叫startScroll()方法來初始化滾動資料並重新整理介面 if(getScrollX()<660){ mScroller.startScroll(getScrollX(), 0, dx, 0); } else { mScroller.startScroll(getScrollX(), 0, 0, 0); } Log.i(TAG, "onTouchEvent4: "+getScrollX()+ " "+getWidth()); invalidate(); break; } return super.onTouchEvent(event); } void outSlide() { scrollTo(dx,0); mScroller.startScroll(dx,0,-dx,0); } @Override public void computeScroll() { // 第三步,重寫computeScroll()方法,並在其內部完成平滑滾動的邏輯 if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }