pageView继承自viewgroup
它这里面的layout是水平走的
大致就是顺序layout子view的left+right 累和做到页面水平顺序排列
这些子 View 的 left/right 在 onLayout() 里确定,之后不再变
然后scrollTo,这个就是滑动
然后scrollX就是从哪里的坐标开始展示
scrollX = 0 时,屏幕显示 x=01080 的区域
scrollX = 1080 时,屏幕显示 x=1080
2160 的区域
依次类推吧

问题:wrap 时 scrollTo 必须穿过中间页
就它是从3到1,3 -> 2 -> 1这种的
思路1:中间drawChildren的时候跳过,然后自己特判计算一下duration改一下就好了,问题是这个不能慢慢拖+方向反了
思路2:修改trainsitionX
每个 View 最终在屏幕上的位置 = layout 位置 + translationX
屏幕渲染位置 = view.left + view.translationX left layout定了,改不了,但是translationX 可以改
正常情况(translationX = 0):
页0.left = 0 → 屏幕上 x=0
页1.left = 1080 → 屏幕上 x=1080
页2.left = 2160 → 屏幕上 x=2160

给页0设置 translationX = 3240:
页0.left = 0, translationX = 3240 → 屏幕上 x=0+3240 = 3240
页1.left = 1080, translationX = 0 → 屏幕上 x=1080
页2.left = 2160, translationX = 0 → 屏幕上 x=2160
说简单点,就是临时搬过来
思路简单,但是实现有点工程上的复杂性。因为你有一些屏幕限制需要突破,然后动画结束之后再该回去。
比如scrollTo 有范围限制
// PagedView 内部,scrollTo 会 clamp:
if (scroll < mMinScroll) scroll = mMinScroll; // 不能超出左边界
if (scroll > mMaxScroll) scroll = mMaxScroll; // 不能超出右边界

// 正常情况:
mMinScroll = 0 (页0的位置)
mMaxScroll = 2160 (页2的位置)

如果你想 scrollTo(3240),会被截到 2160,动画根本滚不过去。

所以必须临时扩大边界:

mSavedMaxScroll = mMaxScroll; // 保存原始值 2160
mMaxScroll = mSavedMaxScroll + 1080; // 扩大到 3240
// 现在 scrollTo(3240) 不会被截断了
动画结束后的归位
动画结束时 scrollX = 3240,页0在 x=3240。但真实状态应该是 scrollX=0 看页0
private void finalizeWrapScroll() {
// 1. 页0的 translationX 清零 → 回到 x=0
targetView.setTranslationX(0);

  // 2. 恢复滚动边界
  mMinScroll = mSavedMinScroll;  // 0
  mMaxScroll = mSavedMaxScroll;  // 2160

  // 3. 瞬间跳到页0的真实位置
  scrollTo(0);

}
一个非常严重的问题:scrollTo(0) 就这个归位,它会不会闪烁呢?
不会,因为:
归位前一瞬间:
scrollX = 3240,页0渲染在 x=3240
屏幕窗口在 32404320 → 显示页0
归位后一瞬间:
页0.translationX = 0 → 页0回到 x=0
scrollX = 0 → 屏幕窗口在 0
1080 → 显示页0
两帧看到的都是页0,用户感知不到切换
简单来说,就是我最后这两帧,实际上是一样的,只是属性略有不同而已
时间轴:
t0: scrollX=2160,显示页2,用户右滑

t1: 手指拖过右边界
→ startWrapDrag(0)
→ 页0.translationX = +3240(页0视觉上跑到 x=3240)
→ mMaxScroll = 3240(扩大边界)

  画布状态:
  x=0      x=1080    x=2160    x=3240
  (空白)    页1       页2       页0'
                     ↑ scrollX=2160,屏幕在这

t2: 手指继续拖 → scrollX 从 2160 向 3240 移动
屏幕窗口右移 → 页0 从右边探出来

t3: 手指松开 → snapToPageWrapped(0, velocity)
mScroller 从 scrollX=2500 滚到 3240

t4: 动画播放中
scrollX: 2500 → 2800 → 3100 → 3240
用户看到:页2 平滑滑走,页0 平滑滑入

t5: mScroller.isFinished() = true
→ finalizeWrapScroll()
→ 页0.translationX = 0(回到 x=0)
→ mMaxScroll = 2160(恢复边界)
→ scrollTo(0)(跳到真实位置)

  用户看到:还是页0,没有任何跳变