NumberKeyboard.ets 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. export class NumberKeyBoardStyle {
  2. private static instance: NumberKeyBoardStyle
  3. //重写所有点击事件 慎用 参数一为下标 参数二为当前textInputValue的值
  4. rebuildAllClick?: (_: string, __: number) => void
  5. private border: BorderOptions = { width: 1, color: '#FF1A7DD8' }
  6. private borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses = 6
  7. private commonButtonBackgroundColor: ResourceColor = Color.White
  8. // 0的背景颜色
  9. private zeroBackGround: ResourceColor = '#FFACD7FF'
  10. // 完成的背景颜色
  11. private finishBackGround: ResourceColor = '#FF186EBD'
  12. // 删除按钮的图标
  13. private deleteIcon: ResourceStr = $r('app.media.app_icon')
  14. // 完成按钮的text
  15. private finishText: ResourceStr = '完成'
  16. private rowsGap: Length = 4.62
  17. private columnsGap: Length = 4.62
  18. // 大按钮的高
  19. private longHeight: Length = 101.69
  20. // 普通按钮的高
  21. private shortHeight: Length = 48.59
  22. // 字体样式
  23. private fontSize: number = 20
  24. private fonsWeight: number = 500
  25. private fontFamily: string = 'Source Han Sans SC'
  26. constructor() {
  27. if (!NumberKeyBoardStyle.instance) {
  28. NumberKeyBoardStyle.instance = this
  29. }
  30. return NumberKeyBoardStyle.instance
  31. }
  32. getFontSize() {
  33. return this.fontSize
  34. }
  35. setFontSize(fontSize: number) {
  36. this.fontSize = fontSize
  37. return this
  38. }
  39. getFontWeight() {
  40. return this.fonsWeight
  41. }
  42. setFontWeight(fontWeight: number) {
  43. this.fonsWeight = fontWeight
  44. return this
  45. }
  46. getFontFamily() {
  47. return this.fontFamily
  48. }
  49. setFontFamily(fontFamily: string) {
  50. this.fontFamily = fontFamily
  51. return this
  52. }
  53. getShortHeight() {
  54. return this.shortHeight
  55. }
  56. setShortHeight(height: Length) {
  57. this.shortHeight = height
  58. return this
  59. }
  60. getLongHeight() {
  61. return this.longHeight
  62. }
  63. setLongHeight(height: Length) {
  64. this.longHeight = height
  65. return this
  66. }
  67. getRowsGap() {
  68. return this.rowsGap
  69. }
  70. setColumnsGap(columnsGap: number) {
  71. this.columnsGap = columnsGap
  72. return this
  73. }
  74. setRowsGap(rowsGap: number) {
  75. this.rowsGap = rowsGap
  76. return this
  77. }
  78. getColumnsGap() {
  79. return this.columnsGap
  80. }
  81. getBorder() {
  82. return this.border
  83. }
  84. setBorder(border: BorderOptions) {
  85. this.border = border
  86. return this
  87. }
  88. getBorderRadius() {
  89. return this.borderRadius
  90. }
  91. setBorderRadius(borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses) {
  92. this.borderRadius = borderRadius
  93. return this
  94. }
  95. getZeroBackGround() {
  96. return this.zeroBackGround
  97. }
  98. setZeroBackGround(zeroBackGround: ResourceColor) {
  99. this.zeroBackGround = zeroBackGround
  100. return this
  101. }
  102. getFinishBackGround() {
  103. return this.finishBackGround
  104. }
  105. setFinishBackGround(finishBackGround: ResourceColor) {
  106. this.finishBackGround = finishBackGround
  107. return this
  108. }
  109. getDeleteIcon() {
  110. return this.deleteIcon
  111. }
  112. setDeleteIcon(deleteIcon: ResourceStr) {
  113. this.deleteIcon = deleteIcon
  114. return this
  115. }
  116. getCommonButtonBackground() {
  117. return this.commonButtonBackgroundColor
  118. }
  119. setCommonButtonBackground(commonButtonBackground: ResourceColor) {
  120. this.commonButtonBackgroundColor = commonButtonBackground
  121. return this
  122. }
  123. getFinishText() {
  124. return this.finishText
  125. }
  126. setFinishText(finishText: ResourceStr) {
  127. this.finishText = finishText
  128. return this
  129. }
  130. }
  131. @Extend(Text)
  132. function TextStyle(style: NumberKeyBoardStyle) {
  133. .fontSize(style.getFontSize())
  134. .fontWeight(style.getFontWeight())
  135. .fontFamily(style.getFontFamily())
  136. }
  137. /**
  138. * @description 自定义数字按钮键盘
  139. */
  140. @Component
  141. export struct NumberKeyBoard {
  142. //初始值
  143. @Prop @Require textInputValue: string
  144. //最大输入数
  145. maxInputNum: number = 5
  146. //样式设置 支持链式设置 允许动态修改 但是如果在父组件使用链式调用需要重新赋值,因为链式调用会导致装饰器失效
  147. @Prop keyBoardStyle: NumberKeyBoardStyle
  148. //完成字体的样式 自己实现AttributeModifier<TextAttribute>来传 AttributeModifier不支持响应式 如果需要动态刷新需要同步更改其它具有响应式的属性
  149. textModifier?: AttributeModifier<TextAttribute>
  150. //grid计算器的排序规则
  151. private layoutOptions: GridLayoutOptions = {
  152. regularSize: [1, 1],
  153. irregularIndexes: Array.from<undefined>({ length: 13 }).map((_,
  154. index) => index),
  155. onGetIrregularSizeByIndex: (index: number) => {
  156. if (index < 10) {
  157. if (index == 3) {
  158. return [2, 3]
  159. }
  160. return [1, 3]
  161. } else if (index == 10) {
  162. return [2, 3]
  163. } else if (index == 11) {
  164. return [1, 4]
  165. } else {
  166. return [1, 5]
  167. }
  168. }
  169. };
  170. //点击完成所需要的逻辑
  171. onFinishClick = (_: string) => {
  172. }
  173. //输入值变化
  174. onTextInputValueChange = (_: string) => {
  175. }
  176. @Styles
  177. pressStyles() {
  178. .opacity(0.7)
  179. }
  180. @Styles
  181. normalStyles() {
  182. .opacity(1)
  183. }
  184. build() {
  185. Grid(undefined, this.layoutOptions) {
  186. ForEach(Array.from({ length: 13 }), (_: undefined, index) => {
  187. GridItem() {
  188. Column() {
  189. if (index == 3) {
  190. Image(this.keyBoardStyle.getDeleteIcon())
  191. .width(20)
  192. .aspectRatio(2)
  193. } else if (index == 10) {
  194. Text(this.keyBoardStyle.getFinishText())
  195. .TextStyle(this.keyBoardStyle)
  196. .attributeModifier(this.textModifier)
  197. } else if (index == 11) {
  198. Text('0')
  199. .TextStyle(this.keyBoardStyle)
  200. } else if (index == 12) {
  201. Text('.')
  202. .TextStyle(this.keyBoardStyle)
  203. } else if (index < 3) {
  204. Text((index + 1).toString())
  205. .TextStyle(this.keyBoardStyle)
  206. } else {
  207. Text(index.toString())
  208. .TextStyle(this.keyBoardStyle)
  209. }
  210. }
  211. .backgroundColor(index == 11 ? this.keyBoardStyle.getZeroBackGround() :
  212. index == 10 ? this.keyBoardStyle.getFinishBackGround() : this.keyBoardStyle.getCommonButtonBackground())
  213. .width('100%')
  214. .height(this.calcGridItemHeight(index))
  215. .borderRadius(this.keyBoardStyle.getBorderRadius())
  216. .justifyContent(FlexAlign.Center)
  217. .border(this.keyBoardStyle.getBorder())
  218. .stateStyles({
  219. pressed: this.pressStyles,
  220. normal: this.normalStyles
  221. })
  222. .onClick(() => {
  223. if (this.keyBoardStyle.rebuildAllClick) {
  224. this.keyBoardStyle.rebuildAllClick(this.textInputValue, index)
  225. return
  226. }
  227. if (index == 3) {
  228. if (this.textInputValue.length > 0) {
  229. this.textInputValue = this.textInputValue.slice(0, this.textInputValue.length - 1)
  230. }
  231. if (this.textInputValue == '') {
  232. this.textInputValue = '0'
  233. }
  234. this.onTextInputValueChange(this.textInputValue)
  235. return
  236. }
  237. if (index == 10) {
  238. this.onFinishClick(this.textInputValue)
  239. return
  240. }
  241. if (this.textInputValue.length >= this.maxInputNum) {
  242. if (this.textInputValue.length > this.maxInputNum) {
  243. //裁剪为最大长度
  244. this.textInputValue = this.textInputValue.slice(0, this.maxInputNum)
  245. }
  246. return
  247. }
  248. if (index == 11) {
  249. if (parseInt(this.textInputValue) > 0) {
  250. this.textInputValue = this.textInputValue.concat('0')
  251. }
  252. } else if (index == 12) {
  253. if (!this.textInputValue.includes('.')) {
  254. this.textInputValue = this.textInputValue.concat('.')
  255. }
  256. } else if (index < 3) {
  257. if (parseInt(this.textInputValue) > 0) {
  258. this.textInputValue = this.textInputValue.concat((index + 1).toString())
  259. } else {
  260. this.textInputValue = (index + 1).toString()
  261. }
  262. } else {
  263. if (parseInt(this.textInputValue) > 0|| this.textInputValue.includes('.')) {
  264. this.textInputValue = this.textInputValue.concat(index.toString())
  265. } else {
  266. this.textInputValue = index.toString()
  267. }
  268. }
  269. this.onTextInputValueChange(this.textInputValue)
  270. })
  271. }
  272. })
  273. }
  274. .rowsGap(this.keyBoardStyle.getRowsGap())
  275. .columnsGap(this.keyBoardStyle.getColumnsGap())
  276. .columnsTemplate('repeat(12, 1fr)')
  277. // .layoutWeight(1)
  278. .width('100%')
  279. }
  280. //计算渲染grid的高
  281. private calcGridItemHeight(index: number): Length {
  282. if (index == 3 || index == 10) {
  283. return this.keyBoardStyle.getLongHeight()
  284. } else {
  285. return this.keyBoardStyle.getShortHeight()
  286. }
  287. }
  288. }