安卓開發 類似於扣扣 刪除訊息 時,滑動調出選項的功能實現
阿新 • • 發佈:2019-01-04
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();
}
}