1/* 2 * Copyright (c) 2025 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 16import { memo, __memo_context_type, __memo_id_type } from '@ohos.arkui.stateManagement' // should be insert by ui-plugins 17import { Text, TextAttribute, Column, Component, Button, ButtonAttribute, ClickEvent, UserView, Entry, Tabs, TabContent, SubTabBarStyle, 18 Row, ForEach, Position, Builder, Margin, BarMode, OnTabsAnimationStartCallback, TabsAnimationEvent, TabsOptions, 19 Color, FlexAlign, $r, Image, SizeOptions, Position, AnimateParam, Flex,FlexDirection,FlexAlign,ItemAlign} from '@ohos.arkui.component' // TextAttribute should be insert by ui-plugins 20import { State, Link, StateDecoratedVariable, MutableState, stateOf, observableProxy } from '@ohos.arkui.stateManagement' // should be insert by ui-plugins 21import hilog from '@ohos.hilog' 22import { UIContext, Router } from '@ohos.arkui.UIContext' 23import router from '@ohos.router' 24 25@Entry 26@Component 27export struct TabViewComponent { 28 // 配置起始的页签索引 29 @State selectedIndex: number = 0; 30 // 初始化Tab控制器 31 @State tabArray: string[] = ['首页', '新闻', 32 '视频', '朋友圈', '我的']; 33 @State imageArray: string[] = 34 ['app.media.custom_tab_home', 'app.media.custom_tab_new', 'app.media.custom_tab_video', 35 'app.media.custom_tab_friend','app.media.custom_tab_user']; 36 @State imageClickArray: string[] = 37 ['app.media.custom_tab_home_selected', 'app.media.custom_tab_new_selected', 'app.media.custom_tab_video_selected', 38 'app.media.custom_tab_friend_selected','app.media.custom_tab_user_selected']; 39 40 @State fontColor: string = '#182431'; 41 @State selectedFontColor: string = '#007DFF'; 42 43 @Builder tabBuilder(item: string, index: number) { 44 Column() { 45 if (index === 2) { 46 Column() { 47 Image(this.selectedIndex === index ? $r('app.media.custom_tab_video_selected') : 48 $r('app.media.custom_tab_video')) 49 .size({ 50 width: 43, 51 height: 43 52 } as SizeOptions) 53 } 54 .width(52) 55 .height(52) 56 // TODO:知识点:通过设置borderRadius以及margin的top值实现圆弧外轮廓效果。 57 .borderRadius(24) 58 .margin({ top: -15 } as Margin) 59 .backgroundColor(Color.White) 60 .justifyContent(FlexAlign.Center) 61 } else { 62 Image(this.selectedIndex === index ? $r(this.imageClickArray[index]) : $r(this.imageArray[index])) 63 .width(24) 64 .height(24) 65 .margin({ bottom: 4 } as Margin) 66 .size({ 67 width: 28, 68 height: 28 69 } as SizeOptions)// TODO:知识点:通过offset控制图片的纵向偏移。 70 .offset({ 71 y: (this.selectedIndex === index && 72 this.selectedIndex !== 2) ? 73 -3 : 0 74 } as Position)// TODO:知识点:组件的某些通用属性变化时,可以通过属性动画animation实现过渡效果。本示例的动画效果是tabBar的图片向上偏移一小段距离 75 .animation({ 76 duration: 400, 77 iterations: 1, 78 } as AnimateParam) 79 } 80 Text(item) 81 .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor) 82 .fontSize(10) 83 .fontWeight(500) 84 .lineHeight(14) 85 }.width('100%') 86 .onClick((e: ClickEvent) => { 87 // 更新被选中的tabBar下标 88 this.selectedIndex = index; 89 }) 90 } 91 92 build() { 93 Column() { 94 Row() { 95 Text($r('app.string.custom_return')) 96 } 97 .margin(3) 98 .width('100%') 99 .onClick((e: ClickEvent) => { 100 this.getUIContext().getRouter().back(); 101 }) 102 Tabs({ index: this.selectedIndex } as TabsOptions) { 103 // 首页模块,可根据开发者实际业务替换TabContent中的布局 104 TabContent() { 105 Text($r('app.string.custom_tab_home')) 106 .fontSize(26) 107 .padding(20) 108 } 109 110 // 新闻模块,可根据开发者实际业务替换TabContent中的布局 111 TabContent() { 112 Text($r('app.string.custom_news')) 113 .fontSize(26) 114 } 115 116 // 视频模块,可根据开发者实际业务替换TabContent中的布局 117 TabContent() { 118 Text($r('app.string.custom_video')) 119 .fontSize(26) 120 } 121 122 // 朋友圈模块,可根据开发者实际业务替换TabContent中的布局 123 TabContent() { 124 Text($r('app.string.custom_friend')) 125 .fontSize(26) 126 } 127 128 // 我的模块,可根据开发者实际业务替换TabContent中的布局 129 TabContent() { 130 Text($r('app.string.custom_tab_mine')) 131 .fontSize(26) 132 } 133 } 134 .vertical(false) 135 .scrollable(true) 136 .layoutWeight(1) 137 .backgroundColor('#ffdbd9d9') 138 .barHeight(1) 139 .onAnimationStart((index: number, targetIndex: number) => { 140 this.selectedIndex = targetIndex; 141 } as OnTabsAnimationStartCallback) 142 /** 143 * 自定义TabBar组件 144 * selectedIndex: 配置起始的页签索引 145 * tabsInfo: tab数据源,类型为TabBarInfo 146 */ 147 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) { 148 ForEach(this.tabArray, (item: string, tabBarIndex: number) => { 149 // 单独一个TabBar组件 150 this.tabBuilder(item, tabBarIndex) 151 }) 152 } 153 } 154 .width('100%') 155 .height('100%') 156 } 157} 158 159