View自带的两个方法
左加右减,上加下减
package com.abilix.learn.dashpinyinisland1.view;
import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ScrollView;
import android.widget.Scroller;
/**
* Created by yanghd on 2017/6/9.
*/
public class SlowScrollView extends ScrollView {
private Scroller mScroller;
public SlowScrollView(Context context) {
this(context,null);
}
public SlowScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// 第一步,创建Scroller的实例
mScroller = new Scroller(context);
setUpBorder(2000);
ViewConfiguration configuration = ViewConfiguration.get(context);
// 获取TouchSlop值
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
}
public SlowScrollView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
}
//调用此方法滚动到目标位置 duration滚动时间
public void smoothScrollToSlow(int fx, int fy, int duration) {
int dx = fx - getScrollX();//mScroller.getFinalX(); 普通view使用这种方法
int dy = fy - getScrollY(); //mScroller.getFinalY();
smoothScrollBySlow(dx, dy, duration);
}
//调用此方法设置滚动的相对偏移
public void smoothScrollBySlow(int dx, int dy, int duration) {
//设置mScroller的滚动偏移量
mScroller.startScroll(getScrollX(), getScrollY(), dx, dy, duration);//scrollView使用的方法(因为可以触摸拖动)
// mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, duration); //普通view使用的方法
invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
}
@Override
public void computeScroll() {
//先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset()) {
//这里调用View的scrollTo()完成实际的滚动
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//必须调用该方法,否则不一定能看到滚动效果
postInvalidate();
}
super.computeScroll();
}
/**
* 滑动事件,这是控制手指滑动的惯性速度
*/
@Override
public void fling(int velocityY) {
super.fling(velocityY / 400);
}
// ------------------- 新增方法 ------------------
/**
* 手机当时所处的屏幕坐标
*/
private float mYMove;
/**
* 上次触发ACTION_MOVE事件时的屏幕坐标
*/
private float mYLastMove;
/**
* 界面可滚动的上边界
*/
private int upBorder;
/**
* 手机按下时的屏幕坐标
*/
private float mYDown;
/**
* 判定为拖动的最小移动像素数
*/
private int mTouchSlop;
/* @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mYDown = ev.getRawY();
mYLastMove = mYDown;
Log.d("SlowScrollView", "拦截Down");
break;
case MotionEvent.ACTION_MOVE:
mYMove = ev.getRawY();
float diff = Math.abs(mYMove - mYDown);
mYLastMove = mYMove;
// 当手指拖动值大于TouchSlop值时,认为应该进行滚动,拦截子控件的事件
if (diff > mTouchSlop) {
Log.d("SlowScrollView", "diff:" + diff);
Log.d("SlowScrollView", "mTouchSlop:" + mTouchSlop);
Log.d("SlowScrollView", "拦截Move");
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Log.d("SlowScrollView", "执行Move");
mYMove = event.getRawY();
int scrolledY = (int) (mYLastMove - mYMove);
if (getScrollY() + scrolledY < upBorder) {
scrollTo(0, upBorder);
return true;
}
scrollBy(scrolledY, 0);
mYLastMove = mYMove;
break;
case MotionEvent.ACTION_UP:
Log.d("SlowScrollView", "执行Up");
/* // 当手指抬起时,根据当前的滚动值来判定应该滚动到哪个子控件的界面
int targetIndex = (getScrollX() + getWidth() / 2) / getWidth();
int dx = targetIndex * getWidth() - getScrollX();
// 第二步,调用startScroll()方法来初始化滚动数据并刷新界面
mScroller.startScroll(getScrollX(), 0, dx, 0);
invalidate();*/
break;
}
return super.onTouchEvent(event);
}
public void setUpBorder(int upBorder) {
this.upBorder = upBorder;
}
}
其实可以直接不重写 onInterceptTouchEvent 方法;