• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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