開局一張圖,先看看是不是想要的效果
沒錯,今天就要實現這種效果,首先,可以看出來,這個效果是由兩部分組成的,滑動的view以及背景view.重點就是滑動的View,並且分兩種情況,當滑動距離超過一半時,則順勢滑下去,沒有超過一半,則回彈到初始位置。
對於View跟隨手勢去滑動,當然是ViewDragHelper是比較合適的。我對這個類我也是第一次用,裏面還有很多東西沒有理解,只是簡單的去運用。主要是自定義View繼承自LinearLayout.
貼代碼,不多BB,看會應該都能懂。
public class SlideRightViewDragHelper extends LinearLayout {
private ViewDragHelper viewDragHelper;
private View child;
private Point childPosition = new Point();
private Point childEndPosition = new Point();
private OnReleasedListener onReleasedListener;
private int oldX;
public SlideRightViewDragHelper(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setTouchable(boolean isTouch) {
if (isTouch) {
//新建viewDragHelper ,viewGroup, 靈敏度,回調(子view的移動)
viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
oldX = left;
return Math.max(0, left);
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (oldX > getWidth() / 2) {
/*
*之所以沒這麼寫,是因爲在滑到最右邊之後,滑動的View就會被釋放,我通過 layout方法無法將view設置
*爲原位置,然後我必須又要把view在移回最左邊,但無法實現向右順勢滑動的效果,反正達不到預期的效果,
*後來就自己寫了個位移動畫,最終實現了想要的效果。
*/
// viewDragHelper.settleCapturedViewAt(childEndPosition.x, childEndPosition.y);
// invalidate(); //必須刷新,因爲其內部使用的是mScroller.startScroll,所以別忘了需要invalidate()以及結合computeScroll方法一起。
// if (onReleasedListener != null) {
// child.layout(childPosition.x, childPosition.y, getWidth(), getHeight());
// viewDragHelper.settleCapturedViewAt(childPosition.x, childPosition.y); //反彈
// onReleasedListener.onReleased();
// }
TranslateAnimation translateAnimation = new TranslateAnimation(0, childEndPosition.x, childPosition.y, childPosition.y);
translateAnimation.setDuration(500);
child.startAnimation(translateAnimation);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
onReleasedListener.onReleased(0, 0, getWidth(), getHeight());
}
}, 10);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
} else {//滑動距離不夠一半,回到初始位置
viewDragHelper.settleCapturedViewAt(childPosition.x, childPosition.y); //反彈
invalidate();//必須調用
}
super.onViewReleased(releasedChild, xvel, yvel);
}
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
});
} else {
viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return false;
}
});
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
child = getChildAt(0);
}
@Override //用viewDragHelper攔截-true
public boolean onInterceptTouchEvent(MotionEvent ev) {
return viewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override //viewDragHelper攔截事件
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);
return true;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//定位左側的座標
childPosition.x = child.getLeft();
childPosition.y = child.getTop();
//定位右側的座標
childEndPosition.x = child.getRight();
childEndPosition.y = child.getTop();
}
@Override
public void computeScroll() {
super.computeScroll();
if (viewDragHelper.continueSettling(true)) {
invalidate();
}
}
public void setOnReleasedListener(OnReleasedListener onReleasedListener) {
this.onReleasedListener = onReleasedListener;
}
public interface OnReleasedListener {
void onReleased(int left, int top, int right, int bottom);
}
}
主要重寫了ViewDragHelper的三個方法
tryCaptureView()試圖要捕捉的View 當返回true時,可對當前View進行操作,返回false,則不可操作
clampViewPositionHorizontal() 在水平滑動過程中,可以得到當前View的left值
onViewReleased() 當手指擡起的時候回走這個方法,但我總覺得當我滑到最右邊的時候,就會把我的View給釋放掉,這個方法還不是很懂
當View滑動到最右邊時,就會通過接口告知Activity當前view已經滑到最右邊,實現這個接口,並作出對應的操作。
dragHelper.setOnReleasedListener(new SlideRightViewDragHelper.OnReleasedListener() {
@Override
public void onReleased(final int left, final int top, final int right, final int bottom) {
//自己的操作
}
});
到這裏就結束了,這種功能也不是很難,前提是一定要多實踐才行。加油