鸿蒙ArkTS Tabs组件开发底部导航栏,可自适应平板和手机,相当于Android开发中的MainActivity+Fragment的底部导航栏模式。
一、主页:MainPage.ets
import { BreakpointSystem, BreakpointConstants, StyleConstants, PageConstants, } from '@ohos/common';? // 通用工具
import { Chat } from '@ohos/chat';? // 子模块 相当于Android 的Fragment
import { Contact } from '@ohos/Contact';? // 子模块
import { Work } from '@ohos/Work';? //? 子模块
import { Mine } from '@ohos/Mine';? //? 子模块
import { buttonInfo, ButtonInfoModel } from '../viewmodel/MainPageData'; // 底部导航数据
@Entry
@Component
struct MainPage {
? @StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';
? @State currentPageIndex: number = 0;
? private breakpointSystem = new BreakpointSystem();
? aboutToAppear() {
? ? this.breakpointSystem.register();
? }
? aboutToDisappear() {
? ? this.breakpointSystem.unregister();
? }
? @Builder BottomNavigation(button: ButtonInfoModel) {
? ? Column({ space: PageConstants.BUTTON_SPACE }) {? //? static readonly BUTTON_SPACE: string = '6vp';
? ? ? Image(this.currentPageIndex === button.index button.selectImg : button.img)
? ? ? ? .objectFit(ImageFit.Contain)
? ? ? ? .width($r('app.float.main_image_size'))
? ? ? ? .height($r('app.float.main_image_size'))
? ? ? Text(button.title)
? ? ? ? .fontColor(this.currentPageIndex === button.index $r('app.color.focus_color') : $r('app.color.un_focus_color'))
? ? ? ? .opacity(this.currentPageIndex === button.index StyleConstants.FULL_OPACITY : StyleConstants.SIXTY_OPACITY)
? ? ? ? .fontWeight(StyleConstants.FONT_WEIGHT_FIVE)
? ? ? ? .textAlign(TextAlign.Center)
? ? ? ? .fontSize($r('app.float.micro_font_size'))
? ? }
? ? .width(StyleConstants.FULL_WIDTH)
? ? .height(StyleConstants.FULL_HEIGHT)
? ? .alignItems(HorizontalAlign.Center)
? ? .justifyContent(FlexAlign.Center)
? }
? build() {
? ? Column() {
? ? ? Tabs({
? ? ? ? barPosition: this.currentBreakpoint === BreakpointConstants.BREAKPOINT_LG
? ? ? ? BarPosition.Start : BarPosition.End,
? ? ? ? index: this.currentPageIndex,
? ? ? }) {
? ? ? ? TabContent() {
? ? ? ? ? Chat() // 子模块
? ? ? ? }.tabBar(this.BottomNavigation(buttonInfo[0]))
? ? ? ? TabContent() {
? ? ? ? ? Contact() // 子模块
? ? ? ? }.tabBar(this.BottomNavigation(buttonInfo[1]))
? ? ? ? TabContent() {
? ? ? ? ? Work() // 子模块
? ? ? ? }.tabBar(this.BottomNavigation(buttonInfo[2]))
? ? ? ? TabContent() {
? ? ? ? ? Mine() // 子模块
? ? ? ? }.tabBar(this.BottomNavigation(buttonInfo[3]))
? ? ? }
? ? ? .barWidth(this.currentBreakpoint === BreakpointConstants.BREAKPOINT_LG
? ? ? $r('app.float.bar_width') : StyleConstants.FULL_WIDTH)
? ? ? .barHeight(this.currentBreakpoint === BreakpointConstants.BREAKPOINT_LG
? ? ? StyleConstants.SIXTY_HEIGHT : $r('app.float.vp_fifty_six'))
? ? ? .vertical(this.currentBreakpoint === BreakpointConstants.BREAKPOINT_LG)
? ? ? .scrollable(false)
? ? ? .onChange((index: number) => {
? ? ? ? this.currentPageIndex = index;
? ? ? ? // 提前查询数据
? ? ? ? // if (index === 1) {
? ? ? ? //? this.queryShopCart();
? ? ? ? // } else if (index === 2) {
? ? ? ? //? this.queryOrderList();
? ? ? ? // }
? ? ? })
? ? }
? ? .backgroundColor($r('app.color.page_background'))
? }
}
StyleConstants.ets:
/**
* Constants for common style.
*/
export class StyleConstants {
? /**
? * Component width percentage: 100%.
? */
? static readonly FULL_WIDTH: string = '100%';
? /**
? * Component height percentage: 100%.
? */
? static readonly FULL_HEIGHT: string = '100%';
? /**
? * Component height percentage: 70%.
? */
? static readonly SEVENTY_HEIGHT: string = '70%';
? /**
? * Component height percentage: 60%.
? */
? static readonly SIXTY_HEIGHT: string = '60%';
? /**
? * Component width percentage: 60%.
? */
? static readonly SIXTY_WIDTH: string = '60%';
? /**
? * Component height percentage: 50%.
? */
? static readonly FIFTY_HEIGHT: string = '50%';
? /**
? * Component height percentage: 50%.
? */
? static readonly HUNDRED_FIFTEEN_WIDTH: string = '115%';
? /**
? * Component space vp : 4.
? */
? static readonly FOUR_SPACE: string = '4vp';
? /**
? * Component space vp : 12.
? */
? static readonly TWELVE_SPACE: string = '12vp';
? /**
? * Component space vp : 14.
? */
? static readonly ITEM_SPACE: string = '14vp';
? /**
? * Component space vp : 15.
? */
? static readonly FIFTEEN_SPACE: string = '15vp';
? /**
? * Font weight value: 700.
? */
? static readonly FONT_WEIGHT_SEVEN: number = 700;
? /**
? * Font weight value: 500.
? */
? static readonly FONT_WEIGHT_FIVE: number = 500;
? /**
? * Font weight value: 400.
? */
? static readonly FONT_WEIGHT_FOUR: number = 400;
? /**
? * Text line value: 2.
? */
? static readonly TWO_TEXT_LINE: number = 2;
? /**
? * Component opacity value: 1.
? */
? static readonly FULL_OPACITY: number = 1;
? /**
? * Component opacity value: 0.6.
? */
? static readonly SIXTY_OPACITY: number = 0.6;
? /**
? * Component opacity value: 0.8.
? */
? static readonly EIGHTY_OPACITY: number = 0.8;
? /**
? * Component layout value: 1.
? */
? static readonly LAYOUT_WEIGHT: number = 1;
? /**
? * Flex basic value: 1.
? */
? static readonly FLEX_BASIC: number = 1;
? /**
? * Flex shrink value: 1.
? */
? static readonly FLEX_SHRINK: number = 1;
? /**
? * Flex grow value: 1.
? */
? static readonly FLEX_GROW: number = 1;
? /**
? * Swiper or list display count value: 1.
? */
? static readonly DISPLAY_ONE: number = 1;
? /**
? * Swiper or list display count value: 2.
? */
? static readonly DISPLAY_TWO: number = 2;
? /**
? * Swiper or list display count value: 3.
? */
? static readonly DISPLAY_THREE: number = 3;
? /**
? * Swiper or list display count value: 4.
? */
? static readonly DISPLAY_FOUR: number = 4;
? /**
? * Image aspect ratio value: 2.23.
? */
? static readonly IMAGE_ASPECT_RATIO: number = 2.25;
? /**
? * Number of value: 0.5.
? */
? static readonly HALF_ONE: number = 0.5;
? /**
? * Number of value: -1.
? */
? static readonly MINUS_ONE: number = -1;
}
二、BreakpointSystem.ets:响应式设计的核心
import mediaQuery from '@ohos.mediaquery';
import { BreakpointConstants } from '../constants/BreakpointConstants';
declare interface BreakPointTypeOption<T> {
? sm?: T
? md?: T
? lg?: T
? xl?: T
? xxl?: T
}
/**
* 媒体查询(mediaquery)
* 响应式设计的核心
*/
export class BreakPointType<T> {
? options: BreakPointTypeOption<T>
? constructor(option: BreakPointTypeOption<T>) {
? ? this.options = option
? }
? getValue(currentBreakPoint: string): T {
? ? return this.options[currentBreakPoint] as T
? }
}
export class BreakpointSystem {
? private currentBreakpoint: string = '';
? private smListener?: mediaQuery.MediaQueryListener;
? private mdListener?: mediaQuery.MediaQueryListener;
? private lgListener?: mediaQuery.MediaQueryListener;
? private updateCurrentBreakpoint(breakpoint: string) {
? ? if (this.currentBreakpoint !== breakpoint) {
? ? ? this.currentBreakpoint = breakpoint;
? ? ? AppStorage.Set<string>(BreakpointConstants.CURRENT_BREAKPOINT, this.currentBreakpoint);
? ? }
? }
? private isBreakpointSM = (mediaQueryResult: mediaQuery.MediaQueryResult) => {
? ? if (mediaQueryResult.matches) {
? ? ? this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_SM);
? ? }
? }
? private isBreakpointMD = (mediaQueryResult: mediaQuery.MediaQueryResult) => {
? ? if (mediaQueryResult.matches) {
? ? ? this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_MD);
? ? }
? }
? private isBreakpointLG = (mediaQueryResult: mediaQuery.MediaQueryResult) => {
? ? if (mediaQueryResult.matches) {
? ? ? this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_LG);
? ? }
? }
? public register() {
? ? this.smListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_SM);
? ? this.smListener.on('change', this.isBreakpointSM);
? ? this.mdListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_MD);
? ? this.mdListener.on('change', this.isBreakpointMD);
? ? this.lgListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_LG);
? ? this.lgListener.on('change', this.isBreakpointLG);
? }
? public unregister() {
? ? this.smListener?.off('change', this.isBreakpointSM);
? ? this.mdListener?.off('change', this.isBreakpointMD);
? ? this.lgListener?.off('change', this.isBreakpointLG);
? }
}
BreakpointConstants.ets:
export class BreakpointConstants {
? /**
? * Breakpoints that represent small device types.
? */
? static readonly BREAKPOINT_SM: string = 'sm';
? /**
? * Breakpoints that represent middle device types.
? */
? static readonly BREAKPOINT_MD: string = 'md';
? /**
? * Breakpoints that represent large device types.
? */
? static readonly BREAKPOINT_LG: string = 'lg';
? /**
? * Current breakpoints that to query the device types.
? */
? static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';
? /**
? * Range of the small device width.
? */
? static readonly RANGE_SM: string = '(320vp<=width<520vp)';
? /**
? * Range of the middle device width.
? */
? static readonly RANGE_MD: string = '(520vp<=width<840vp)';
? /**
? * Range of the large device width.
? */
? static readonly RANGE_LG: string = '(840vp<=width)';
}
三、ButtonInfoModel.ets:底部导航按钮数据
export class ButtonInfoModel {
? index: number ;? // 序号
? img: Resource;? // 未选中图片
? selectImg: Resource ; // 选中图片
? title: Resource; // 按钮名称
}
const buttonInfo: ButtonInfoModel[] = [
? {
? ? index: 0,
? ? img: $r('app.media.ic_chat_off'),
? ? selectImg: $r('app.media.ic_chat_on'),
? ? title: $r('app.string.chat')
? },
? {
? ? index: 1,
? ? img: $r('app.media.ic_contact_off'),
? ? selectImg: $r('app.media.ic_contact_on'),
? ? title: $r('app.string.contact')
? },
? {
? ? index: 2,
? ? img: $r('app.media.ic_work_off'),
? ? selectImg: $r('app.media.ic_work_on'),
? ? title: $r('app.string.work')
? },
? {
? ? index: 3,
? ? img: $r('app.media.ic_mine_off'),
? ? selectImg: $r('app.media.ic_mine_on'),
? ? title: $r('app.string.mine')
? }
]
export { buttonInfo }