1, 先看效果
2, 直接cv代码-- 先修改一下 资源配置 图标使用自己的
color.json配置
{
"integer": [
{
"name": "tab_row_column_image_width",
"value": 24
},
{
"name": "tab_row_column_image_height",
"value": 24
},
{
"name": "tab_row_column_text_font_size",
"value": 10
},
{
"name": "tab_row_column_width",
"value": 50
},
{
"name": "tab_row_column_height",
"value": 100
},
{
"name": "tab_row_offset",
"value": -60
},
{
"name": "tab_interval_number",
"value": 20
},
{
"name": "tab_image_width",
"value": 50
},
{
"name": "tab_image_height",
"value": 50
},
{
"name": "tab_text_size",
"value": 20
},
{
"name": "tab_margin_small",
"value": 10
},
{
"name": "tabs_bar_height",
"value": 0
},
{
"name": "tab_upgrade_text_font_size",
"value": 14
},
{
"name": "tab_upgrade_icon_size",
"value": 14
},
{
"name": "tab_mus_font_size",
"value": 12
},
{
"name": "tab_max_line",
"value": 1
},
{
"name": "tab_mus_height",
"value": 20
},
{
"name": "tab_upgrade_margin",
"value": 4
},
{
"name": "tab_upgrade_height",
"value": 36
},
{
"name": "tab_upgrade_padding",
"value": 12
},
{
"name": "tab_search_icon_width",
"value": 20
},
{
"name": "tab_search_icon_height",
"value": 20
},
{
"name": "tab_tab_font_size",
"value": 16
},
{
"name": "tab_tab_divider_width",
"value": 30
},
{
"name": "tab_divider_margin_top",
"value": 5
},
{
"name": "tab_side_margin_top",
"value": -20
},
{
"name": "tab_video_des_margin_bottom",
"value": 2
},
{
"name": "tab_play_time_text_font_size",
"value": 20
},
{
"name": "tab_play_time_text_width",
"value": 100
},
{
"name": "tab_play_time_text_height",
"value": 30
},
{
"name": "tab_play_time_text_margin",
"value": -100
},
{
"name": "tab_text1_height",
"value": 5
},
{
"name": "tab_text1_touch_height",
"value": 10
},
{
"name": "tab_text1_borderradius",
"value": 5
},
{
"name": "tab_text1_touch_border_radius",
"value": 0
},
{
"name": "tab_text1_margin_top",
"value": -5
},
{
"name": "tab_text1_margin_left",
"value": 15
},
{
"name": "tab_text3_width",
"value": 12
},
{
"name": "tab_text3_height",
"value": 12
},
{
"name": "tab_text3_border_radius",
"value": 6
},
{
"name": "tab_tabbar_height",
"value": 60
},
{
"name": "tab_head_image_width",
"value": 45
},
{
"name": "tab_head_image_height",
"value": 45
},
{
"name": "tab_head_image_border_width",
"value": 1
},
{
"name": "tab_focus_image_width",
"value": 20
},
{
"name": "tab_focus_image_height",
"value": 20
},
{
"name": "tab_focus_image_border_radius",
"value": 20
},
{
"name": "tab_focus_image_margin",
"value": -10
},
{
"name": "tab_like_image_width",
"value": 35
},
{
"name": "tab_like_image_height",
"value": 30
},
{
"name": "tab_like_image_margin_top",
"value": 18
},
{
"name": "tab_like_text_font_size",
"value": 10
},
{
"name": "tab_like_text_margin_top",
"value": 5
},
{
"name": "tab_relativecontainer_width",
"value": 60
},
{
"name": "tab_relativecontainer_height",
"value": 330
},
{
"name": "tab_name_text_font_size",
"value": 18
},
{
"name": "tab_name_text_margin_left",
"value": 10
},
{
"name": "tab_des_text_font_size",
"value": 14
},
{
"name": "tab_des_text_margin_top",
"value": 5
},
{
"name": "tab_des_text_padding_left",
"value": 10
},
{
"name": "tab_time_text_font_size",
"value": 10
},
{
"name": "tab_gray_background_margin_top",
"value": 16
},
{
"name": "tab_upgrade_filled_margin_top",
"value": 8
},
{
"name": "tab_arrow_right_margin_right",
"value": 10
},
{
"name": "tab_divider_margin_right",
"value": 5
},
{
"name": "tab_video_des_relativecontainer_height",
"value": 106
},
{
"name": "tab_search_image_margin",
"value": 20
},
{
"name": "tab_top_view_relativecontainer_height",
"value": 50
},
{
"name": "tab_top_view_divider_margin_top",
"value": 3
},
{
"name": "tab_top_view_divider_margin_left",
"value": -15
},
{
"name": "tab_white_top",
"value": 4
}
]
}
float.json配置
{
"float": [
{
"name": "mainPage_baseTab_size",
"value": "24vp"
},
{
"name": "mainPage_baseTab_top",
"value": "4vp"
},
{
"name": "mainPage_barHeight",
"value": "52vp"
},
{
"name": "rudder_barHeight",
"value": "90vp"
},
{
"name": "tab_text_font_size",
"value": "10fp"
},
{
"name": "content_font_size",
"value": "30fp"
},
{
"name": "title_font_size",
"value": "30fp"
},
{
"name": "text_size",
"value": "16fp"
},
{
"name": "double_text_size",
"value": "18fp"
},
{
"name": "current_text_size",
"value": "20fp"
},
{
"name": "back_text_size",
"value": "14fp"
},
{
"name": "text_line_height",
"value": "22vp"
},
{
"name": "divider_width",
"value": "48vp"
},
{
"name": "opacity_1",
"value": "1"
},
{
"name": "opacity_0",
"value": "0"
},
{
"name": "list_friction",
"value": "0.6"
},
{
"name": "size_text",
"value": "16vp"
},
{
"name": "margin_drawer_list",
"value": "4vp"
},
{
"name": "margin_tab_text",
"value": "6vp"
},
{
"name": "margin_under_tab",
"value": "7vp"
},
{
"name": "margin_eight",
"value": "8vp"
},
{
"name": "margin_index_top",
"value": "14vp"
},
{
"name": "margin_sixteen",
"value": "16vp"
},
{
"name": "margin_list",
"value": "17vp"
},
{
"name": "margin_index_bottom",
"value": "18vp"
},
{
"name": "margin_slide_top",
"value": "40vp"
},
{
"name": "margin_button_bottom",
"value": "48vp"
},
{
"name": "margin_side_tab_top",
"value": "74vp"
},
{
"name": "margin_sidebar_content",
"value": "284vp"
},
{
"name": "padding_double_tab_left",
"value": "4vp"
},
{
"name": "padding_rudder_tab",
"value": "11vp"
},
{
"name": "padding_bottom_tab",
"value": "12vp"
},
{
"name": "padding_drawer_row",
"value": "13vp"
},
{
"name": "padding_index_top",
"value": "44vp"
},
{
"name": "drawer_padding",
"value": "104vp"
}
]
}
integer.json 配置
{
"integer": [
{
"name": "tab_row_column_image_width",
"value": 24
},
{
"name": "tab_row_column_image_height",
"value": 24
},
{
"name": "tab_row_column_text_font_size",
"value": 10
},
{
"name": "tab_row_column_width",
"value": 50
},
{
"name": "tab_row_column_height",
"value": 100
},
{
"name": "tab_row_offset",
"value": -60
},
{
"name": "tab_interval_number",
"value": 20
},
{
"name": "tab_image_width",
"value": 50
},
{
"name": "tab_image_height",
"value": 50
},
{
"name": "tab_text_size",
"value": 20
},
{
"name": "tab_margin_small",
"value": 10
},
{
"name": "tabs_bar_height",
"value": 0
},
{
"name": "tab_upgrade_text_font_size",
"value": 14
},
{
"name": "tab_upgrade_icon_size",
"value": 14
},
{
"name": "tab_mus_font_size",
"value": 12
},
{
"name": "tab_max_line",
"value": 1
},
{
"name": "tab_mus_height",
"value": 20
},
{
"name": "tab_upgrade_margin",
"value": 4
},
{
"name": "tab_upgrade_height",
"value": 36
},
{
"name": "tab_upgrade_padding",
"value": 12
},
{
"name": "tab_search_icon_width",
"value": 20
},
{
"name": "tab_search_icon_height",
"value": 20
},
{
"name": "tab_tab_font_size",
"value": 16
},
{
"name": "tab_tab_divider_width",
"value": 30
},
{
"name": "tab_divider_margin_top",
"value": 5
},
{
"name": "tab_side_margin_top",
"value": -20
},
{
"name": "tab_video_des_margin_bottom",
"value": 2
},
{
"name": "tab_play_time_text_font_size",
"value": 20
},
{
"name": "tab_play_time_text_width",
"value": 100
},
{
"name": "tab_play_time_text_height",
"value": 30
},
{
"name": "tab_play_time_text_margin",
"value": -100
},
{
"name": "tab_text1_height",
"value": 5
},
{
"name": "tab_text1_touch_height",
"value": 10
},
{
"name": "tab_text1_borderradius",
"value": 5
},
{
"name": "tab_text1_touch_border_radius",
"value": 0
},
{
"name": "tab_text1_margin_top",
"value": -5
},
{
"name": "tab_text1_margin_left",
"value": 15
},
{
"name": "tab_text3_width",
"value": 12
},
{
"name": "tab_text3_height",
"value": 12
},
{
"name": "tab_text3_border_radius",
"value": 6
},
{
"name": "tab_tabbar_height",
"value": 60
},
{
"name": "tab_head_image_width",
"value": 45
},
{
"name": "tab_head_image_height",
"value": 45
},
{
"name": "tab_head_image_border_width",
"value": 1
},
{
"name": "tab_focus_image_width",
"value": 20
},
{
"name": "tab_focus_image_height",
"value": 20
},
{
"name": "tab_focus_image_border_radius",
"value": 20
},
{
"name": "tab_focus_image_margin",
"value": -10
},
{
"name": "tab_like_image_width",
"value": 35
},
{
"name": "tab_like_image_height",
"value": 30
},
{
"name": "tab_like_image_margin_top",
"value": 18
},
{
"name": "tab_like_text_font_size",
"value": 10
},
{
"name": "tab_like_text_margin_top",
"value": 5
},
{
"name": "tab_relativecontainer_width",
"value": 60
},
{
"name": "tab_relativecontainer_height",
"value": 330
},
{
"name": "tab_name_text_font_size",
"value": 18
},
{
"name": "tab_name_text_margin_left",
"value": 10
},
{
"name": "tab_des_text_font_size",
"value": 14
},
{
"name": "tab_des_text_margin_top",
"value": 5
},
{
"name": "tab_des_text_padding_left",
"value": 10
},
{
"name": "tab_time_text_font_size",
"value": 10
},
{
"name": "tab_gray_background_margin_top",
"value": 16
},
{
"name": "tab_upgrade_filled_margin_top",
"value": 8
},
{
"name": "tab_arrow_right_margin_right",
"value": 10
},
{
"name": "tab_divider_margin_right",
"value": 5
},
{
"name": "tab_video_des_relativecontainer_height",
"value": 106
},
{
"name": "tab_search_image_margin",
"value": 20
},
{
"name": "tab_top_view_relativecontainer_height",
"value": 50
},
{
"name": "tab_top_view_divider_margin_top",
"value": 3
},
{
"name": "tab_top_view_divider_margin_left",
"value": -15
},
{
"name": "tab_white_top",
"value": 4
}
]
}
3, 页面配置--新建3个页面
Constants.ets
export class Constants {
/**
* Index content width.
*/
static readonly INDEX_CONTENT_WIDTH: string = '91.1%';
/**
* Index divider height.
*/
static readonly DIVIDER_HEIGHT: number = 0.5;
/**
* Index divider width.
*/
static readonly DIVIDER_WIDTH: string = '93%';
/**
* Drawer divider width.
*/
static readonly DIVIDER_DRAWER_WIDTH: string = '90%';
/**
* Card title height.
*/
static readonly CARD_TITLE_HEIGHT: number = 20;
/**
* Card text height.
*/
static readonly CARD_TEXT_HEIGHT: number = 48;
/**
* Index title height.
*/
static readonly INDEX_TITLE_HEIGHT: number = 112;
/**
* Full screen width.
*/
static readonly FULL_WIDTH: string = '100%';
/**
* Full screen height.
*/
static readonly FULL_HEIGHT: string = '100%';
/**
* Font size of unchecked title.
*/
static readonly FONT_SIZE_UNCHECKED = 18;
/**
* Font size of checked title.
*/
static readonly FONT_SIZE_CHECKED: number = 24;
/**
* Content height.
*/
static readonly CONTENT_HEIGHT: number = 300;
/**
* List height.
*/
static readonly LIST_HEIGHT: number = 48;
/**
* List card width.
*/
static readonly LIST_CARD_WIDTH: number = 272;
/**
* List card height.
*/
static readonly LIST_CARD_HEIGHT: number = 344;
/**
* List content height.
*/
static readonly LIST_CONTENT_HEIGHT: string = '110%';
/**
* Background tab height.
*/
static readonly BACKGROUND_TAB_HEIGHT: number = 40;
/**
* Index button height.
*/
static readonly INDEX_BUTTON_HEIGHT: number = 60;
/**
* Background tab width.
*/
static readonly BACKGROUND_TAB_WIDTH: number = 96;
/**
* Drawer width.
*/
static readonly DRAWER_WIDTH: number = 264;
/**
* Sub tab width.
*/
static readonly SUB_TAB_WIDTH: number = 56;
/**
* Sub slide width.
*/
static readonly SUB_SLIDE_TAB_WIDTH: number = 56;
/**
* Sub tab bottom height.
*/
static readonly SUB_TAB_BOT_HEIGHT: number = 25;
/**
* Sub tab width.
*/
static readonly SUB_TAB_HEIGHT: number = 30;
/**
* Sub list width.
*/
static readonly SUB_LIST_WIDTH: string = '85%';
/**
* Side tab width.
*/
static readonly SIDE_TAB_WIDTH: string = '27.8%';
/**
* Side contend width.
*/
static readonly SIDE_CONTEND_WIDTH: string = '72.2%';
/**
* Tab index0.
*/
static readonly TAB_INDEX_ZERO: number = 0;
/**
* Tab index1.
*/
static readonly TAB_INDEX_ONE: number = 1;
/**
* Tab index2.
*/
static readonly TAB_INDEX_TWO: number = 2;
/**
* Tab index3.
*/
static readonly TAB_INDEX_THREE: number = 3;
/**
* Tab index4.
*/
static readonly TAB_INDEX_FOUR: number = 4;
/**
* Tab index5.
*/
static readonly TAB_INDEX_FIVE: number = 5;
/**
* Image tab size.
*/
static readonly IMAGE_SIZE_TAB: number = 22;
/**
* Image middle size.
*/
static readonly IMAGE_SIZE_MIDDLE: number = 56;
/**
* More image width.
*/
static readonly MORE_IMAGE_WIDTH: number = 20;
/**
* More image height.
*/
static readonly MORE_IMAGE_HEIGHT: number = 15;
/**
* Drawer image height or width.
*/
static readonly DRAWER_IMAGE_HEIGHT_WIDTH: number = 24;
/**
* List image height or width.
*/
static readonly LIST_IMAGE_HEIGHT_WIDTH: number = 40;
/**
* Image offset.
*/
static readonly IMAGE_OFFSET: number = -15;
/**
* Icon offset.
*/
static readonly ICON_Offset: number = -3;
/**
* Animation duration.
*/
static readonly ANIMATION_DURATION: number = 300;
/**
* Margin sixteen.
*/
static readonly MARGIN_SIXTEEN: number = 16;
/**
* Margin button top.
*/
static readonly MARGIN_BUTTON_TOP: number = 48;
/**
* Translate top.
*/
static readonly TRANSLATE_TOP: number = -40;
/**
* Translate bottom.
*/
static readonly TRANSLATE_BOTTOM: number = 40;
/**
* Border radius drawer.
*/
static readonly BORDER_RADIUS_DRAWER: number = 16;
/**
* Border radius index list.
*/
static readonly BORDER_RADIUS_INDEX_LIST: number = 18;
/**
* Border radius drawer content.
*/
static readonly BORDER_RADIUS_DRAWER_CONTENT: number = 20;
/**
* Border radius back tab.
*/
static readonly BORDER_RADIUS_BACK_TAB: number = 21;
/**
* Divider strokeWidth.
*/
static readonly STROKE_WIDTH: number = 2;
/**
* Slice index index0.
*/
static readonly SLICE_INDEX_ZERO: number = 0;
/**
* Slice index index6.
*/
static readonly SLICE_INDEX_SIX: number = 6;
/**
* fontWeight.
*/
static readonly FONT_WEIGHT_TAB: number = 600;
/**
* TopTabData.
*/
static readonly TOP_TAB_DATA: string[] = ['文学', '交友', '直播', '视频', '盛典', '潮玩'];
/**
* Routes.
*/
static readonly ROUTES: Route[] = [
{
title: '底部导航',
child: [
{
text: '常见底部导航',
to: 'BottomTab'
},
{
text: '舵式底部导航',
to: 'RudderStyleTab'
},
{
text: 'TabContent视频内容滑动并在Tabbar上显示',
to: 'TabContentOverflow'
}
]
},
{
title: '顶部导航',
child: [
{
text: '下划线样式',
to: 'UnderlineTab'
},
{
text: '背景高亮样式',
to: 'BackgroundLightTab'
},
{
text: '文字样式',
to: 'WordTab'
},
{
text: '双层嵌套样式实现1',
to: 'DoubleNestingTabOne'
},
{
text: '双层嵌套样式实现2',
to: 'DoubleNestingTabTwo'
},
{
text: '可滑动+更多按钮',
to: 'SlideAndMoreTab'
}
]
},
{
title: '侧边导航',
child: [
{
text: '常见侧边导航',
to: 'SideTab'
},
{
text: '抽屉式侧边导航',
to: 'DrawerTab'
}
]
}
]
}
/**
* Route type define.
*/
export interface Route {
title: string,
child: Array<ChildRoute>
}
/**
* ChildRoute type define.
*/
export interface ChildRoute {
text: string,
to: string
}
Index.ets
import { initTabTuData } from './TabViewModel';
import { BottomTabModel } from './TabItem';
import { Constants } from './Constants';
@Entry
@Component
struct OstrichStyleTab {
@State tabArray: Array<BottomTabModel> = initTabTuData();
@State currentIndex: number = 0;
@State iconOffset: number = 0;
@State initNumber: number = 0;
private controller: TabsController = new TabsController();
@Builder
Tab(selectImage: Resource, defaultImage: Resource, title: string, middleMode: boolean, index: number) {
Column() {
if (index === Constants.TAB_INDEX_TWO) {
Image(defaultImage)
.size({ width: Constants.IMAGE_SIZE_MIDDLE, height: Constants.IMAGE_SIZE_MIDDLE })
.offset({ y: Constants.IMAGE_OFFSET })
} else {
Image(this.currentIndex === index ? selectImage : defaultImage)
.size({ width: Constants.IMAGE_SIZE_TAB, height: Constants.IMAGE_SIZE_TAB })
.offset({
y: (this.currentIndex === index && this.currentIndex !== Constants.TAB_INDEX_TWO)
? this.iconOffset : this.initNumber
})
.objectFit(ImageFit.Contain)
.animation({
duration: Constants.ANIMATION_DURATION,
curve: Curve.Ease,
playMode: PlayMode.Normal
})
}
if (!middleMode) {
Text(title)
.fontSize($r('app.float.tab_text_font_size'))
.margin({ top: $r('app.float.margin_tab_text') })
.fontColor(this.currentIndex === index ? $r('app.color.current_color') : $r('app.color.text_color'))
}
}
.padding({ top: $r('app.float.padding_rudder_tab') })
.width(Constants.FULL_WIDTH)
.backgroundColor($r('app.color.tab_color'))
.height($r('app.float.rudder_barHeight'))
.translate({ y: Constants.TRANSLATE_BOTTOM })
.onClick(() => {
if (index !== Constants.TAB_INDEX_TWO) {
this.currentIndex = index;
this.controller.changeIndex(index);
this.iconOffset = Constants.ICON_Offset;
}
})
}
build() {
Column() {
Stack({ alignContent: Alignment.BottomStart }) {
Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
ForEach(this.tabArray, (item: BottomTabModel, index: number) => {
if (index === Constants.TAB_INDEX_TWO) {
TabContent() {
}
.backgroundColor(Color.White)
} else {
TabContent() {
Row() {
Text(item.title)
.fontSize($r('app.float.content_font_size'))
}
.height(Constants.CONTENT_HEIGHT)
.width(Constants.FULL_WIDTH)
.justifyContent(FlexAlign.Center)
}
.backgroundColor(Color.White)
}
}, (item: BottomTabModel, index: number) => JSON.stringify(item) + index)
}
.scrollable(false)
.barHeight(this.initNumber)
.animationDuration(Constants.ANIMATION_DURATION)
Flex() {
ForEach(this.tabArray, (item: BottomTabModel, index: number) => {
this.Tab(item.selectImage, item.defaultImage, item.title, item.middleMode, index)
}, (item: BottomTabModel, index: number) => JSON.stringify(item) + index)
}
.backgroundColor('#00090a1c')
.margin({
top: '0.00vp',
right: '0.00vp',
bottom: '0',
left: '0.00vp'
})
}
}
.height(Constants.FULL_HEIGHT)
}
}
TabItem.ets
export class TabItem {
id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
export class BottomTabModel {
selectImage: Resource;
defaultImage: Resource;
middleMode: boolean;
title: string;
isSelected: boolean = false;
constructor(selectImage: Resource, defaultImage: Resource, title: string, middleMode = false) {
this.selectImage = selectImage;
this.defaultImage = defaultImage;
this.title = title;
this.middleMode = middleMode;
}
}
TabViewModel.ets
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BottomTabModel, TabItem } from './TabItem';
export function initTabData(): TabItem[] {
let tabDataArray: TabItem[] = [];
return tabDataArray;
}
export function initTabTuData(): BottomTabModel[] {
let tabTuDataArray: BottomTabModel[] = [];
TabTuItemData.forEach((item: BottomTabModel) => {
tabTuDataArray.push(new BottomTabModel(item.defaultImage, item.selectImage, item.title, item.middleMode));
})
return tabTuDataArray;
}
const TabTuItemData: BottomTabModel[] = [
new BottomTabModel($r('app.media.home'), $r('app.media.activeHome'), '首页'),
new BottomTabModel($r('app.media.star'), $r('app.media.activeStar'), '动态'),
new BottomTabModel($r('app.media.activePlus'), $r('app.media.activePlus'), '', true),
new BottomTabModel($r('app.media.message'), $r('app.media.activeMessage'), '消息'),
new BottomTabModel($r('app.media.people'), $r('app.media.activePeople'), '我的')
]