12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339 |
- /**
- * ***************************************
- *
- * @format
- * @author kL <klk0@qq.com>
- * @date 2019/6/6
- * @doc 列表组件.
- * @end
- */
- const {ccclass, property, disallowMultiple, menu, executionOrder, requireComponent} = cc._decorator
- import ListItem from './ListItem'
- enum TemplateType {
- NODE = 1,
- PREFAB = 2,
- }
- enum SlideType {
- NORMAL = 1, // 普通
- ADHERING = 2, // 粘附模式,将强制关闭滚动惯性
- PAGE = 3, // 页面模式,将强制关闭滚动惯性
- }
- export enum SelectedType {
- NONE = 0,
- SINGLE = 1, // 单选
- MULT = 2, // 多选
- }
- @ccclass
- @disallowMultiple()
- @menu('自定义组件/List')
- @requireComponent(cc.ScrollView)
- // 脚本生命周期回调的执行优先级。小于 0 的脚本将优先执行,大于 0 的脚本将最后执行。该优先级只对 onLoad, onEnable, start, update 和 lateUpdate 有效,对 onDisable 和 onDestroy 无效。
- @executionOrder(-5000)
- export default class List extends cc.Component {
- // 模板类型
- @property({type: cc.Enum(TemplateType), tooltip: CC_DEV && '模板类型'})
- private templateType: TemplateType = TemplateType.NODE
- // 模板Item(Node)
- @property({
- type: cc.Node,
- tooltip: CC_DEV && '模板Item',
- visible() {
- return this.templateType == TemplateType.NODE
- },
- })
- public tmpNode: cc.Node = null
- // 模板Item(Prefab)
- @property({
- type: cc.Prefab,
- tooltip: CC_DEV && '模板Item',
- visible() {
- return this.templateType == TemplateType.PREFAB
- },
- })
- public tmpPrefab: cc.Prefab = null
- // 滑动模式
- @property()
- private _slideMode: SlideType = SlideType.NORMAL
- @property({
- type: cc.Enum(SlideType),
- tooltip: CC_DEV && '滑动模式',
- })
- set slideMode(val: SlideType) {
- this._slideMode = val
- }
- get slideMode() {
- return this._slideMode
- }
- // 翻页作用距离
- @property({
- type: cc.Float,
- range: [0, 1, 0.1],
- tooltip: CC_DEV && '翻页作用距离',
- slide: true,
- visible() {
- return this._slideMode == SlideType.PAGE
- },
- })
- public pageDistance: number = 0.3
- // 页面改变事件
- @property({
- type: cc.Component.EventHandler,
- tooltip: CC_DEV && '页面改变事件',
- visible() {
- return this._slideMode == SlideType.PAGE
- },
- })
- private pageChangeEvent: cc.Component.EventHandler = new cc.Component.EventHandler()
- // 是否为虚拟列表(动态列表)
- @property()
- private _virtual: boolean = true
- @property({
- type: cc.Boolean,
- tooltip: CC_DEV && '是否为虚拟列表(动态列表)',
- })
- set virtual(val: boolean) {
- if (val != null) {
- this._virtual = val
- }
- if (!CC_DEV && this._numItems != 0) {
- this._onScrolling()
- }
- }
- get virtual() {
- return this._virtual
- }
- // 是否为循环列表
- @property({
- tooltip: CC_DEV && '是否为循环列表',
- visible() {
- let val: boolean = this.virtual && this.slideMode == SlideType.NORMAL
- if (!val) {
- this.cyclic = false
- }
- return val
- },
- })
- public cyclic: boolean = false
- // 缺省居中
- @property({
- tooltip: CC_DEV && 'Item数量不足以填满Content时,是否居中显示Item(不支持Grid布局)',
- visible() {
- return this.virtual
- },
- })
- public lackCenter: boolean = false
- // 缺省可滑动
- @property({
- tooltip: CC_DEV && 'Item数量不足以填满Content时,是否可滑动',
- visible() {
- let val: boolean = this.virtual && !this.lackCenter
- if (!val) {
- this.lackSlide = false
- }
- return val
- },
- })
- public lackSlide: boolean = false
- // 刷新频率
- @property({type: cc.Integer})
- private _updateRate: number = 0
- @property({
- type: cc.Integer,
- range: [0, 6, 1],
- tooltip: CC_DEV && '刷新频率(值越大刷新频率越低、性能越高)',
- slide: true,
- })
- set updateRate(val: number) {
- if (val >= 0 && val <= 6) {
- this._updateRate = val
- }
- }
- get updateRate() {
- return this._updateRate
- }
- // 分帧渲染(每帧渲染的Item数量(<=0时关闭分帧渲染))
- @property({
- type: cc.Integer,
- range: [0, 12, 1],
- tooltip: CC_DEV && '逐帧渲染时,每帧渲染的Item数量(<=0时关闭分帧渲染)',
- slide: true,
- })
- public frameByFrameRenderNum: number = 0
- // 渲染事件(渲染器)
- @property({
- type: cc.Component.EventHandler,
- tooltip: CC_DEV && '渲染事件(渲染器)',
- })
- private renderEvent: cc.Component.EventHandler = new cc.Component.EventHandler()
- // 选择模式
- @property({
- type: cc.Enum(SelectedType),
- tooltip: CC_DEV && '选择模式',
- })
- public selectedMode: SelectedType = SelectedType.NONE
- @property({
- tooltip: CC_DEV && '是否重复响应单选事件',
- visible() {
- return this.selectedMode == SelectedType.SINGLE
- },
- })
- public repeatEventSingle: boolean = false
- // 触发选择事件
- @property({
- type: cc.Component.EventHandler,
- tooltip: CC_DEV && '触发选择事件',
- visible() {
- return this.selectedMode > SelectedType.NONE
- },
- })
- private selectedEvent: cc.Component.EventHandler = null // new cc.Component.EventHandler();
- // 当前选择id
- private _selectedId: number = -1
- private _lastSelectedId: number
- public maxMutSelected: number = -1
- private multSelected: number[]
- set selectedId(val: number) {
- let t: any = this
- let item: any
- switch (t.selectedMode) {
- case SelectedType.SINGLE: {
- if (!t.repeatEventSingle && val == t._selectedId) {
- return
- }
- item = t.getItemByListId(val)
- // if (!item && val >= 0)
- // return;
- let listItem: ListItem
- if (t._selectedId >= 0) {
- t._lastSelectedId = t._selectedId
- } else {
- // 如果<0则取消选择,把_lastSelectedId也置空吧,如果以后有特殊需求再改吧。
- t._lastSelectedId = null
- }
- t._selectedId = val
- if (item) {
- listItem = item.getComponent(ListItem)
- listItem.selected = true
- }
- if (t._lastSelectedId >= 0 && t._lastSelectedId != t._selectedId) {
- let lastItem: any = t.getItemByListId(t._lastSelectedId)
- if (lastItem) {
- lastItem.getComponent(ListItem).selected = false
- }
- }
- if (t.selectedEvent) {
- cc.Component.EventHandler.emitEvents(
- [t.selectedEvent],
- item,
- val % this._actualNumItems,
- t._lastSelectedId == null ? null : t._lastSelectedId % this._actualNumItems,
- )
- }
- break
- }
- case SelectedType.MULT: {
- item = t.getItemByListId(val)
- if (!item) {
- return
- }
- let listItem = item.getComponent(ListItem)
- if (t._selectedId >= 0) {
- t._lastSelectedId = t._selectedId
- }
- t._selectedId = val
- let bool: boolean = !listItem.selected
- let isMaxMut = t.maxMutSelected > 0 && t.multSelected.length >= t.maxMutSelected
- if (!(isMaxMut && bool)) listItem.selected = bool
- let sub: number = t.multSelected.indexOf(val)
- if (bool && sub < 0 && !isMaxMut) {
- t.multSelected.push(val)
- } else if (!bool && sub >= 0) {
- t.multSelected.splice(sub, 1)
- }
- if (t.selectedEvent) {
- cc.Component.EventHandler.emitEvents(
- [t.selectedEvent],
- item,
- val % this._actualNumItems,
- t._lastSelectedId == null ? null : t._lastSelectedId % this._actualNumItems,
- listItem.selected,
- isMaxMut && bool,
- )
- }
- break
- }
- }
- }
- get selectedId() {
- return this._selectedId
- }
- private _forceUpdate: boolean = false
- private _align: number
- private _horizontalDir: number
- private _verticalDir: number
- private _startAxis: number
- private _alignCalcType: number
- public content: cc.Node
- private firstListId: number
- public displayItemNum: number
- private _updateDone: boolean = true
- private _updateCounter: number
- public _actualNumItems: number
- private _cyclicNum: number
- private _cyclicPos1: number
- private _cyclicPos2: number
- // 列表数量
- @property({
- serializable: false,
- })
- private _numItems: number = 0
- set numItems(val: number) {
- let t = this
- if (!t.checkInited(false)) {
- return
- }
- if (val == null || val < 0) {
- cc.error('numItems set the wrong::', val)
- return
- }
- t._actualNumItems = t._numItems = val
- t._forceUpdate = true
- if (t._virtual) {
- t._resizeContent()
- if (t.cyclic) {
- t._numItems = t._cyclicNum * t._numItems
- }
- t._onScrolling()
- if (!t.frameByFrameRenderNum && t.slideMode == SlideType.PAGE) {
- t.curPageNum = t.nearestListId
- }
- } else {
- let layout: cc.Layout = t.content.getComponent(cc.Layout)
- if (layout) {
- layout.enabled = true
- }
- t._delRedundantItem()
- t.firstListId = 0
- if (t.frameByFrameRenderNum > 0) {
- // 先渲染几个出来
- let len: number = t.frameByFrameRenderNum > t._numItems ? t._numItems : t.frameByFrameRenderNum
- for (let n: number = 0; n < len; n++) {
- t._createOrUpdateItem2(n)
- }
- if (t.frameByFrameRenderNum < t._numItems) {
- t._updateCounter = t.frameByFrameRenderNum
- t._updateDone = false
- }
- } else {
- for (let n: number = 0; n < val; n++) {
- t._createOrUpdateItem2(n)
- }
- t.displayItemNum = val
- }
- }
- }
- get numItems() {
- return this._actualNumItems
- }
- private _inited: boolean = false
- private _scrollView: cc.ScrollView
- get scrollView() {
- return this._scrollView
- }
- private _layout: cc.Layout
- private _resizeMode: cc.Layout.ResizeMode
- private _topGap: number
- private _rightGap: number
- private _bottomGap: number
- private _leftGap: number
- private _columnGap: number
- private _lineGap: number
- private _colLineNum: number
- private _lastDisplayData: number[]
- public displayData: any[]
- private _pool: cc.NodePool
- private _itemTmp: any
- private _needUpdateWidget: boolean = false
- private _itemSize: cc.Size
- private _sizeType: boolean
- public _customSize: any
- private frameCount: number
- private _aniDelRuning: boolean = false
- private viewTop: number
- private viewRight: number
- private viewBottom: number
- private viewLeft: number
- private _doneAfterUpdate: boolean = false
- private elasticTop: number
- private elasticRight: number
- private elasticBottom: number
- private elasticLeft: number
- private scrollToListId: number
- private adhering: boolean = false
- private _adheringBarrier: boolean = false
- private nearestListId: number
- public curPageNum: number = 0
- private _beganPos: number
- private _scrollPos: number
- private _scrollToListId: number
- private _scrollToEndTime: number
- private _scrollToSo: any
- private _lack: boolean
- private _allItemSize: number
- private _allItemSizeNoEdge: number
- private _scrollItem: any // 当前控制 ScrollView 滚动的 Item
- // ----------------------------------------------------------------------------
- public onLoad() {
- this._init()
- }
- public onDestroy() {
- let t: any = this
- if (t._itemTmp && t._itemTmp.isValid) {
- t._itemTmp.destroy()
- }
- if (t.tmpNode && t.tmpNode.isValid) {
- t.tmpNode.destroy()
- }
- // let total = t._pool.size();
- while (t._pool.size()) {
- let node = t._pool.get()
- node.destroy()
- }
- // if (total)
- // cc.log('-----------------' + t.node.name + '<List> destroy node total num. =>', total);
- }
- public onEnable() {
- // if (!CC_EDITOR)
- this._registerEvent()
- this._init()
- }
- public onDisable() {
- // if (!CC_EDITOR)
- this._unregisterEvent()
- }
- // 注册事件
- public _registerEvent() {
- let t: any = this
- t.node.on(cc.Node.EventType.TOUCH_START, t._onTouchStart, t, true)
- t.node.on('touch-up', t._onTouchUp, t)
- t.node.on(cc.Node.EventType.TOUCH_CANCEL, t._onTouchCancelled, t, true)
- t.node.on('scroll-began', t._onScrollBegan, t, true)
- t.node.on('scroll-ended', t._onScrollEnded, t, true)
- t.node.on('scrolling', t._onScrolling, t, true)
- t.node.on(cc.Node.EventType.SIZE_CHANGED, t._onSizeChanged, t)
- }
- // 卸载事件
- public _unregisterEvent() {
- let t: any = this
- t.node.off(cc.Node.EventType.TOUCH_START, t._onTouchStart, t, true)
- t.node.off('touch-up', t._onTouchUp, t)
- t.node.off(cc.Node.EventType.TOUCH_CANCEL, t._onTouchCancelled, t, true)
- t.node.off('scroll-began', t._onScrollBegan, t, true)
- t.node.off('scroll-ended', t._onScrollEnded, t, true)
- t.node.off('scrolling', t._onScrolling, t, true)
- t.node.off(cc.Node.EventType.SIZE_CHANGED, t._onSizeChanged, t)
- }
- // 初始化各种..
- public _init() {
- let t: any = this
- if (t._inited) {
- return
- }
- t._scrollView = t.node.getComponent(cc.ScrollView)
- t.content = t._scrollView.content
- if (!t.content) {
- cc.error(t.node.name + "'s cc.ScrollView unset content!")
- return
- }
- t._layout = t.content.getComponent(cc.Layout)
- t._align = t._layout.type // 排列模式
- t._resizeMode = t._layout.resizeMode // 自适应模式
- t._startAxis = t._layout.startAxis
- t._topGap = t._layout.paddingTop // 顶边距
- t._rightGap = t._layout.paddingRight // 右边距
- t._bottomGap = t._layout.paddingBottom // 底边距
- t._leftGap = t._layout.paddingLeft // 左边距
- t._columnGap = t._layout.spacingX // 列距
- t._lineGap = t._layout.spacingY // 行距
- t._colLineNum // 列数或行数(非GRID模式则=1,表示单列或单行);
- t._verticalDir = t._layout.verticalDirection // 垂直排列子节点的方向
- t._horizontalDir = t._layout.horizontalDirection // 水平排列子节点的方向
- t.setTemplateItem(cc.instantiate(t.templateType == TemplateType.PREFAB ? t.tmpPrefab : t.tmpNode))
- // 特定的滑动模式处理
- if (t._slideMode == SlideType.ADHERING || t._slideMode == SlideType.PAGE) {
- t._scrollView.inertia = false
- t._scrollView._onMouseWheel = function () {
- return
- }
- }
- if (!t.virtual) {
- // lackCenter 仅支持 Virtual 模式
- t.lackCenter = false
- }
- t._lastDisplayData = [] // 最后一次刷新的数据
- t.displayData = [] // 当前数据
- t._pool = new cc.NodePool() // 这是个池子..
- t._forceUpdate = false // 是否强制更新
- t._updateCounter = 0 // 当前分帧渲染帧数
- t._updateDone = true // 分帧渲染是否完成
- t.curPageNum = 0 // 当前页数
- if (t.cyclic || 0) {
- t._scrollView._processAutoScrolling = this._processAutoScrolling.bind(t)
- t._scrollView._startBounceBackIfNeeded = function () {
- return false
- }
- // t._scrollView._scrollChildren = function () {
- // return false;
- // }
- }
- switch (t._align) {
- case cc.Layout.Type.HORIZONTAL: {
- switch (t._horizontalDir) {
- case cc.Layout.HorizontalDirection.LEFT_TO_RIGHT:
- t._alignCalcType = 1
- break
- case cc.Layout.HorizontalDirection.RIGHT_TO_LEFT:
- t._alignCalcType = 2
- break
- }
- break
- }
- case cc.Layout.Type.VERTICAL: {
- switch (t._verticalDir) {
- case cc.Layout.VerticalDirection.TOP_TO_BOTTOM:
- t._alignCalcType = 3
- break
- case cc.Layout.VerticalDirection.BOTTOM_TO_TOP:
- t._alignCalcType = 4
- break
- }
- break
- }
- case cc.Layout.Type.GRID: {
- switch (t._startAxis) {
- case cc.Layout.AxisDirection.HORIZONTAL:
- switch (t._verticalDir) {
- case cc.Layout.VerticalDirection.TOP_TO_BOTTOM:
- t._alignCalcType = 3
- break
- case cc.Layout.VerticalDirection.BOTTOM_TO_TOP:
- t._alignCalcType = 4
- break
- }
- break
- case cc.Layout.AxisDirection.VERTICAL:
- switch (t._horizontalDir) {
- case cc.Layout.HorizontalDirection.LEFT_TO_RIGHT:
- t._alignCalcType = 1
- break
- case cc.Layout.HorizontalDirection.RIGHT_TO_LEFT:
- t._alignCalcType = 2
- break
- }
- break
- }
- break
- }
- }
- // 清空 content
- // t.content.children.forEach((child: cc.Node) => {
- // child.removeFromParent();
- // if (child != t.tmpNode && child.isValid)
- // child.destroy();
- // });
- t.content.removeAllChildren()
- t._inited = true
- }
- /**
- * 为了实现循环列表,必须覆写cc.ScrollView的某些函数
- * @param {Number} dt
- */
- public _processAutoScrolling(dt: number) {
- // let isAutoScrollBrake = this._scrollView._isNecessaryAutoScrollBrake();
- let brakingFactor: number = 1
- this._scrollView['_autoScrollAccumulatedTime'] += dt * (1 / brakingFactor)
- let percentage: number = Math.min(
- 1,
- this._scrollView['_autoScrollAccumulatedTime'] / this._scrollView['_autoScrollTotalTime'],
- )
- if (this._scrollView['_autoScrollAttenuate']) {
- let time: number = percentage - 1
- percentage = time * time * time * time * time + 1
- }
- let newPosition: any = this._scrollView['_autoScrollStartPosition'].add(
- this._scrollView['_autoScrollTargetDelta'].mul(percentage),
- )
- let EPSILON: number = this._scrollView['getScrollEndedEventTiming']()
- let reachedEnd: boolean = Math.abs(percentage - 1) <= EPSILON
- // cc.log(reachedEnd, Math.abs(percentage - 1), EPSILON)
- let fireEvent: boolean = Math.abs(percentage - 1) <= this._scrollView['getScrollEndedEventTiming']()
- if (fireEvent && !this._scrollView['_isScrollEndedWithThresholdEventFired']) {
- this._scrollView['_dispatchEvent']('scroll-ended-with-threshold')
- this._scrollView['_isScrollEndedWithThresholdEventFired'] = true
- }
- // if (this._scrollView.elastic && !reachedEnd) {
- // let brakeOffsetPosition = newPosition.sub(this._scrollView._autoScrollBrakingStartPosition);
- // if (isAutoScrollBrake) {
- // brakeOffsetPosition = brakeOffsetPosition.mul(brakingFactor);
- // }
- // newPosition = this._scrollView._autoScrollBrakingStartPosition.add(brakeOffsetPosition);
- // } else {
- // let moveDelta = newPosition.sub(this._scrollView.getContentPosition());
- // let outOfBoundary = this._scrollView._getHowMuchOutOfBoundary(moveDelta);
- // if (!outOfBoundary.fuzzyEquals(cc.v2(0, 0), EPSILON)) {
- // newPosition = newPosition.add(outOfBoundary);
- // reachedEnd = true;
- // }
- // }
- if (reachedEnd) {
- this._scrollView['_autoScrolling'] = false
- }
- let deltaMove: any = newPosition.sub(this._scrollView.getContentPosition())
- // cc.log(deltaMove)
- this._scrollView['_moveContent'](this._scrollView['_clampDelta'](deltaMove), reachedEnd)
- this._scrollView['_dispatchEvent']('scrolling')
- // scollTo API controll move
- if (!this._scrollView['_autoScrolling']) {
- this._scrollView['_isBouncing'] = false
- this._scrollView['_scrolling'] = false
- this._scrollView['_dispatchEvent']('scroll-ended')
- }
- }
- // 设置模板Item
- public setTemplateItem(item: any) {
- if (!item) {
- return
- }
- let t: any = this
- t._itemTmp = item
- if (t._resizeMode == cc.Layout.ResizeMode.CHILDREN) {
- t._itemSize = t._layout.cellSize
- } else {
- t._itemSize = cc.size(item.width, item.height)
- }
- // 获取ListItem,如果没有就取消选择模式
- let com = item.getComponent(ListItem)
- let remove = false
- if (!com) {
- remove = true
- }
- // if (com) {
- // if (!com._btnCom && !item.getComponent(cc.Button)) {
- // remove = true;
- // }
- // }
- if (remove) {
- t.selectedMode = SelectedType.NONE
- }
- com = item.getComponent(cc.Widget)
- if (com && com.enabled) {
- t._needUpdateWidget = true
- }
- if (t.selectedMode == SelectedType.MULT) {
- t.multSelected = []
- }
- switch (t._align) {
- case cc.Layout.Type.HORIZONTAL:
- t._colLineNum = 1
- t._sizeType = false
- break
- case cc.Layout.Type.VERTICAL:
- t._colLineNum = 1
- t._sizeType = true
- break
- case cc.Layout.Type.GRID:
- switch (t._startAxis) {
- case cc.Layout.AxisDirection.HORIZONTAL:
- // 计算列数
- let trimW: number = t.content.width - t._leftGap - t._rightGap
- t._colLineNum = Math.floor((trimW + t._columnGap) / (t._itemSize.width + t._columnGap))
- t._sizeType = true
- break
- case cc.Layout.AxisDirection.VERTICAL:
- // 计算行数
- let trimH: number = t.content.height - t._topGap - t._bottomGap
- t._colLineNum = Math.floor((trimH + t._lineGap) / (t._itemSize.height + t._lineGap))
- t._sizeType = false
- break
- }
- break
- }
- }
- /**
- * 检查是否初始化
- * @param {Boolean} printLog 是否打印错误信息
- * @returns
- */
- public checkInited(printLog: boolean = true) {
- if (!this._inited) {
- if (printLog) {
- cc.error('List initialization not completed!')
- }
- return false
- }
- return true
- }
- // 禁用 Layout 组件,自行计算 Content Size
- public _resizeContent() {
- let t: any = this
- let result: number
- switch (t._align) {
- case cc.Layout.Type.HORIZONTAL: {
- if (t._customSize) {
- let fixed: any = t._getFixedSize(null)
- result =
- t._leftGap +
- fixed.val +
- t._itemSize.width * (t._numItems - fixed.count) +
- t._columnGap * (t._numItems - 1) +
- t._rightGap
- } else {
- result =
- t._leftGap + t._itemSize.width * t._numItems + t._columnGap * (t._numItems - 1) + t._rightGap
- }
- break
- }
- case cc.Layout.Type.VERTICAL: {
- if (t._customSize) {
- let fixed: any = t._getFixedSize(null)
- result =
- t._topGap +
- fixed.val +
- t._itemSize.height * (t._numItems - fixed.count) +
- t._lineGap * (t._numItems - 1) +
- t._bottomGap
- } else {
- result =
- t._topGap + t._itemSize.height * t._numItems + t._lineGap * (t._numItems - 1) + t._bottomGap
- }
- break
- }
- case cc.Layout.Type.GRID: {
- // 网格模式不支持居中
- if (t.lackCenter) {
- t.lackCenter = false
- }
- switch (t._startAxis) {
- case cc.Layout.AxisDirection.HORIZONTAL:
- let lineNum: number = Math.ceil(t._numItems / t._colLineNum)
- result = t._topGap + t._itemSize.height * lineNum + t._lineGap * (lineNum - 1) + t._bottomGap
- break
- case cc.Layout.AxisDirection.VERTICAL:
- let colNum: number = Math.ceil(t._numItems / t._colLineNum)
- result = t._leftGap + t._itemSize.width * colNum + t._columnGap * (colNum - 1) + t._rightGap
- break
- }
- break
- }
- }
- let layout: cc.Layout = t.content.getComponent(cc.Layout)
- if (layout) {
- layout.enabled = false
- }
- t._allItemSize = result
- t._allItemSizeNoEdge = t._allItemSize - (t._sizeType ? t._topGap + t._bottomGap : t._leftGap + t._rightGap)
- if (t.cyclic) {
- let totalSize: number = t._sizeType ? t.node.height : t.node.width
- t._cyclicPos1 = 0
- totalSize -= t._cyclicPos1
- t._cyclicNum = Math.ceil(totalSize / t._allItemSizeNoEdge) + 1
- let spacing: number = t._sizeType ? t._lineGap : t._columnGap
- t._cyclicPos2 = t._cyclicPos1 + t._allItemSizeNoEdge + spacing
- t._cyclicAllItemSize =
- t._allItemSize + t._allItemSizeNoEdge * (t._cyclicNum - 1) + spacing * (t._cyclicNum - 1)
- t._cycilcAllItemSizeNoEdge = t._allItemSizeNoEdge * t._cyclicNum
- t._cycilcAllItemSizeNoEdge += spacing * (t._cyclicNum - 1)
- // cc.log('_cyclicNum ->', t._cyclicNum, t._allItemSizeNoEdge, t._allItemSize, t._cyclicPos1, t._cyclicPos2);
- }
- t._lack = !t.cyclic && t._allItemSize < (t._sizeType ? t.node.height : t.node.width)
- let slideOffset: number = (!t._lack || !t.lackCenter) && t.lackSlide ? 0 : 0.1
- let targetWH: number = t._lack
- ? (t._sizeType ? t.node.height : t.node.width) - slideOffset
- : t.cyclic
- ? t._cyclicAllItemSize
- : t._allItemSize
- if (targetWH < 0) {
- targetWH = 0
- }
- if (t._sizeType) {
- t.content.height = targetWH
- } else {
- t.content.width = targetWH
- }
- // cc.log('_resizeContent() numItems =', t._numItems, ',content =', t.content);
- }
- // 滚动进行时...
- public _onScrolling(ev: cc.Event = null) {
- if (this.frameCount == null) {
- this.frameCount = this._updateRate
- }
- if (!this._forceUpdate && ev && ev.type != 'scroll-ended' && this.frameCount > 0) {
- this.frameCount--
- return
- } else {
- this.frameCount = this._updateRate
- }
- if (this._aniDelRuning) {
- return
- }
- // 循环列表处理
- if (this.cyclic) {
- let scrollPos: any = this.content.getPosition()
- scrollPos = this._sizeType ? scrollPos.y : scrollPos.x
- let addVal = this._allItemSizeNoEdge + (this._sizeType ? this._lineGap : this._columnGap)
- let add: any = this._sizeType ? cc.v2(0, addVal) : cc.v2(addVal, 0)
- switch (this._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- if (scrollPos > -this._cyclicPos1) {
- this.content.x = -this._cyclicPos2
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].sub(add)
- }
- // if (this._beganPos) {
- // this._beganPos += add;
- // }
- } else if (scrollPos < -this._cyclicPos2) {
- this.content.x = -this._cyclicPos1
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].add(add)
- }
- // if (this._beganPos) {
- // this._beganPos -= add;
- // }
- }
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- if (scrollPos < this._cyclicPos1) {
- this.content.x = this._cyclicPos2
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].add(add)
- }
- } else if (scrollPos > this._cyclicPos2) {
- this.content.x = this._cyclicPos1
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].sub(add)
- }
- }
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- if (scrollPos < this._cyclicPos1) {
- this.content.y = this._cyclicPos2
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].add(add)
- }
- } else if (scrollPos > this._cyclicPos2) {
- this.content.y = this._cyclicPos1
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].sub(add)
- }
- }
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- if (scrollPos > -this._cyclicPos1) {
- this.content.y = -this._cyclicPos2
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].sub(add)
- }
- } else if (scrollPos < -this._cyclicPos2) {
- this.content.y = -this._cyclicPos1
- if (this._scrollView.isAutoScrolling()) {
- this._scrollView['_autoScrollStartPosition'] = this._scrollView[
- '_autoScrollStartPosition'
- ].add(add)
- }
- }
- break
- }
- }
- this._calcViewPos()
- let vTop: number, vRight: number, vBottom: number, vLeft: number
- if (this._sizeType) {
- vTop = this.viewTop
- vBottom = this.viewBottom
- } else {
- vRight = this.viewRight
- vLeft = this.viewLeft
- }
- if (this._virtual) {
- this.displayData = []
- let itemPos: any
- let curId: number = 0
- let endId: number = this._numItems - 1
- if (this._customSize) {
- let breakFor: boolean = false
- // 如果该item的位置在可视区域内,就推入displayData
- for (; curId <= endId && !breakFor; curId++) {
- itemPos = this._calcItemPos(curId)
- switch (this._align) {
- case cc.Layout.Type.HORIZONTAL:
- if (itemPos.right >= vLeft && itemPos.left <= vRight) {
- this.displayData.push(itemPos)
- } else if (curId != 0 && this.displayData.length > 0) {
- breakFor = true
- }
- break
- case cc.Layout.Type.VERTICAL:
- if (itemPos.bottom <= vTop && itemPos.top >= vBottom) {
- this.displayData.push(itemPos)
- } else if (curId != 0 && this.displayData.length > 0) {
- breakFor = true
- }
- break
- case cc.Layout.Type.GRID:
- switch (this._startAxis) {
- case cc.Layout.AxisDirection.HORIZONTAL:
- if (itemPos.bottom <= vTop && itemPos.top >= vBottom) {
- this.displayData.push(itemPos)
- } else if (curId != 0 && this.displayData.length > 0) {
- breakFor = true
- }
- break
- case cc.Layout.AxisDirection.VERTICAL:
- if (itemPos.right >= vLeft && itemPos.left <= vRight) {
- this.displayData.push(itemPos)
- } else if (curId != 0 && this.displayData.length > 0) {
- breakFor = true
- }
- break
- }
- break
- }
- }
- } else {
- let ww: number = this._itemSize.width + this._columnGap
- let hh: number = this._itemSize.height + this._lineGap
- switch (this._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- curId = (vLeft + this._leftGap) / ww
- endId = (vRight + this._rightGap) / ww
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- curId = (-vRight - this._rightGap) / ww
- endId = (-vLeft - this._leftGap) / ww
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- curId = (-vTop - this._topGap) / hh
- endId = (-vBottom - this._bottomGap) / hh
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- curId = (vBottom + this._bottomGap) / hh
- endId = (vTop + this._topGap) / hh
- break
- }
- curId = Math.floor(curId) * this._colLineNum
- endId = Math.ceil(endId) * this._colLineNum
- endId--
- if (curId < 0) {
- curId = 0
- }
- if (endId >= this._numItems) {
- endId = this._numItems - 1
- }
- for (; curId <= endId; curId++) {
- this.displayData.push(this._calcItemPos(curId))
- }
- }
- this._delRedundantItem()
- if (this.displayData.length <= 0 || !this._numItems) {
- // if none, delete all.
- this._lastDisplayData = []
- return
- }
- this.firstListId = this.displayData[0].id
- this.displayItemNum = this.displayData.length
- let len: number = this._lastDisplayData.length
- let haveDataChange: boolean = this.displayItemNum != len
- if (haveDataChange) {
- // 如果是逐帧渲染,需要排序
- if (this.frameByFrameRenderNum > 0) {
- this._lastDisplayData.sort((a, b) => {
- return a - b
- })
- }
- // 因List的显示数据是有序的,所以只需要判断数组长度是否相等,以及头、尾两个元素是否相等即可。
- haveDataChange =
- this.firstListId != this._lastDisplayData[0] ||
- this.displayData[this.displayItemNum - 1].id != this._lastDisplayData[len - 1]
- }
- if (this._forceUpdate || haveDataChange) {
- // 如果是强制更新
- if (this.frameByFrameRenderNum > 0) {
- // if (this._updateDone) {
- // this._lastDisplayData = [];
- // 逐帧渲染
- if (this._numItems > 0) {
- if (!this._updateDone) {
- this._doneAfterUpdate = true
- } else {
- this._updateCounter = 0
- }
- this._updateDone = false
- } else {
- this._updateCounter = 0
- this._updateDone = true
- }
- // }
- } else {
- // 直接渲染
- this._lastDisplayData = []
- //cc.log('List Display Data II::', this.displayData)
- for (let c = 0; c < this.displayItemNum; c++) {
- this._createOrUpdateItem(this.displayData[c])
- }
- this._forceUpdate = false
- }
- }
- this._calcNearestItem()
- }
- }
- // 计算可视范围
- public _calcViewPos() {
- let scrollPos: any = this.content.getPosition()
- switch (this._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- this.elasticLeft = scrollPos.x > 0 ? scrollPos.x : 0
- this.viewLeft = (scrollPos.x < 0 ? -scrollPos.x : 0) - this.elasticLeft
- this.viewRight = this.viewLeft + this.node.width
- this.elasticRight =
- this.viewRight > this.content.width ? Math.abs(this.viewRight - this.content.width) : 0
- this.viewRight += this.elasticRight
- // cc.log(this.elasticLeft, this.elasticRight, this.viewLeft, this.viewRight);
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- this.elasticRight = scrollPos.x < 0 ? -scrollPos.x : 0
- this.viewRight = (scrollPos.x > 0 ? -scrollPos.x : 0) + this.elasticRight
- this.viewLeft = this.viewRight - this.node.width
- this.elasticLeft =
- this.viewLeft < -this.content.width ? Math.abs(this.viewLeft + this.content.width) : 0
- this.viewLeft -= this.elasticLeft
- // cc.log(this.elasticLeft, this.elasticRight, this.viewLeft, this.viewRight);
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- this.elasticTop = scrollPos.y < 0 ? Math.abs(scrollPos.y) : 0
- this.viewTop = (scrollPos.y > 0 ? -scrollPos.y : 0) + this.elasticTop
- this.viewBottom = this.viewTop - this.node.height
- this.elasticBottom =
- this.viewBottom < -this.content.height ? Math.abs(this.viewBottom + this.content.height) : 0
- this.viewBottom += this.elasticBottom
- // cc.log(this.elasticTop, this.elasticBottom, this.viewTop, this.viewBottom);
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- this.elasticBottom = scrollPos.y > 0 ? Math.abs(scrollPos.y) : 0
- this.viewBottom = (scrollPos.y < 0 ? -scrollPos.y : 0) - this.elasticBottom
- this.viewTop = this.viewBottom + this.node.height
- this.elasticTop = this.viewTop > this.content.height ? Math.abs(this.viewTop - this.content.height) : 0
- this.viewTop -= this.elasticTop
- // cc.log(this.elasticTop, this.elasticBottom, this.viewTop, this.viewBottom);
- break
- }
- }
- // 计算位置 根据id
- public _calcItemPos(id: number) {
- let width: number,
- height: number,
- top: number,
- bottom: number,
- left: number,
- right: number,
- itemX: number,
- itemY: number
- switch (this._align) {
- case cc.Layout.Type.HORIZONTAL:
- switch (this._horizontalDir) {
- case cc.Layout.HorizontalDirection.LEFT_TO_RIGHT: {
- if (this._customSize) {
- let fixed: any = this._getFixedSize(id)
- left =
- this._leftGap +
- (this._itemSize.width + this._columnGap) * (id - fixed.count) +
- (fixed.val + this._columnGap * fixed.count)
- let cs: number = this._customSize[id]
- width = cs > 0 ? cs : this._itemSize.width
- } else {
- left = this._leftGap + (this._itemSize.width + this._columnGap) * id
- width = this._itemSize.width
- }
- right = left + width
- if (this.lackCenter) {
- let offset: number = this.content.width / 2 - this._allItemSizeNoEdge / 2
- left += offset
- right += offset
- }
- return {
- id: id,
- left: left,
- right: right,
- x: left + this._itemTmp.anchorX * width,
- y: this._itemTmp.y,
- }
- }
- case cc.Layout.HorizontalDirection.RIGHT_TO_LEFT: {
- if (this._customSize) {
- let fixed: any = this._getFixedSize(id)
- right =
- -this._rightGap -
- (this._itemSize.width + this._columnGap) * (id - fixed.count) -
- (fixed.val + this._columnGap * fixed.count)
- let cs: number = this._customSize[id]
- width = cs > 0 ? cs : this._itemSize.width
- } else {
- right = -this._rightGap - (this._itemSize.width + this._columnGap) * id
- width = this._itemSize.width
- }
- left = right - width
- if (this.lackCenter) {
- let offset: number = this.content.width / 2 - this._allItemSizeNoEdge / 2
- left -= offset
- right -= offset
- }
- return {
- id: id,
- right: right,
- left: left,
- x: left + this._itemTmp.anchorX * width,
- y: this._itemTmp.y,
- }
- }
- }
- break
- case cc.Layout.Type.VERTICAL: {
- switch (this._verticalDir) {
- case cc.Layout.VerticalDirection.TOP_TO_BOTTOM: {
- if (this._customSize) {
- let fixed: any = this._getFixedSize(id)
- top =
- -this._topGap -
- (this._itemSize.height + this._lineGap) * (id - fixed.count) -
- (fixed.val + this._lineGap * fixed.count)
- let cs: number = this._customSize[id]
- height = cs > 0 ? cs : this._itemSize.height
- } else {
- top = -this._topGap - (this._itemSize.height + this._lineGap) * id
- height = this._itemSize.height
- }
- bottom = top - height
- if (this.lackCenter) {
- let offset: number = this.content.height / 2 - this._allItemSizeNoEdge / 2
- top -= offset
- bottom -= offset
- }
- return {
- id: id,
- top: top,
- bottom: bottom,
- x: this._itemTmp.x,
- y: bottom + this._itemTmp.anchorY * height,
- }
- }
- case cc.Layout.VerticalDirection.BOTTOM_TO_TOP: {
- if (this._customSize) {
- let fixed: any = this._getFixedSize(id)
- bottom =
- this._bottomGap +
- (this._itemSize.height + this._lineGap) * (id - fixed.count) +
- (fixed.val + this._lineGap * fixed.count)
- let cs: number = this._customSize[id]
- height = cs > 0 ? cs : this._itemSize.height
- } else {
- bottom = this._bottomGap + (this._itemSize.height + this._lineGap) * id
- height = this._itemSize.height
- }
- top = bottom + height
- if (this.lackCenter) {
- let offset: number = this.content.height / 2 - this._allItemSizeNoEdge / 2
- top += offset
- bottom += offset
- }
- return {
- id: id,
- top: top,
- bottom: bottom,
- x: this._itemTmp.x,
- y: bottom + this._itemTmp.anchorY * height,
- }
- break
- }
- }
- }
- case cc.Layout.Type.GRID: {
- let colLine: number = Math.floor(id / this._colLineNum)
- switch (this._startAxis) {
- case cc.Layout.AxisDirection.HORIZONTAL: {
- switch (this._verticalDir) {
- case cc.Layout.VerticalDirection.TOP_TO_BOTTOM: {
- top = -this._topGap - (this._itemSize.height + this._lineGap) * colLine
- bottom = top - this._itemSize.height
- itemY = bottom + this._itemTmp.anchorY * this._itemSize.height
- break
- }
- case cc.Layout.VerticalDirection.BOTTOM_TO_TOP: {
- bottom = this._bottomGap + (this._itemSize.height + this._lineGap) * colLine
- top = bottom + this._itemSize.height
- itemY = bottom + this._itemTmp.anchorY * this._itemSize.height
- break
- }
- }
- itemX = this._leftGap + (id % this._colLineNum) * (this._itemSize.width + this._columnGap)
- switch (this._horizontalDir) {
- case cc.Layout.HorizontalDirection.LEFT_TO_RIGHT: {
- itemX += this._itemTmp.anchorX * this._itemSize.width
- itemX -= this.content.anchorX * this.content.width
- break
- }
- case cc.Layout.HorizontalDirection.RIGHT_TO_LEFT: {
- itemX += (1 - this._itemTmp.anchorX) * this._itemSize.width
- itemX -= (1 - this.content.anchorX) * this.content.width
- itemX *= -1
- break
- }
- }
- return {
- id: id,
- top: top,
- bottom: bottom,
- x: itemX,
- y: itemY,
- }
- }
- case cc.Layout.AxisDirection.VERTICAL: {
- switch (this._horizontalDir) {
- case cc.Layout.HorizontalDirection.LEFT_TO_RIGHT: {
- left = this._leftGap + (this._itemSize.width + this._columnGap) * colLine
- right = left + this._itemSize.width
- itemX = left + this._itemTmp.anchorX * this._itemSize.width
- itemX -= this.content.anchorX * this.content.width
- break
- }
- case cc.Layout.HorizontalDirection.RIGHT_TO_LEFT: {
- right = -this._rightGap - (this._itemSize.width + this._columnGap) * colLine
- left = right - this._itemSize.width
- itemX = left + this._itemTmp.anchorX * this._itemSize.width
- itemX += (1 - this.content.anchorX) * this.content.width
- break
- }
- }
- itemY = -this._topGap - (id % this._colLineNum) * (this._itemSize.height + this._lineGap)
- switch (this._verticalDir) {
- case cc.Layout.VerticalDirection.TOP_TO_BOTTOM: {
- itemY -= (1 - this._itemTmp.anchorY) * this._itemSize.height
- itemY += (1 - this.content.anchorY) * this.content.height
- break
- }
- case cc.Layout.VerticalDirection.BOTTOM_TO_TOP: {
- itemY -= this._itemTmp.anchorY * this._itemSize.height
- itemY += this.content.anchorY * this.content.height
- itemY *= -1
- break
- }
- }
- return {
- id: id,
- left: left,
- right: right,
- x: itemX,
- y: itemY,
- }
- }
- }
- break
- }
- }
- }
- // 计算已存在的Item的位置
- public _calcExistItemPos(id: number) {
- let item: any = this.getItemByListId(id)
- if (!item) {
- return null
- }
- let data: any = {
- id: id,
- x: item.x,
- y: item.y,
- }
- if (this._sizeType) {
- data.top = item.y + item.height * (1 - item.anchorY)
- data.bottom = item.y - item.height * item.anchorY
- } else {
- data.left = item.x - item.width * item.anchorX
- data.right = item.x + item.width * (1 - item.anchorX)
- }
- return data
- }
- // 获取Item位置
- public getItemPos(id: number) {
- if (this._virtual) {
- return this._calcItemPos(id)
- } else {
- if (this.frameByFrameRenderNum) {
- return this._calcItemPos(id)
- } else {
- return this._calcExistItemPos(id)
- }
- }
- }
- // 获取固定尺寸
- public _getFixedSize(listId: number) {
- if (!this._customSize) {
- return null
- }
- if (listId == null) {
- listId = this._numItems
- }
- let fixed: number = 0
- let count: number = 0
- for (let id in this._customSize) {
- if (parseInt(id) < listId) {
- fixed += this._customSize[id]
- count++
- }
- }
- return {
- val: fixed,
- count: count,
- }
- }
- // 滚动结束时..
- public _onScrollBegan() {
- this._beganPos = this._sizeType ? this.viewTop : this.viewLeft
- }
- // 滚动结束时..
- public _onScrollEnded() {
- let t: any = this
- if (t.scrollToListId != null) {
- let item: any = t.getItemByListId(t.scrollToListId)
- t.scrollToListId = null
- if (item) {
- item.runAction(
- cc.sequence(
- cc.scaleTo(0.1, 1.06),
- cc.scaleTo(0.1, 1),
- // new cc.callFunc(function (runNode) {
- // })
- ),
- )
- }
- }
- t._onScrolling()
- if (t._slideMode == SlideType.ADHERING && !t.adhering) {
- // cc.log(t.adhering, t._scrollView.isAutoScrolling(), t._scrollView.isScrolling());
- t.adhere()
- } else if (t._slideMode == SlideType.PAGE) {
- if (t._beganPos != null) {
- this._pageAdhere()
- } else {
- t.adhere()
- }
- }
- }
- // 触摸时
- public _onTouchStart(ev, captureListeners) {
- if (this._scrollView['hasNestedViewGroup'](ev, captureListeners)) {
- return
- }
- let isMe = ev.eventPhase === cc.Event.AT_TARGET && ev.target === this.node
- if (!isMe) {
- let itemNode: any = ev.target
- while (itemNode._listId == null && itemNode.parent) {
- itemNode = itemNode.parent
- }
- this._scrollItem = itemNode._listId != null ? itemNode : ev.target
- }
- }
- // 触摸抬起时..
- public _onTouchUp() {
- let t: any = this
- t._scrollPos = null
- if (t._slideMode == SlideType.ADHERING) {
- if (this.adhering) {
- this._adheringBarrier = true
- }
- t.adhere()
- } else if (t._slideMode == SlideType.PAGE) {
- if (t._beganPos != null) {
- this._pageAdhere()
- } else {
- t.adhere()
- }
- }
- this._scrollItem = null
- }
- public _onTouchCancelled(ev, captureListeners) {
- let t = this
- if (t._scrollView['hasNestedViewGroup'](ev, captureListeners) || ev.simulate) {
- return
- }
- t._scrollPos = null
- if (t._slideMode == SlideType.ADHERING) {
- if (t.adhering) {
- t._adheringBarrier = true
- }
- t.adhere()
- } else if (t._slideMode == SlideType.PAGE) {
- if (t._beganPos != null) {
- t._pageAdhere()
- } else {
- t.adhere()
- }
- }
- this._scrollItem = null
- }
- // 当尺寸改变
- public _onSizeChanged() {
- if (this.checkInited(false)) {
- this._onScrolling()
- }
- }
- // 当Item自适应
- public _onItemAdaptive(item) {
- // if (this.checkInited(false)) {
- if (
- (!this._sizeType && item.width != this._itemSize.width) ||
- (this._sizeType && item.height != this._itemSize.height)
- ) {
- if (!this._customSize) {
- this._customSize = {}
- }
- let val = this._sizeType ? item.height : item.width
- if (this._customSize[item._listId] != val) {
- this._customSize[item._listId] = val
- this._resizeContent()
- // this.content.children.forEach((child: cc.Node) => {
- // this._updateItemPos(child);
- // });
- this.updateAll()
- // 如果当前正在运行 scrollTo,肯定会不准确,在这里做修正
- if (this._scrollToListId != null) {
- this._scrollPos = null
- this.unschedule(this._scrollToSo)
- this.scrollTo(
- this._scrollToListId,
- Math.max(0, this._scrollToEndTime - new Date().getTime() / 1000),
- )
- }
- }
- }
- // }
- }
- // PAGE粘附
- public _pageAdhere() {
- let t = this
- if (!t.cyclic && (t.elasticTop > 0 || t.elasticRight > 0 || t.elasticBottom > 0 || t.elasticLeft > 0)) {
- return
- }
- let curPos = t._sizeType ? t.viewTop : t.viewLeft
- let dis = (t._sizeType ? t.node.height : t.node.width) * t.pageDistance
- let canSkip = Math.abs(t._beganPos - curPos) > dis
- if (canSkip) {
- let timeInSecond = 0.5
- switch (t._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- if (t._beganPos > curPos) {
- t.prePage(timeInSecond)
- // cc.log('_pageAdhere PPPPPPPPPPPPPPP');
- } else {
- t.nextPage(timeInSecond)
- // cc.log('_pageAdhere NNNNNNNNNNNNNNN');
- }
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- if (t._beganPos < curPos) {
- t.prePage(timeInSecond)
- } else {
- t.nextPage(timeInSecond)
- }
- break
- }
- } else if (t.elasticTop <= 0 && t.elasticRight <= 0 && t.elasticBottom <= 0 && t.elasticLeft <= 0) {
- t.adhere()
- }
- t._beganPos = null
- }
- // 粘附
- public adhere() {
- let t: any = this
- if (!t.checkInited()) {
- return
- }
- if (t.elasticTop > 0 || t.elasticRight > 0 || t.elasticBottom > 0 || t.elasticLeft > 0) {
- return
- }
- t.adhering = true
- t._calcNearestItem()
- let offset: number = (t._sizeType ? t._topGap : t._leftGap) / (t._sizeType ? t.node.height : t.node.width)
- let timeInSecond: number = 0.7
- t.scrollTo(t.nearestListId, timeInSecond, offset)
- }
- // Update..
- public update() {
- if (this.frameByFrameRenderNum <= 0 || this._updateDone) {
- return
- }
- // cc.log(this.displayData.length, this._updateCounter, this.displayData[this._updateCounter]);
- if (this._virtual) {
- let len: number =
- this._updateCounter + this.frameByFrameRenderNum > this.displayItemNum
- ? this.displayItemNum
- : this._updateCounter + this.frameByFrameRenderNum
- for (let n: number = this._updateCounter; n < len; n++) {
- let data: any = this.displayData[n]
- if (data) {
- this._createOrUpdateItem(data)
- }
- }
- if (this._updateCounter >= this.displayItemNum - 1) {
- // 最后一个
- if (this._doneAfterUpdate) {
- this._updateCounter = 0
- this._updateDone = false
- // if (!this._scrollView.isScrolling())
- this._doneAfterUpdate = false
- } else {
- this._updateDone = true
- this._delRedundantItem()
- this._forceUpdate = false
- this._calcNearestItem()
- if (this.slideMode == SlideType.PAGE) {
- this.curPageNum = this.nearestListId
- }
- }
- } else {
- this._updateCounter += this.frameByFrameRenderNum
- }
- } else {
- if (this._updateCounter < this._numItems) {
- let len: number =
- this._updateCounter + this.frameByFrameRenderNum > this._numItems
- ? this._numItems
- : this._updateCounter + this.frameByFrameRenderNum
- for (let n: number = this._updateCounter; n < len; n++) {
- this._createOrUpdateItem2(n)
- }
- this._updateCounter += this.frameByFrameRenderNum
- } else {
- this._updateDone = true
- this._calcNearestItem()
- if (this.slideMode == SlideType.PAGE) {
- this.curPageNum = this.nearestListId
- }
- }
- }
- }
- /**
- * 创建或更新Item(虚拟列表用)
- * @param {Object} data 数据
- */
- public _createOrUpdateItem(data: any) {
- let item: any = this.getItemByListId(data.id)
- if (!item) {
- // 如果不存在
- let canGet: boolean = this._pool.size() > 0
- if (canGet) {
- item = this._pool.get()
- // cc.log('从池中取出:: 旧id =', item['_listId'], ',新id =', data.id, item);
- } else {
- item = cc.instantiate(this._itemTmp)
- // cc.log('新建::', data.id, item);
- }
- if (item._listId != data.id) {
- item._listId = data.id
- item.setContentSize(this._itemSize)
- }
- item.setPosition(cc.v2(data.x, data.y))
- item.zIndex = data.x / item.width - data.y / item.height
- this._resetItemSize(item)
- this.content.addChild(item)
- if (canGet && this._needUpdateWidget) {
- let widget: cc.Widget = item.getComponent(cc.Widget)
- if (widget) {
- widget.updateAlignment()
- }
- }
- item.setSiblingIndex(this.content.childrenCount - 1)
- let listItem: ListItem = item.getComponent(ListItem)
- item['listItem'] = listItem
- if (listItem) {
- listItem.listId = data.id
- listItem.list = this
- listItem._registerEvent()
- }
- if (this.renderEvent) {
- cc.Component.EventHandler.emitEvents([this.renderEvent], item, data.id % this._actualNumItems, this)
- }
- } else if (this._forceUpdate && this.renderEvent) {
- // 强制更新
- item.setPosition(cc.v2(data.x, data.y))
- item.zIndex = data.x / item.width - data.y / item.height
- this._resetItemSize(item)
- // cc.log('ADD::', data.id, item);
- if (this.renderEvent) {
- cc.Component.EventHandler.emitEvents([this.renderEvent], item, data.id % this._actualNumItems, this)
- }
- }
- this._resetItemSize(item)
- this._updateListItem(item['listItem'])
- if (this._lastDisplayData.indexOf(data.id) < 0) {
- this._lastDisplayData.push(data.id)
- }
- }
- // 创建或更新Item(非虚拟列表用)
- public _createOrUpdateItem2(listId: number) {
- let item: any = this.content.children[listId]
- let listItem: ListItem
- if (!item) {
- // 如果不存在
- item = cc.instantiate(this._itemTmp)
- item._listId = listId
- this.content.addChild(item)
- listItem = item.getComponent(ListItem)
- item['listItem'] = listItem
- if (listItem) {
- listItem.listId = listId
- listItem.list = this
- listItem._registerEvent()
- }
- if (this.renderEvent) {
- cc.Component.EventHandler.emitEvents([this.renderEvent], item, listId)
- }
- } else if (this._forceUpdate && this.renderEvent) {
- // 强制更新
- item._listId = listId
- if (listItem) {
- listItem.listId = listId
- }
- if (this.renderEvent) {
- cc.Component.EventHandler.emitEvents([this.renderEvent], item, listId)
- }
- }
- this._updateListItem(listItem)
- if (this._lastDisplayData.indexOf(listId) < 0) {
- this._lastDisplayData.push(listId)
- }
- }
- public _updateListItem(listItem: ListItem) {
- if (!listItem) {
- return
- }
- if (this.selectedMode > SelectedType.NONE) {
- let item: any = listItem.node
- switch (this.selectedMode) {
- case SelectedType.SINGLE:
- listItem.selected = this.selectedId == item._listId
- break
- case SelectedType.MULT:
- listItem.selected = this.multSelected.indexOf(item._listId) >= 0
- break
- }
- }
- }
- // 仅虚拟列表用
- public _resetItemSize(item: any) {
- return
- let size: number
- if (this._customSize && this._customSize[item._listId]) {
- size = this._customSize[item._listId]
- } else {
- if (this._colLineNum > 1) {
- item.setContentSize(this._itemSize)
- } else {
- size = this._sizeType ? this._itemSize.height : this._itemSize.width
- }
- }
- if (size) {
- if (this._sizeType) {
- item.height = size
- } else {
- item.width = size
- }
- }
- }
- /**
- * 更新Item位置
- * @param {Number||Node} listIdOrItem
- */
- public _updateItemPos(listIdOrItem: any) {
- let item: any = isNaN(listIdOrItem) ? listIdOrItem : this.getItemByListId(listIdOrItem)
- let pos: any = this.getItemPos(item._listId)
- item.setPosition(pos.x, pos.y)
- }
- /**
- * 设置多选
- * @param {Array} args 可以是单个listId,也可是个listId数组
- * @param {Boolean} bool 值,如果为null的话,则直接用args覆盖
- */
- public setMultSelected(args: any, bool: boolean) {
- let t: any = this
- if (!t.checkInited()) {
- return
- }
- if (!Array.isArray(args)) {
- args = [args]
- }
- if (bool == null) {
- t.multSelected = args
- } else {
- let listId: number, sub: number
- if (bool) {
- for (let n: number = args.length - 1; n >= 0; n--) {
- listId = args[n]
- sub = t.multSelected.indexOf(listId)
- if (sub < 0) {
- t.multSelected.push(listId)
- }
- }
- } else {
- for (let n: number = args.length - 1; n >= 0; n--) {
- listId = args[n]
- sub = t.multSelected.indexOf(listId)
- if (sub >= 0) {
- t.multSelected.splice(sub, 1)
- }
- }
- }
- }
- t._forceUpdate = true
- t._onScrolling()
- }
- public getMultSelected() {
- return this.multSelected
- }
- /**
- * 更新指定的Item
- * @param {Array} args 单个listId,或者数组
- * @returns
- */
- public updateItem(args: any) {
- if (!this.checkInited()) {
- return
- }
- if (!Array.isArray(args)) {
- args = [args]
- }
- for (let n: number = 0, len: number = args.length; n < len; n++) {
- let listId: number = args[n]
- let item: any = this.getItemByListId(listId)
- if (item) {
- cc.Component.EventHandler.emitEvents([this.renderEvent], item, listId % this._actualNumItems)
- }
- }
- }
- /**
- * 更新全部
- */
- public updateAll() {
- if (!this.checkInited()) {
- return
- }
- this.numItems = this.numItems
- }
- /**
- * 根据ListID获取Item
- * @param {Number} listId
- * @returns
- */
- public getItemByListId(listId: number) {
- if (this.content) {
- for (let n: number = this.content.childrenCount - 1; n >= 0; n--) {
- let item: any = this.content.children[n]
- if (item._listId == listId) {
- return item
- }
- }
- }
- }
- public getInsideItemById(id) {
- return this.displayData.find(d => d.id == id)
- }
- /**
- * 获取当前item数量
- */
- public getItemCount() {
- return this.content.childrenCount
- }
- /**
- * 获取在显示区域内的Item
- */
- public getInsideItem() {
- let item: any
- let result: any[] = []
- for (let n: number = 0; n < this.content.childrenCount; n++) {
- item = this.content.children[n]
- if (this.displayData.find(d => d.id == item._listId)) {
- result.push(item)
- }
- }
- return result
- }
- /**
- * 获取在显示区域外的Item
- * @returns
- */
- private _getOutsideItem() {
- let item: any
- let result: any[] = []
- for (let n: number = this.content.childrenCount - 1; n >= 0; n--) {
- item = this.content.children[n]
- if (!this.displayData.find(d => d.id == item._listId)) {
- result.push(item)
- }
- }
- return result
- }
- // 删除显示区域以外的Item
- private _delRedundantItem() {
- if (this._virtual) {
- let arr: any[] = this._getOutsideItem()
- for (let n: number = arr.length - 1; n >= 0; n--) {
- let item: any = arr[n]
- if (this._scrollItem && item._listId == this._scrollItem._listId) {
- continue
- }
- this._pool.put(item)
- for (let m: number = this._lastDisplayData.length - 1; m >= 0; m--) {
- if (this._lastDisplayData[m] == item._listId) {
- this._lastDisplayData.splice(m, 1)
- break
- }
- }
- }
- // cc.log('存入::', str, ' pool.length =', this._pool.length);
- } else {
- while (this.content.childrenCount > this._numItems) {
- this._delSingleItem(this.content.children[this.content.childrenCount - 1])
- }
- }
- }
- // 删除单个Item
- public _delSingleItem(item: any) {
- // cc.log('DEL::', item['_listId'], item);
- item.removeFromParent()
- if (item.destroy) {
- item.destroy()
- }
- item = null
- }
- /**
- * 动效删除Item(此方法只适用于虚拟列表,即_virtual=true)
- * 一定要在回调函数里重新设置新的numItems进行刷新,毕竟本List是靠数据驱动的。
- */
- public aniDelItem(listId: number, callFunc: Function, aniType: number) {
- let t: any = this
- if (!t.checkInited() || t.cyclic || !t._virtual) {
- return cc.error('This function is not allowed to be called!')
- }
- if (t._aniDelRuning) {
- return cc.warn('Please wait for the current deletion to finish!')
- }
- let item: any = t.getItemByListId(listId)
- let listItem: ListItem
- if (!item) {
- callFunc(listId)
- return
- } else {
- listItem = item.getComponent(ListItem)
- }
- t._aniDelRuning = true
- let curLastId: number = t.displayData[t.displayData.length - 1].id
- let resetSelectedId: boolean = listItem.selected
- listItem.showAni(
- aniType,
- () => {
- // 判断有没有下一个,如果有的话,创建粗来
- let newId: number
- if (curLastId < t._numItems - 2) {
- newId = curLastId + 1
- }
- if (newId != null) {
- let newData: any = t._calcItemPos(newId)
- t.displayData.push(newData)
- if (t._virtual) {
- t._createOrUpdateItem(newData)
- } else {
- t._createOrUpdateItem2(newId)
- }
- } else {
- t._numItems--
- }
- if (t.selectedMode == SelectedType.SINGLE) {
- if (resetSelectedId) {
- t._selectedId = -1
- } else if (t._selectedId - 1 >= 0) {
- t._selectedId--
- }
- } else if (t.selectedMode == SelectedType.MULT && t.multSelected.length) {
- let sub: number = t.multSelected.indexOf(listId)
- if (sub >= 0) {
- t.multSelected.splice(sub, 1)
- }
- // 多选的数据,在其后的全部减一
- for (let n: number = t.multSelected.length - 1; n >= 0; n--) {
- let id: number = t.multSelected[n]
- if (id >= listId) {
- t.multSelected[n]--
- }
- }
- }
- if (t._customSize) {
- if (t._customSize[listId]) {
- delete t._customSize[listId]
- }
- let newCustomSize: any = {}
- let size: number
- for (let id in t._customSize) {
- size = t._customSize[id]
- let idNumber: number = parseInt(id)
- newCustomSize[idNumber - (idNumber >= listId ? 1 : 0)] = size
- }
- t._customSize = newCustomSize
- }
- // 后面的Item向前怼的动效
- let sec: number = 0.2333
- let acts: any[], haveCB: boolean
- for (let n: number = newId != null ? newId : curLastId; n >= listId + 1; n--) {
- item = t.getItemByListId(n)
- if (item) {
- let posData: any = t._calcItemPos(n - 1)
- acts = [cc.moveTo(sec, cc.v2(posData.x, posData.y))]
- if (n <= listId + 1) {
- haveCB = true
- acts.push(
- cc.callFunc(() => {
- t._aniDelRuning = false
- callFunc(listId)
- }),
- )
- }
- if (acts.length > 1) {
- item.runAction(cc.sequence(acts))
- } else {
- item.runAction(acts[0])
- }
- }
- }
- if (!haveCB) {
- t._aniDelRuning = false
- callFunc(listId)
- }
- },
- true,
- )
- }
- /**
- * 滚动到..
- * @param {Number} listId 索引(如果<0,则滚到首个Item位置,如果>=_numItems,则滚到最末Item位置)
- * @param {Number} timeInSecond 时间
- * @param {Number} offset 索引目标位置偏移,0-1
- * @param {Boolean} overStress 滚动后是否强调该Item(这只是个实验功能)
- */
- public scrollTo(listId: number, timeInSecond: number = 0.5, offset: number = null, overStress: boolean = false) {
- let t = this
- if (!t.checkInited(false)) {
- return
- }
- // t._scrollView.stopAutoScroll();
- if (timeInSecond == null) {
- // 默认0.5
- timeInSecond = 0.5
- } else if (timeInSecond < 0) {
- timeInSecond = 0
- }
- if (listId < 0) {
- listId = 0
- } else if (listId >= t._numItems) {
- listId = t._numItems - 1
- }
- // 以防设置了numItems之后layout的尺寸还未更新
- if (!t._virtual && t._layout && t._layout.enabled) {
- t._layout.updateLayout()
- }
- let pos = t.getItemPos(listId)
- let targetX: number, targetY: number
- switch (t._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- targetX = pos.left
- if (offset != null) {
- targetX -= t.node.width * offset
- } else {
- targetX -= t._leftGap
- }
- pos = cc.v2(targetX, 0)
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- targetX = pos.right - t.node.width
- if (offset != null) {
- targetX += t.node.width * offset
- } else {
- targetX += t._rightGap
- }
- pos = cc.v2(targetX + t.content.width, 0)
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- targetY = pos.top
- if (offset != null) {
- targetY += t.node.height * offset
- } else {
- targetY += t._topGap
- }
- pos = cc.v2(0, -targetY)
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- targetY = pos.bottom + t.node.height
- if (offset != null) {
- targetY -= t.node.height * offset
- } else {
- targetY -= t._bottomGap
- }
- pos = cc.v2(0, -targetY + t.content.height)
- break
- }
- let viewPos: any = t.content.getPosition()
- viewPos = Math.abs(t._sizeType ? viewPos.y : viewPos.x)
- let comparePos = t._sizeType ? pos.y : pos.x
- let runScroll = Math.abs((t._scrollPos != null ? t._scrollPos : viewPos) - comparePos) > 0.5
- // cc.log(runScroll, t._scrollPos, viewPos, comparePos)
- // t._scrollView.stopAutoScroll();
- if (runScroll) {
- t._scrollView.scrollToOffset(pos, timeInSecond)
- t._scrollToListId = listId
- t._scrollToEndTime = new Date().getTime() / 1000 + timeInSecond
- // cc.log(listId, t.content.width, t.content.getPosition(), pos);
- t._scrollToSo = t.scheduleOnce(() => {
- if (!t._adheringBarrier) {
- t.adhering = t._adheringBarrier = false
- }
- t._scrollPos = t._scrollToListId = t._scrollToEndTime = t._scrollToSo = null
- // cc.log('2222222222', t._adheringBarrier)
- if (overStress) {
- // t.scrollToListId = listId;
- let item = t.getItemByListId(listId)
- if (item) {
- item.runAction(cc.sequence(cc.scaleTo(0.1, 1.05), cc.scaleTo(0.1, 1)))
- }
- }
- }, timeInSecond + 0.1)
- if (timeInSecond <= 0) {
- t._onScrolling()
- }
- }
- }
- /**
- * 计算当前滚动窗最近的Item
- */
- public _calcNearestItem() {
- let t: any = this
- t.nearestListId = null
- let data: any, center: number
- if (t._virtual) {
- t._calcViewPos()
- }
- let vTop: number, vRight: number, vBottom: number, vLeft: number
- vTop = t.viewTop
- vRight = t.viewRight
- vBottom = t.viewBottom
- vLeft = t.viewLeft
- let breakFor: boolean = false
- for (let n = 0; n < t.content.childrenCount && !breakFor; n += t._colLineNum) {
- data = t._virtual ? t.displayData[n] : t._calcExistItemPos(n)
- if (data) {
- center = t._sizeType ? (data.top + data.bottom) / 2 : (center = (data.left + data.right) / 2)
- switch (t._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- if (data.right >= vLeft) {
- t.nearestListId = data.id
- if (vLeft > center) {
- t.nearestListId += t._colLineNum
- }
- breakFor = true
- }
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- if (data.left <= vRight) {
- t.nearestListId = data.id
- if (vRight < center) {
- t.nearestListId += t._colLineNum
- }
- breakFor = true
- }
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- if (data.bottom <= vTop) {
- t.nearestListId = data.id
- if (vTop < center) {
- t.nearestListId += t._colLineNum
- }
- breakFor = true
- }
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- if (data.top >= vBottom) {
- t.nearestListId = data.id
- if (vBottom > center) {
- t.nearestListId += t._colLineNum
- }
- breakFor = true
- }
- break
- }
- }
- }
- // 判断最后一个Item。。。(哎,这些判断真心恶心,判断了前面的还要判断最后一个。。。一开始呢,就只有一个布局(单列布局),那时候代码才三百行,后来就想着完善啊,艹..这坑真深,现在这行数都一千五了= =||)
- data = t._virtual ? t.displayData[t.displayItemNum - 1] : t._calcExistItemPos(t._numItems - 1)
- if (data && data.id == t._numItems - 1) {
- center = t._sizeType ? (data.top + data.bottom) / 2 : (center = (data.left + data.right) / 2)
- switch (t._alignCalcType) {
- case 1: // 单行HORIZONTAL(LEFT_TO_RIGHT)、网格VERTICAL(LEFT_TO_RIGHT)
- if (vRight > center) {
- t.nearestListId = data.id
- }
- break
- case 2: // 单行HORIZONTAL(RIGHT_TO_LEFT)、网格VERTICAL(RIGHT_TO_LEFT)
- if (vLeft < center) {
- t.nearestListId = data.id
- }
- break
- case 3: // 单列VERTICAL(TOP_TO_BOTTOM)、网格HORIZONTAL(TOP_TO_BOTTOM)
- if (vBottom < center) {
- t.nearestListId = data.id
- }
- break
- case 4: // 单列VERTICAL(BOTTOM_TO_TOP)、网格HORIZONTAL(BOTTOM_TO_TOP)
- if (vTop > center) {
- t.nearestListId = data.id
- }
- break
- }
- }
- // cc.log('t.nearestListId =', t.nearestListId);
- }
- // 上一页
- public prePage(timeInSecond: number = 0.5) {
- // cc.log('👈');
- if (!this.checkInited()) {
- return
- }
- this.skipPage(this.curPageNum - 1, timeInSecond)
- }
- // 下一页
- public nextPage(timeInSecond: number = 0.5) {
- // cc.log('👉');
- if (!this.checkInited()) {
- return
- }
- this.skipPage(this.curPageNum + 1, timeInSecond)
- }
- // 跳转到第几页
- public skipPage(pageNum: number, timeInSecond: number) {
- let t: any = this
- if (!t.checkInited()) {
- return
- }
- if (t._slideMode != SlideType.PAGE) {
- return cc.error('This function is not allowed to be called, Must SlideMode = PAGE!')
- }
- if (pageNum < 0 || pageNum >= t._numItems) {
- return
- }
- if (t.curPageNum == pageNum) {
- return
- }
- // cc.log(pageNum);
- t.curPageNum = pageNum
- if (t.pageChangeEvent) {
- cc.Component.EventHandler.emitEvents([t.pageChangeEvent], pageNum)
- }
- t.scrollTo(pageNum, timeInSecond)
- }
- // 计算 CustomSize(这个函数还是保留吧,某些罕见的情况的确还是需要手动计算customSize的)
- public calcCustomSize(numItems: number) {
- let t: any = this
- if (!t.checkInited()) {
- return
- }
- if (!t._itemTmp) {
- return cc.error('Unset template item!')
- }
- if (!t.renderEvent) {
- return cc.error('Unset Render-Event!')
- }
- t._customSize = {}
- let temp: any = cc.instantiate(t._itemTmp)
- t.content.addChild(temp)
- for (let n: number = 0; n < numItems; n++) {
- cc.Component.EventHandler.emitEvents([t.renderEvent], temp, n)
- if (temp.height != t._itemSize.height || temp.width != t._itemSize.width) {
- t._customSize[n] = t._sizeType ? temp.height : temp.width
- }
- }
- if (!Object.keys(t._customSize).length) {
- t._customSize = null
- }
- temp.removeFromParent()
- if (temp.destroy) {
- temp.destroy()
- }
- return t._customSize
- }
- }
|