PageView使用和分析

从我对使用经验和看源码上谈谈PageView使用的几个要点

PageView基本使用

tree

  • PageView_Horizental:PageView所在节点
  • View:通常这里放置Mask组件,如果不需要Mask,此节点也可省略
  • content:包含pages的节点

使用要点:

  • PageView的size决定了每个page将会移动到的位置,正常情况下根据方向的不同会移动到相对PageView居中的位置
  • 添加Page时一定要使用PageView的addPage方法,而不是拿到content节点addChild
  • 移动view节点是没有意义的,最好是让它在PageView居中的位置,这样不会出现意外
  • 由于PageView继承自ScrollView,一定要注意在初始状态时content的位置处在不会回弹的位置,否则位置将不正确
  • PageView的SizeMode初始状态设置好后最好不要改变,除非你知道自己在做什么
  • 自己手动设置content的padding没有意义,因为PageView自己进行了设置

接下来进行分析

SizeMode Free/Unified

  • Free:每一个Page可以是不一样的尺寸
  • Unified:所有Page统一尺寸

不管如何,只要设置正确,PageView根据设定,滑动时总会让当前那个Page移动到相对PageView居中的位置

深入分析:

PageView组件初始化SizeMode被改变时,会调用_syncSizeMode,从而对布局作了一些影响:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
_syncSizeMode: function () {
if (!this.content) { return; }
var layout = this.content.getComponent(cc.Layout);
if (layout) {
if (this._pages.length === 0) {
// 将 paddingLeft/paddingRight/paddingTop/paddingBottom 设置为0
layout.padding = 0;
}
else {
var lastPage = this._pages[this._pages.length - 1];
if (this.sizeMode === SizeMode.Free) {
if (this.direction === Direction.Horizontal) {
layout.paddingLeft = (this.node.width - this._pages[0].width) / 2;
layout.paddingRight = (this.node.width - lastPage.width) / 2;
}
else if (this.direction === Direction.Vertical) {
layout.paddingTop = (this.node.height - this._pages[0].height) / 2;
layout.paddingBottom = (this.node.height - lastPage.height) / 2;
}
}
}
layout._updateLayout();
}
},


...


// 刷新页面视图
_updatePageView: function () {
var pageCount = this._pages.length;

// 当页面数组变化时修改 content 大小
var layout = this.content.getComponent(cc.Layout);
if(layout && layout.enabled) {
layout._updateLayout();
}
if (this._curPageIdx >= pageCount) {
this._curPageIdx = pageCount === 0 ? 0 : pageCount - 1;
this._lastPageIdx = this._curPageIdx;
}
// 进行排序
for (var i = 0; i < pageCount; ++i) {
this._pages[i].setSiblingIndex(i);
if (this.direction === Direction.Horizontal) {
this._scrollCenterOffsetX[i] = Math.abs(this.content.x + this._pages[i].x);
}
else {
this._scrollCenterOffsetY[i] = Math.abs(this.content.y + this._pages[i].y);
}
}
// 刷新 indicator 信息与状态
if (this.indicator) {
this.indicator._refresh();
}
},

当SizeMode为Free时,PageView会把content的padding设置正确,同时会记录每一个page中心点位置的相对位移,以致于在滚动时能正确滚到相应位置

注意,从代码中可以看出:content的Layout组件中的padding不再受
开发者自己设置影响了(这是其中一个坑点)除非SizeMode设置
Unified**,并且在onLoad时content已经存在有子节点,这里
的代码设计非常不受控因此,最佳实践是:从不去设置content的Layout
组件中的padding,并且SizeMode设置后不再更改

快速滑动和滚动

  • 快速滑动:英文通常为swipe,通过惯性翻页
  • 滚动:慢速的滚动,当滚动放手时,惯性不够大时不会产生快速滑动,会由ScrollThreshold决定将要去到哪一页

PageView.js源码地址