Nanfeng

Notes on software development, code, and curious ideas

Resolving PageView and ScrollView Touch Conflicts in Cocos Creator

A screen may need horizontal page switching and vertical scrolling at the same time. When a ScrollView is nested inside a PageView, both controls may compete for the same touch gesture.

The hierarchy in this example is:

PageView and ScrollView hierarchy

Without extra handling, vertical scrolling works inside the white ScrollView area, but horizontal page switching does not. The solution below measures the gesture direction and explicitly changes pages when horizontal movement exceeds a threshold.

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
public initView() {
const node = this._view._ScrollC_game.node;
node.on(Node.EventType.TOUCH_START, this.touchStart, this);
node.on(Node.EventType.TOUCH_MOVE, this.touchMove, this);
node.on(Node.EventType.TOUCH_END, this.touchEnd, this);
}

public touchStart(event) {
this.canForward = true;
this.startPosition = event.getLocation();
this.pageIndex = this._view._PageC_record.getCurrentPageIndex();
}

public touchMove(event) {
if (!this.canForward) return;

const current = event.getLocation();
const distanceX = current.x - this.startPosition.x;

if (Math.abs(distanceX) > 50) {
const pages = this._view._PageC_record.getPages();
const target = distanceX > 0
? this.pageIndex - 1
: this.pageIndex + 1;
const clamped = Math.max(0, Math.min(target, pages.length - 1));

this._view._PageC_record.scrollToPage(clamped);
this.canForward = false;
}
}

public touchEnd(event) {
const end = event.getLocation();
const distanceX = end.x - this.startPosition.x;
const distanceY = end.y - this.startPosition.y;

if (Math.abs(distanceX) < 50 && Math.abs(distanceY) < 50) {
console.log('The gesture was a tap');
}
}

The canForward flag prevents one gesture from triggering multiple page changes, and clamping prevents an invalid page index.

PageView and ScrollView working together
+