1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16if (!("finalizeConstruction" in ViewPU.prototype)) { 17 Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { }); 18} 19const DEFAULT_BAR_WIDTH = 96; 20const DEFAULT_BAR_HEIGHT = 48; 21const TEXT_WIDTH_HEIGHT_SIZE = 24; 22const TEXT_FONT_WEIGHT = 500; 23const TEXT_LIGHT_HEIGHT = 14; 24export class AtomicServiceTabs extends ViewPU { 25 constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) { 26 super(parent, __localStorage, elmtId, extraInfo); 27 if (typeof paramsLambda === 'function') { 28 this.paramsGenerator_ = paramsLambda; 29 } 30 this.tabContents = undefined; 31 this.__tabBarOptionsArray = new SynchedPropertyObjectOneWayPU(params.tabBarOptionsArray, this, 'tabBarOptionsArray'); 32 this.__tabBarPosition = new SynchedPropertySimpleOneWayPU(params.tabBarPosition, this, 'tabBarPosition'); 33 this.__barBackgroundColor = new SynchedPropertyObjectOneWayPU(params.barBackgroundColor, this, 'barBackgroundColor'); 34 this.__index = new SynchedPropertyObjectOneWayPU(params.index, this, 'index'); 35 this.__barOverlap = new SynchedPropertySimpleOneWayPU(params.barOverlap, this, 'barOverlap'); 36 this.__layoutMode = new SynchedPropertySimpleOneWayPU(params.layoutMode, this, 'layoutMode'); 37 this.controller = new TabsController(); 38 this.onChange = undefined; 39 this.onTabBarClick = undefined; 40 this.onContentWillChange = undefined; 41 this.__selectedIndex = new ObservedPropertySimplePU(0, this, 'selectedIndex'); 42 this.__barModeStatus = new ObservedPropertySimplePU(BarMode.Fixed, this, 'arModeStatus'); 43 this.__tabBarHeight = new ObservedPropertyObjectPU(undefined, this, 'tabBarHeight'); 44 this.isIconTextExist = false; 45 this.setInitiallyProvidedValue(params); 46 this.declareWatch('tabBarPosition', this.barPositionChangeBySingleMode); 47 this.finalizeConstruction(); 48 } 49 setInitiallyProvidedValue(params) { 50 if (params.tabContents !== undefined) { 51 this.tabContents = params.tabContents; 52 } 53 if (params.tabBarPosition === undefined) { 54 this.__tabBarPosition.set(TabBarPosition.BOTTOM); 55 } 56 if (params.barBackgroundColor === undefined) { 57 this.__barBackgroundColor.set(Color.Transparent); 58 } 59 if (params.index === undefined) { 60 this.__index.set(0); 61 } 62 if (params.barOverlap === undefined) { 63 this.__barOverlap.set(true); 64 } 65 if (params.layoutMode === undefined) { 66 this.__layoutMode.set(LayoutMode.VERTICAL); 67 } 68 if (params.controller !== undefined) { 69 this.controller = params.controller; 70 } 71 if (params.onChange !== undefined) { 72 this.onChange = params.onChange; 73 } 74 if (params.onTabBarClick !== undefined) { 75 this.onTabBarClick = params.onTabBarClick; 76 } 77 if (params.onContentWillChange !== undefined) { 78 this.onContentWillChange = params.onContentWillChange; 79 } 80 if (params.selectedIndex !== undefined) { 81 this.selectedIndex = params.selectedIndex; 82 } 83 if (params.barModeStatus !== undefined) { 84 this.barModeStatus = params.barModeStatus; 85 } 86 if (params.tabBarHeight !== undefined) { 87 this.tabBarHeight = params.tabBarHeight; 88 } 89 if (params.isIconTextExist !== undefined) { 90 this.isIconTextExist = params.isIconTextExist; 91 } 92 } 93 updateStateVars(params) { 94 this.__tabBarOptionsArray.reset(params.tabBarOptionsArray); 95 this.__tabBarPosition.reset(params.tabBarPosition); 96 this.__barBackgroundColor.reset(params.barBackgroundColor); 97 this.__index.reset(params.index); 98 this.__barOverlap.reset(params.barOverlap); 99 this.__layoutMode.reset(params.layoutMode); 100 } 101 purgeVariableDependenciesOnElmtId(rmElmtId) { 102 this.__tabBarOptionsArray.purgeDependencyOnElmtId(rmElmtId); 103 this.__tabBarPosition.purgeDependencyOnElmtId(rmElmtId); 104 this.__barBackgroundColor.purgeDependencyOnElmtId(rmElmtId); 105 this.__index.purgeDependencyOnElmtId(rmElmtId); 106 this.__barOverlap.purgeDependencyOnElmtId(rmElmtId); 107 this.__layoutMode.purgeDependencyOnElmtId(rmElmtId); 108 this.__selectedIndex.purgeDependencyOnElmtId(rmElmtId); 109 this.__barModeStatus.purgeDependencyOnElmtId(rmElmtId); 110 this.__tabBarHeight.purgeDependencyOnElmtId(rmElmtId); 111 } 112 aboutToBeDeleted() { 113 this.__tabBarOptionsArray.aboutToBeDeleted(); 114 this.__tabBarPosition.aboutToBeDeleted(); 115 this.__barBackgroundColor.aboutToBeDeleted(); 116 this.__index.aboutToBeDeleted(); 117 this.__barOverlap.aboutToBeDeleted(); 118 this.__layoutMode.aboutToBeDeleted(); 119 this.__selectedIndex.aboutToBeDeleted(); 120 this.__barModeStatus.aboutToBeDeleted(); 121 this.__tabBarHeight.aboutToBeDeleted(); 122 SubscriberManager.Get().delete(this.id__()); 123 this.aboutToBeDeletedInternal(); 124 } 125 get tabBarOptionsArray() { 126 return this.__tabBarOptionsArray.get(); 127 } 128 set tabBarOptionsArray(newValue) { 129 this.__tabBarOptionsArray.set(newValue); 130 } 131 get tabBarPosition() { 132 return this.__tabBarPosition.get(); 133 } 134 set tabBarPosition(newValue) { 135 this.__tabBarPosition.set(newValue); 136 } 137 get barBackgroundColor() { 138 return this.__barBackgroundColor.get(); 139 } 140 set barBackgroundColor(newValue) { 141 this.__barBackgroundColor.set(newValue); 142 } 143 get index() { 144 return this.__index.get(); 145 } 146 set index(newValue) { 147 this.__index.set(newValue); 148 } 149 get barOverlap() { 150 return this.__barOverlap.get(); 151 } 152 set barOverlap(newValue) { 153 this.__barOverlap.set(newValue); 154 } 155 get layoutMode() { 156 return this.__layoutMode.get(); 157 } 158 set layoutMode(newValue) { 159 this.__layoutMode.set(newValue); 160 } 161 get selectedIndex() { 162 return this.__selectedIndex.get(); 163 } 164 set selectedIndex(newValue) { 165 this.__selectedIndex.set(newValue); 166 } 167 get barModeStatus() { 168 return this.__barModeStatus.get(); 169 } 170 set barModeStatus(newValue) { 171 this.__barModeStatus.set(newValue); 172 } 173 get tabBarHeight() { 174 return this.__tabBarHeight.get(); 175 } 176 set tabBarHeight(newValue) { 177 this.__tabBarHeight.set(newValue); 178 } 179 aboutToAppear() { 180 if (this.tabBarOptionsArray[0].icon && this.tabBarOptionsArray[0].text) { 181 this.isIconTextExist = true; 182 } 183 this.barPositionChangeBySingleMode(); 184 } 185 /** 186 *单图标或文本场景下监听位置变化影响tabbar高度布局样式 187 */ 188 barPositionChangeBySingleMode() { 189 if (this.isIconTextExist) { 190 return; 191 } 192 if (this.tabBarPosition === TabBarPosition.LEFT) { 193 this.tabBarHeight = (50 / this.tabBarOptionsArray.length + '%'); 194 this.barModeStatus = BarMode.Scrollable; 195 } 196 else { 197 this.barModeStatus = BarMode.Fixed; 198 this.tabBarHeight = undefined; 199 } 200 } 201 TabBuilder(item, index, parent = null) { 202 this.observeComponentCreation2((elmtId, isInitialRender) => { 203 Flex.create({ 204 alignItems: ItemAlign.Center, 205 justifyContent: FlexAlign.Center 206 }); 207 Flex.height(ObservedObject.GetRawObject(this.tabBarHeight)); 208 }, Flex); 209 this.observeComponentCreation2((elmtId, isInitialRender) => { 210 If.create(); 211 if (item.icon) { 212 this.ifElseBranchUpdateFunction(0, () => { 213 this.observeComponentCreation2((elmtId, isInitialRender) => { 214 Image.create(item.icon); 215 Image.width(TEXT_WIDTH_HEIGHT_SIZE); 216 Image.height(TEXT_WIDTH_HEIGHT_SIZE); 217 Image.objectFit(ImageFit.Contain); 218 Image.fillColor(this.selectedIndex === index ? item.selectedColor : item.unselectedColor); 219 Image.backgroundColor(Color.Transparent); 220 Image.flexShrink(0); 221 }, Image); 222 }); 223 } 224 else { 225 this.ifElseBranchUpdateFunction(1, () => { 226 this.observeComponentCreation2((elmtId, isInitialRender) => { 227 Text.create(item.text); 228 Text.textOverflow({ overflow: TextOverflow.Ellipsis }); 229 Text.maxLines(1); 230 Text.fontColor(this.selectedIndex === index ? item.selectedColor : item.unselectedColor); 231 Text.maxFontSize({ 'id': -1, 'type': 10002, params: ['sys.float.ohos_id_text_size_button3'], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }); 232 Text.minFontSize(9); 233 Text.fontWeight(TEXT_FONT_WEIGHT); 234 Text.lineHeight(TEXT_LIGHT_HEIGHT); 235 Text.textAlign(TextAlign.Center); 236 Text.focusOnTouch(true); 237 Text.backgroundColor(Color.Transparent); 238 }, Text); 239 Text.pop(); 240 }); 241 } 242 }, If); 243 If.pop(); 244 Flex.pop(); 245 } 246 initialRender() { 247 this.observeComponentCreation2((elmtId, isInitialRender) => { 248 Tabs.create({ 249 barPosition: this.tabBarPosition === TabBarPosition.LEFT ? BarPosition.Start : BarPosition.End, 250 index: this.index, 251 controller: this.controller 252 }); 253 Tabs.safeAreaPadding({ 254 // barHeight设置具体高度时,tabBar的背景色不会延伸到底部安全区,需要新增该属性值使tabBar和安全区背景色一致 255 bottom: 0 256 }); 257 Tabs.animationDuration(0); 258 Tabs.barBackgroundColor(ObservedObject.GetRawObject(this.barBackgroundColor)); 259 Tabs.divider(null); 260 Tabs.barMode(this.barModeStatus); 261 Tabs.vertical(this.tabBarPosition === TabBarPosition.LEFT ? true : false); 262 Tabs.scrollable(false); 263 Tabs.barOverlap(this.barOverlap); 264 Tabs.barBackgroundBlurStyle(BlurStyle.COMPONENT_THICK); 265 Tabs.onChange((index) => { 266 if (this.onChange) { 267 this.onChange(index); 268 } 269 this.selectedIndex = index; 270 }); 271 Tabs.onTabBarClick(this.onTabBarClick); 272 Tabs.onContentWillChange(this.onContentWillChange); 273 Tabs.barWidth(this.isIconTextExist ? undefined : 274 (this.tabBarPosition === TabBarPosition.LEFT) ? DEFAULT_BAR_WIDTH : '100%'); 275 Tabs.barHeight(this.isIconTextExist ? undefined : 276 (this.tabBarPosition === TabBarPosition.BOTTOM) ? DEFAULT_BAR_HEIGHT : '100%'); 277 Tabs.width((!this.tabContents && this.tabBarPosition === TabBarPosition.LEFT) ? DEFAULT_BAR_WIDTH : '100%'); 278 Tabs.height((!this.tabContents && this.tabBarPosition === TabBarPosition.BOTTOM) ? DEFAULT_BAR_HEIGHT : '100%'); 279 }, Tabs); 280 this.observeComponentCreation2((elmtId, isInitialRender) => { 281 ForEach.create(); 282 const forEachItemGenFunction = (_item, index) => { 283 const item = _item; 284 this.observeComponentCreation2((elmtId, isInitialRender) => { 285 If.create(); 286 if (item) { 287 this.ifElseBranchUpdateFunction(0, () => { 288 this.observeComponentCreation2((elmtId, isInitialRender) => { 289 TabContent.create(() => { 290 this.observeComponentCreation2((elmtId, isInitialRender) => { 291 If.create(); 292 if (this.tabContents && this.tabContents[index]) { 293 this.ifElseBranchUpdateFunction(0, () => { 294 this.tabContents[index]?.bind(this)?.(); 295 }); 296 } 297 else { 298 this.ifElseBranchUpdateFunction(1, () => { 299 }); 300 } 301 }, If); 302 If.pop(); 303 }); 304 TabContent.tabBar(this.isIconTextExist ? BottomTabBarStyle.of(item.icon, item.text).layoutMode(this.layoutMode) 305 .labelStyle({ unselectedColor: item.unselectedColor, selectedColor: item.selectedColor }) 306 .iconStyle({ unselectedColor: item.unselectedColor, selectedColor: item.selectedColor }) : { builder: () => { 307 this.TabBuilder.call(this, item, index); 308 } }); 309 TabContent.width((!this.tabContents && this.tabBarPosition === TabBarPosition.LEFT) ? DEFAULT_BAR_WIDTH : '100%'); 310 TabContent.height((!this.tabContents && this.tabBarPosition === TabBarPosition.BOTTOM) ? DEFAULT_BAR_HEIGHT : '100%'); 311 }, TabContent); 312 TabContent.pop(); 313 }); 314 } 315 else { 316 this.ifElseBranchUpdateFunction(1, () => { 317 }); 318 } 319 }, If); 320 If.pop(); 321 }; 322 this.forEachUpdateFunction(elmtId, this.tabBarOptionsArray, forEachItemGenFunction, undefined, true, false); 323 }, ForEach); 324 ForEach.pop(); 325 Tabs.pop(); 326 } 327 rerender() { 328 this.updateDirtyElements(); 329 } 330} 331export class TabBarOptions { 332 constructor(icon, text, unselectedColor, selectedColor) { 333 this.icon = icon; 334 this.text = text; 335 this.unselectedColor = unselectedColor; 336 this.selectedColor = selectedColor; 337 } 338} 339 340export var TabBarPosition; 341(function (TabBarPosition) { 342 TabBarPosition[TabBarPosition['LEFT'] = 0] = 'LEFT'; 343 TabBarPosition[TabBarPosition['BOTTOM'] = 1] = 'BOTTOM'; 344})(TabBarPosition || (TabBarPosition = {})); 345 346export default { AtomicServiceTabs, TabBarOptions, TabBarPosition};