ListItem.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /**
  2. * ***************************************
  3. * ****************************************
  4. *
  5. * @format
  6. * @author kL <klk0@qq.com>
  7. * @date 2019/6/6
  8. * @doc 列表Item组件. 说明: 1、此组件须配合List组件使用。(配套的配套的..)
  9. * @end
  10. */
  11. import UserButton from './UserButton'
  12. const {ccclass, property, disallowMultiple, menu, executionOrder} = cc._decorator
  13. import List from './List'
  14. enum SelectedType {
  15. NONE = 0,
  16. TOGGLE = 1,
  17. SWITCH = 2,
  18. }
  19. @ccclass
  20. @disallowMultiple()
  21. @menu('自定义组件/List Item')
  22. @executionOrder(-5001) // 先于List
  23. export default class ListItem extends cc.Component {
  24. // 图标
  25. @property({type: cc.Sprite, tooltip: CC_DEV && '图标'})
  26. public icon: cc.Sprite = null
  27. // 标题
  28. @property({type: cc.Node, tooltip: CC_DEV && '标题'})
  29. public title: cc.Node = null
  30. // 选择模式
  31. @property({
  32. type: cc.Enum(SelectedType),
  33. tooltip: CC_DEV && '选择模式',
  34. })
  35. public selectedMode: SelectedType = SelectedType.NONE
  36. // 被选标志
  37. @property({
  38. type: cc.Node,
  39. tooltip: CC_DEV && '被选标志',
  40. visible() {
  41. return this.selectedMode > SelectedType.NONE
  42. },
  43. })
  44. public selectedFlag: cc.Node = null
  45. // 被选择的SpriteFrame
  46. @property({
  47. type: cc.SpriteFrame,
  48. tooltip: CC_DEV && '被选择的SpriteFrame',
  49. visible() {
  50. return this.selectedMode == SelectedType.SWITCH
  51. },
  52. })
  53. public selectedSpriteFrame: cc.SpriteFrame = null
  54. // 未被选择的SpriteFrame
  55. public _unselectedSpriteFrame: cc.SpriteFrame = null
  56. // 自适应尺寸
  57. @property({
  58. tooltip: CC_DEV && '自适应尺寸(宽或高)',
  59. })
  60. public adaptiveSize: boolean = false
  61. // 选择
  62. public _selected: boolean = false
  63. set selected(val: boolean) {
  64. this._selected = val
  65. if (!this.selectedFlag) {
  66. return
  67. }
  68. switch (this.selectedMode) {
  69. case SelectedType.TOGGLE:
  70. this.selectedFlag.active = val
  71. break
  72. case SelectedType.SWITCH:
  73. let sp: cc.Sprite = this.selectedFlag.getComponent(cc.Sprite)
  74. if (sp) {
  75. sp.spriteFrame = val ? this.selectedSpriteFrame : this._unselectedSpriteFrame
  76. }
  77. break
  78. }
  79. }
  80. get selected() {
  81. return this._selected
  82. }
  83. // 按钮组件
  84. private _btnCom: UserButton
  85. get btnCom() {
  86. if (!this._btnCom) {
  87. this._btnCom = this.node.getComponent(UserButton)
  88. }
  89. return this._btnCom
  90. }
  91. // 依赖的List组件
  92. public list: List
  93. // 是否已经注册过事件
  94. private _eventReg = false
  95. // 序列id
  96. public listId: number
  97. public onLoad() {
  98. // //没有按钮组件的话,selectedFlag无效
  99. // if (!this.btnCom)
  100. // this.selectedMode == SelectedType.NONE;
  101. // 有选择模式时,保存相应的东西
  102. if (this.selectedMode == SelectedType.SWITCH) {
  103. let com: cc.Sprite = this.selectedFlag.getComponent(cc.Sprite)
  104. this._unselectedSpriteFrame = com.spriteFrame
  105. }
  106. }
  107. public onDestroy() {
  108. this.node.off(cc.Node.EventType.SIZE_CHANGED, this._onSizeChange, this)
  109. }
  110. public _registerEvent() {
  111. if (!this._eventReg) {
  112. if (this.btnCom && this.list.selectedMode > 0) {
  113. this.btnCom.clickEvents.unshift(this.createEvt(this, 'onClickThis'))
  114. }
  115. if (this.adaptiveSize) {
  116. this.node.on(cc.Node.EventType.SIZE_CHANGED, this._onSizeChange, this)
  117. }
  118. this._eventReg = true
  119. }
  120. }
  121. public _onSizeChange() {
  122. this.list._onItemAdaptive(this.node)
  123. }
  124. /**
  125. * 创建事件
  126. * @param {cc.Component} component 组件脚本
  127. * @param {string} handlerName 触发函数名称
  128. * @param {cc.Node} node 组件所在node(不传的情况下取component.node)
  129. * @returns cc.Component.EventHandler
  130. */
  131. public createEvt(component: cc.Component, handlerName: string, node: cc.Node = null) {
  132. if (!component.isValid) {
  133. return
  134. } // 有些异步加载的,节点以及销毁了。
  135. component['comName'] =
  136. component['comName'] ||
  137. component.name
  138. .match(/\<(.*?)\>/g)
  139. .pop()
  140. .replace(/\<|>/g, '')
  141. let evt = new cc.Component.EventHandler()
  142. evt.target = node || component.node
  143. evt.component = component['comName']
  144. evt.handler = handlerName
  145. return evt
  146. }
  147. public showAni(aniType: number, callFunc: Function, del: boolean) {
  148. let acts: any[]
  149. switch (aniType) {
  150. case 0: // 向上消失
  151. acts = [cc.scaleTo(0.2, 0.7), cc.moveBy(0.3, 0, this.node.height * 2)]
  152. break
  153. case 1: // 向右消失
  154. acts = [cc.scaleTo(0.2, 0.7), cc.moveBy(0.3, this.node.width * 2, 0)]
  155. break
  156. case 2: // 向下消失
  157. acts = [cc.scaleTo(0.2, 0.7), cc.moveBy(0.3, 0, this.node.height * -2)]
  158. break
  159. case 3: // 向左消失
  160. acts = [cc.scaleTo(0.2, 0.7), cc.moveBy(0.3, this.node.width * -2, 0)]
  161. break
  162. default:
  163. // 默认:缩小消失
  164. acts = [cc.scaleTo(0.3, 0.1)]
  165. break
  166. }
  167. if (callFunc || del) {
  168. acts.push(
  169. cc.callFunc(() => {
  170. if (del) {
  171. this.list._delSingleItem(this.node)
  172. for (let n: number = this.list.displayData.length - 1; n >= 0; n--) {
  173. if (this.list.displayData[n].id == this.listId) {
  174. this.list.displayData.splice(n, 1)
  175. break
  176. }
  177. }
  178. }
  179. callFunc()
  180. }),
  181. )
  182. }
  183. this.node.runAction(cc.sequence(acts))
  184. }
  185. public onClickThis() {
  186. if (!this.btnCom.interactable) return
  187. this.list.selectedId = this.listId
  188. }
  189. }