华为鸿蒙应用--底部导航栏Tabs(自适应手机和平板)

2023-12-13 10:33:47

鸿蒙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 }

文章来源:https://blog.csdn.net/qq_41374940/article/details/134897583
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。