系列文章
造轮子:滚轮选择器实现及原理解析(一)
造轮子:滚轮选择器实现及原理解析(二)
造轮子:滚轮选择器实现及原理解析(三)
造轮子:滚轮选择器实现及原理解析(源码)
回顾
造轮子:滚轮选择器实现及原理解析(一)
上一篇文章我们简单绘制出了基本框图,此篇我们开始尝试使其动起来
拆解动画
体验过滚轮选择器的同学应该能感受到,滚轮存在着多种动画,这次我们只处理和交互相关的动画,其他动画放到下一节分析
- 跟手动画 - 手拖动到哪就跟随滚动到哪
- 惯性动画 - 松手后一段时间内仍可滚动,速度慢慢降低
- 吸附动画 - 速度降低到一定数值时,使其吸附到就近的一个item上
跟手动画
说到跟手动画,那一定是放到touch事件里处理,我们的处理方式也和常规拖动监听一样简单,拖动时实时修改curY
的位置,并刷新页面。这里新增了一个scrollState
存储当前状态。
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 重置状态
scrollState = SCROLL_STATE_NORMAL;
lastY = event.getY();
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curY -= event.getY() - lastY;
// 调整y使其不超出边界
curY = adjustingY(curY);
lastY = event.getY();
invalidate();
break;
default:
break;
}
return true;
}
惯性动画
惯性动画当然离不开Scroller
,使用Scroller
传入速度很容易使其实时帮助计算出当前惯性距离
调整一下onTouch事件
public boolean onTouchEvent(MotionEvent event) {
// 速度监听
velocityTracker.addMovement(event);
switch (event.getAction()) {
...
case MotionEvent.ACTION_UP:
curY -= event.getY() - lastY;
// 调整y使其不超出边界
curY = adjustingY(curY);
lastY = event.getY();
// 计算速度,根据速度决定惯性滚动还是吸附
velocityTracker.computeCurrentVelocity(1000, 2000);
checkTouch((int) velocityTracker.getXVelocity(), (int) velocityTracker.getYVelocity());
break;
default:
break;
}
return true;
}
在调用了scroller.fling
方法后,会基于Y方向的速度进行实时计算,我们在computeScroll
方法里对当前y值进行计算赋值,逻辑类似于拖拽时的计算,代码就不放了,感兴趣的可以直接看源码。
吸附动画
在开始滚动但是速度不足的场景,或滚动时速度慢慢变慢的场景下,需要使其吸附到最近的item上,逻辑很简单,直接上代码
public void startAdsorbAnim() {
float y = curY;
int centerPosition = getCenterShowPosition(y);
float offsetY = adjustingY(y) - itemHeight * centerPosition;
int newPosition;
// 超出一半时吸附到下一个item
if (offsetY >= itemHeight / 2f) {
// 封装的动画,本质是ValueAnimator
manager.playAnim(KEY_PICKER_ADSORB_ANIM, curY, curY + itemHeight - offsetY);
newPosition = adjustingPosition(centerPosition + 1);
} else {
// 封装的动画,本质是ValueAnimator
manager.playAnim(KEY_PICKER_ADSORB_ANIM, curY, curY - offsetY);
newPosition = adjustingPosition(centerPosition);
}
if (pickerChangeListener != null && curPosition != newPosition) {
curPosition = newPosition;
pickerChangeListener.onPickerSelectedChanged(this, curPosition, data[curPosition], true);
}
}
至此,能够完成基本的动画,使其看起来起码像一个滚轮了,下一篇我们开始优化细节,使其易用,美观
本文由 bt 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。