android菜单回弹,Android ScrollLayout 下拉回弹

Android ScrollLayout 下拉回弹

import android.content.Context;

import android.graphics.PointF;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.widget.LinearLayout;

import android.widget.OverScroller;

public class ScrollLayout extends LinearLayout {

public static final int OVERSCROLL_DISTANCE = 200;

protected static final int INVALID_POINTER_ID = -1;

private OverScroller fScroller;

// The ‘active pointer’ is the one currently moving our object.

private int fTranslatePointerId = INVALID_POINTER_ID;

private PointF fTranslateLastTouch = new PointF();

private float firstX;

private float firstY;

public ScrollLayout(Context context, AttributeSet attrs) {

super(context, attrs);

this.initView(context, attrs);

}

public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

this.initView(context, attrs);

}

protected void initView(Context context, AttributeSet attrs) {

fScroller = new OverScroller(this.getContext());

this.setOverScrollMode(OVER_SCROLL_ALWAYS);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

int action = ev.getAction();

switch (action & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_MOVE: {

final float translateX = ev.getX();

final float translateY = ev.getY();

//距离小于5认为是单击事件,传递给子控件

if ((firstX - translateX < -5) || (firstX - translateX > 5) ||

(firstY - translateY < -5) || (firstY - translateY > 5)) {

return true;

} else {

return false;

}

}

case MotionEvent.ACTION_DOWN: {

if (!fScroller.isFinished())

fScroller.abortAnimation();

final float x = ev.getX();

final float y = ev.getY();

firstX = x;

firstY = y;

fTranslateLastTouch.set(x, y);

//记录第一个手指按下时的ID

fTranslatePointerId = ev.getPointerId(0);

return false;

}

default: {

return false;

}

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

final int action = event.getAction();

switch (action & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN: {

if (!fScroller.isFinished())

fScroller.abortAnimation();

final float x = event.getX();

final float y = event.getY();

fTranslateLastTouch.set(x, y);

//记录第一个手指按下时的ID

fTranslatePointerId = event.getPointerId(0);

break;

}

case MotionEvent.ACTION_MOVE: {

/**

* 取第一个触摸点的位置

*/

final int pointerIndexTranslate = event.findPointerIndex(fTranslatePointerId);

if (pointerIndexTranslate >= 0) {

float translateX = event.getX(pointerIndexTranslate);

float translateY = event.getY(pointerIndexTranslate);

//Log.i("com.zte.allowance", "fTranslatePointerId = " + fTranslatePointerId);

/**

* deltaX 将要在X轴方向上移动距离

* scrollX 滚动deltaX之前,x轴方向上的偏移

* scrollRangeX 在X轴方向上最多能滚动的距离

* maxOverScrollX 在x轴方向上,滚动到边界时,还能超出的滚动距离

*/

//Log.i("com.zte.allowance", "delta y = " + (fTranslateLastTouch.y - translateY));

this.overScrollBy(

(int) (fTranslateLastTouch.x - translateX),

(int) (fTranslateLastTouch.y - translateY) / 4,

this.getScrollX(),

this.getScrollY(),

0,

0,

0,

OVERSCROLL_DISTANCE,

true);

fTranslateLastTouch.set(translateX, translateY);

this.invalidate();

}

break;

}

case MotionEvent.ACTION_UP: {

/**

* startX 回滚开始时x轴上的偏移

* minX 和maxX 当前位置startX在minX和manX之 间时就不再回滚

*

* 此配置表示X和Y上的偏移都必须复位到0

*/

if (fScroller.springBack(this.getScrollX(), this.getScrollY(), 0, 0, 0, 0))

this.invalidate();

fTranslatePointerId = INVALID_POINTER_ID;

break;

}

}

return true;

}

@Override

public void computeScroll() {

if (fScroller != null && fScroller.computeScrollOffset()) {

int oldX = this.getScrollX();

int oldY = this.getScrollY();

/**

* 根据动画开始及持续时间计算出当前时间下,view的X.Y方向上的偏移量

* 参见OverScroller computeScrollOffset 的SCROLL_MODE

*/

int x = fScroller.getCurrX();

int y = fScroller.getCurrY();

if (oldX != x || oldY != y) {

//Log.i("com.zte.allowance", oldY + " " + y);

this.overScrollBy(

x - oldX,

(y - oldY),

oldX,

oldY,

0,

0,

0,

OVERSCROLL_DISTANCE,

false);

}

this.postInvalidate();

}

}

@Override

protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {

// Treat animating scrolls differently; see #computeScroll() for why.

if (!fScroller.isFinished()) {

super.scrollTo(scrollX, scrollY);

if (clampedX || clampedY) {

fScroller.springBack(this.getScrollX(), this.getScrollY(), 0, 0, 0, 0);

}

} else {

super.scrollTo(scrollX, scrollY);

}

awakenScrollBars();

}

@Override

protected int computeHorizontalScrollExtent() {

return this.getWidth();

}

@Override

protected int computeHorizontalScrollOffset() {

return this.getScrollX();

}

@Override

protected int computeVerticalScrollExtent() {

return this.getHeight();

}

@Override

protected int computeVerticalScrollOffset() {

return this.getScrollY();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值