基本原理:每次滑动调用invalidate(),重新绘制item
onTouchEvent
滑动组件 先从onTouchEvent 入手
3,2,1上代码
if (mDisallowTouch) { // 不允许触摸
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (onPickerViewListener != null) {
onPickerViewListener.onTouchDown(ScrollPickerView.this);
}
onTouchDown();
break;
case MotionEvent.ACTION_UP:
if (onPickerViewListener != null) {
onPickerViewListener.onTouchUp(ScrollPickerView.this);
}
onTouchUp();
break;
}
//down 点击会被onTouchEvent消耗
if (mGestureDetector.onTouchEvent消耗(event)) {
return true;
}
//处理move up事件
switch (event.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
// 计算down---up之间移动的距离
// 区分方向是水平还是竖直
//start
if (mIsHorizontal) {
if (Math.abs(event.getX() - mLastMoveX) < 0.1f) {
return true;
}
mMoveLength += event.getX() - mLastMoveX;
} else {
if (Math.abs(event.getY() - mLastMoveY) < 0.1f) {
return true;
}
mMoveLength += event.getY() - mLastMoveY;
}
mLastMoveY = event.getY();
mLastMoveX = event.getX();
//end
//处理滑过的情况,重新移回中间
checkCirculation();
//重绘,使item位置更新
invalidate();
break;
case MotionEvent.ACTION_UP:
mLastMoveY = event.getY();
mLastMoveX = event.getX();
moveToCenter();
onTouchUp();
break;
}
return true;
解析
设置禁止触摸
设置mDisallowTouch后无法响应事件,但是事件仍然被消耗了。 可以通过这个方法设置
public void setDisallowTouch(boolean disallowTouch) {
mDisallowTouch = disallowTouch;
}
onTouchDown onTouchUp
onTouchDown();onTouchUp();是两个空方法,可以通过继承在该方法里面实现按下和抬起的处理逻辑。除此之外还可以通过setOnPickerViewListener这个方法来设置listener,同样也可以达到onTouchDown();onTouchUp();的效果。
mGestureDetector消耗了Down事件和单击事件
private class FlingOnGestureListener extends GestureDetector.SimpleOnGestureListener {
private boolean mIsScrollingLastTime = false;
@Override
public boolean onDown(MotionEvent e) {
..
.....防止拦截触摸事件......
..
//isScrolling()判断是否在滑动
mIsScrollingLastTime = isScrolling(); // 记录是否从滚动状态终止
// 点击时取消所有滚动效果
cancelScroll();
mLastMoveY = e.getY();
mLastMoveX = e.getX();
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, final float velocityY) {
// 惯性滑动
.........
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (isTouchFromOut) {
isTouchFromOut = false;
return true;
}
mLastMoveY = e.getY();
mLastMoveX = e.getX();
float lastMove = 0;
if (isHorizontal()) {
mCenterPoint = mCenterX;
lastMove = mLastMoveX;
} else {
mCenterPoint = mCenterY;
lastMove = mLastMoveY;
}
if (mCanTap && !isScrolling() && !mIsScrollingLastTime) {
//如果单击的位置在当前选择的item则执行onClick事件
if (lastMove >= mCenterPoint && lastMove <= mCenterPoint + mItemSize) {
performClick();
} else if (lastMove < mCenterPoint) {
...............
//调用autoScrollTo 移动指定距离,这个距离正好会使指定的item移到中间
...............
}
} else {
//若该view正在滑动,则当前点击会使滑动停下,并移动item到中间
moveToCenter();
}
return true;
}
}
每次movecenter时都会终止上一次的scroll过程
设置是否循环滚动
setIsCirculation(boolean)
获取当前选择的位置 从0开始
getSelectedPosition
设置选中item的背景
setCenterItemBackground
滚动到指定位置
autoScrollToPosition
设置选择item的监听
setOnPickerViewListener
可以监听这些事件
public interface OnPickerViewListener {
void onSelected(ScrollPickerView scrollPickerView, int position);
void onTouchDown(ScrollPickerView scrollPickerView);
void onTouchUp(ScrollPickerView scrollPickerView);
}
设置item数据
setData(List<? extends T> data)
设置当前相对位置
centerPosition是当前可见数量的位置,比如说当前可见3个item,总的item的数量是10个, centerPosition = 1,是可见item的第二个item,是相对于可见item来说的.
而int mSelected表示绝对item位置。
setCenterPosition(int centerPosition)