HarmonyOS Next技术完善:(一次开发,多端部署)的相关问题

内容阐述:

在我的前一个博客

解决:鸿蒙next媒体查询不能随折叠屏状态实时更新的问题(一次开发,多段部署)-优快云博客​​​​​​

 大致的解决了对于折叠屏状态更新后,设备尺寸不能实时更新,以及刚进入程序时,获取不到设备的尺寸信息的问题,在最近的学习中,对以上代码做了改进,下面是改进的点:

改进之处:

1.对媒体查询的方法进行了封装处理
2.对媒体查询到的数值等信息做了全局存储的处理
3.解决了,刚进入设备时,不会触发CallBack()方法来检测折叠屏的状态,以至于刚进入程序时,设备的尺寸信息是默认的数值

下面先放入整体的代码,在对四处的改进之处做出详细的解释:

代码展示:

项目列表:(绿色的是主要代码文件)

 代码:

BreakPointConstants.ets

    //媒体查询的断点常量
export class BreakPointConstants {
/** * Constants for breakpoint. */
  /**   * 这个单位页面上表示手机 xs就没有加入   */
  static readonly BREAKPOINT_SM: string = 'sm';
  /**   * 折叠屏可以用md来表示   */
  static readonly BREAKPOINT_MD: string = 'md';
  /**   * 一般pad端可以用lg的来表示   */
  static readonly BREAKPOINT_LG: string = 'lg';
  static readonly BREAKPOINT_XL: string = 'xl';
  /**   * The break point value.   */
  static readonly BREAKPOINT_VALUE: Array<string> = ['320vp', '600vp', '840vp', "1200vp"];
  /**   * The number of columns for SM device.   */
  //列数
  static readonly COLUMN_SM: number = 4;
  /**   * The number of columns for MD device.   */
  static readonly COLUMN_MD: number = 8;
  /**   * The number of columns for LG device.   */
  static readonly COLUMN_LG: number = 12;
  /**   * The number of gutter X for device.   */
  static readonly GUTTER_X: number = 12;
  /**   * The number of span for SM device.   */
  static readonly SPAN_SM: number = 4;
  /**   * The number of span for MD device.   */
  static readonly SPAN_MD: number = 6;
  /**   * The number of span for LG device.   */
  static readonly SPAN_LG: number = 8;
  /**   * The number of offset for MD device.   */
  static readonly OFFSET_MD: number = 1;
  /**   * The number of offset for LG device.   */
  static readonly OFFSET_LG: number = 2;
  /**   * Current breakpoints that to query the device types.   */
  //当前的单位
  static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';
  static readonly CURRENT_FLAG: string = "flag";
  /**   * Font size of the small device type.   */
  static readonly FONT_SIZE_SM: number = 14;
  /**   * Font size of the middle device type.   */
  static readonly FONT_SIZE_MD: number = 16;
  /**   * Font size of the large device type.   */
  static readonly FONT_SIZE_LG: number = 18;
  /**   * Cover margin of the small device type.   */
  static readonly COVER_MARGIN_SM: number = 10;
  /**   * Cover margin of the middle device type.   */
  static readonly COVER_MARGIN_MD: number = 30;
  /**   * Cover margin of the large device type.   */
  static readonly COVER_MARGIN_LG: number = 40;
  /**   * Range of the small device width.   */
  static readonly RANGE_SM: string = '(320vp<=width<600vp)';
  /**   * Range of the middle device width.   */
  static readonly RANGE_MD: string = '(600vp<=width<840vp)';
  /**   * Range of the large device width.   */
  static readonly RANGE_LG: string = '(840vp<=width<1200vp)';
  static readonly RANGE_XL: string = '(1200vp<=width)';
}

duoduanbushu.ets

import { BreakpointState, BreakpointSystem } from "./BreakPointSystem";
import { display } from "@kit.ArkUI";
import { BreakPointConstants } from "../constants/BreakPointConstants";

export class duoduanbushu{

  static  comvalue:string|undefined = "sm"
  static  comflag:number = 1

  static start(compStr: BreakpointState<string>, flag: number){
    console.log("执行了内部")
    BreakpointSystem.getInstance().attach(compStr)
    BreakpointSystem.getInstance().start()

    //起初进入页面是,通过getFoldStatus函数,来判断此时的设备状态,即刚进入设备的状态,但是该状态仅仅是对于折叠屏的状态,所以我们在屏幕的尺寸初始值我们就设置sm
    let currentFoldStatus = display.getFoldStatus();
    console.log(currentFoldStatus+"执行了奥执行了")
    if(currentFoldStatus){
      handleFoldStatusChange(currentFoldStatus, compStr, flag);
    }else {
      switch (compStr.value) {
        case "sm":
          flag = 1;
          AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, compStr.value)
          AppStorage.setOrCreate<number>(BreakPointConstants.CURRENT_FLAG, flag)
          console.log(AppStorage.get(BreakPointConstants.CURRENT_BREAKPOINT) + "存进去了")
          break;
        case "lg":
          flag = 1.5
          AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, compStr.value)
          AppStorage.setOrCreate<number>(BreakPointConstants.CURRENT_FLAG, flag)
          console.log(AppStorage.get(BreakPointConstants.CURRENT_BREAKPOINT) + "存进去了")
          break;
      }
    }
    //折叠屏的检测
    let callback: Callback<display.FoldStatus> = (data: display.FoldStatus) => {
      console.log('Listening enabled. Data: ' + JSON.stringify(data));
      handleFoldStatusChange(data, compStr, flag);
    };
    display.on('foldStatusChange', callback);
    //console.log(compStr.value)
    console.log("执行了下面")
  }
  static end(compStr: BreakpointState<string>){
    BreakpointSystem.getInstance().detach(compStr)
    BreakpointSystem.getInstance().stop()
  }

}
// 处理折叠状态变化的逻辑
function handleFoldStatusChange(data: display.FoldStatus, compStr: BreakpointState<string>, flag: number) {
  if (data == 1) {
    compStr.value = "md"
    flag = 1.2;
    AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, compStr.value)
    AppStorage.setOrCreate<number>(BreakPointConstants.CURRENT_FLAG, flag)
    console.log(AppStorage.get(BreakPointConstants.CURRENT_BREAKPOINT) + "存进去了")
  } else {
    compStr.value = "sm"
    flag = 1;
    AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, compStr.value)
    AppStorage.setOrCreate<number>(BreakPointConstants.CURRENT_FLAG, flag)
    console.log(AppStorage.get(BreakPointConstants.CURRENT_BREAKPOINT) + "存进去了")
  }
}


common/index.ets

export {BreakpointSystem,BreakpointState} from './src/main/ets/utils/BreakPointSystem'
export {BreakPointConstants} from './src/main/ets/constants/BreakPointConstants'
export {duoduanbushu} from './src/main/ets/utils/duoduanbushu'

default/index.ets

import { BreakpointState, BreakpointSystem, duoduanbushu } from 'common';
import { display } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State message: string = '这是首页';
  @State currenyIndex: number = 0
  private tabController = new TabsController() //控制页面的活动
  @State selectedIndex: number = 0;
  //多段部署
  @State compStr: BreakpointState<string> = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })
  @StorageProp("currentBreakpoint") comvalue:string= "sm"
  @StorageProp("flag") comflag:number = 1

  aboutToAppear(): void {
    setTimeout(() => {
      duoduanbushu.start(BreakpointState.of({ sm: "sm", md: "md", lg: "lg" }), 1)
    }, 100)
  }

  aboutToDisappear(): void {
    duoduanbushu.end(this.compStr)
  }

  //其实costumBar就是一个函数,这函数用builder来修饰,其实他就是一个布局函数
  @Builder
  tabBuilder(
    title: string,
    targetIndex: number,
    selectImg: Resource,
    normalImg: Resource) {
    Column({ space: 3 }) {
      Image(this.currenyIndex == targetIndex ? selectImg :
        normalImg)//如果默认的这个和你传进来的这个我们就是表示我们选中的就是这个,那么他的图片就是selectimg,如果不是就是选中另一个
        .size({
          width: 30,
          height: 30
        })
      Text(title)
        .fontColor(this.currenyIndex == targetIndex ? Color.Red : Color.Gray)
    }
    .width('100%')
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.currenyIndex = targetIndex
      this.tabController.changeIndex(targetIndex) //控制器的下标也更新,控制器的下标就是用来显示显示的内容
    })
  }

  build() {
    Column() {
      Tabs({
        barPosition: BarPosition.End,
        index: this.currenyIndex,
        controller: this.tabController
      }) {
        TabContent() {
          Column() {
            Text('首页的内容').fontSize(30 * this.comflag)
            Text(this.comvalue)
          }
        }
        .tabBar(this.tabBuilder("首页", 0, $r("app.media.home_select"), $r("app.media.home_default")))

        TabContent() {
          Text('推荐的内容').fontSize(30)
        }
        .tabBar(this.tabBuilder("推荐", 1, $r("app.media.home_select"), $r("app.media.home_default")))

        TabContent() {
          Text('发现的内容').fontSize(30)
        }
        .tabBar(this.tabBuilder("发现", 2, $r("app.media.home_select"), $r("app.media.home_default")))

        TabContent() {
          Text('我的内容').fontSize(30)
        }
        .tabBar(this.tabBuilder("我的", 3, $r("app.media.home_select"), $r("app.media.home_default")))
      }
      .onChange((index: number) => {
        this.currenyIndex = index //用于滑动的时候触发
      })
      .barBackgroundColor("#a1c7fd8a")
      .padding({
        bottom: 1,
      })
      .linearGradient({
        angle: 204, //默认显示颜色的时候,按照180度的角度渲染
        colors: [
          ["#FE9D9D", 0.0], //第一个颜色值,第二个代表颜色范围
          ["#E77D7D", 1.0]
        ]
      })
      .vertical(this.comvalue == "lg" ? true : false) //是否是侧边栏   start是左侧,end是右侧  主要是用在平板中
    }
    .height('100%')
    .width('100%')
    .backgroundColor($r("app.color.bk_gray"))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  }
}

 oh-package.json5

{
  "modelVersion": "5.0.1",
  "description": "Please describe the basic information.",
  "dependencies": {
  },
  "devDependencies": {
    "@ohos/hypium": "1.0.19",
    "@ohos/hamock": "1.0.0",
    "common": "file:./common",  //就只有这一句
    "homelibrary": "file:./features/homelibrary"
  }
}

以上就是主要的代码啦,下面我们来说一下这个的简单的步骤:

代码逻辑分析(针对改进之处)

1.对媒体查询的方法进行了封装处理

针对这一行代码

@State compStr: BreakpointState<string> = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })

1. BreakpointState<string> 类型

  • 作用:这是一个自定义类型(可能来自你的 BreakpointSystem 模块),用于管理不同断点(如 smmdlg)对应的状态值。

  • 泛型 <string>:表示 BreakpointState 内部存储的值的类型是字符串。


    2. BreakpointState.of({ sm: "sm", md: "md", lg: "lg" })

    • 作用:调用 BreakpointState 的静态方法 of,创建一个断点状态实例。

    • 参数解释

      { sm: "sm", md: "md", lg: "lg" }
      • 这是一个对象,定义了不同断点名称(如 smmdlg)对应的实际值。

      • 例如:

        • 当屏幕宽度满足 sm 断点时,compStr.value 会被自动设置为 "sm"

        • 当屏幕宽度满足 md 断点时,compStr.value 会被自动设置为 "md"

我们通过调用该方法,将对应的参数传入进去,在外部文件执行媒体查询,以后每个页面只需要类似的方法调用即可

duoduanbushu.start(BreakpointState.of({ sm: "sm", md: "md", lg: "lg" }), 1)

2.对媒体查询到的数值等信息做了全局存储的处理

在测试的过程中,取出外部方法中的数据是一个问题,在页面的运行中,duoduanbushu这个类只执行一次,但是内部的callback检测折叠屏的方法确实时时刻刻在监听,那么我们如果单纯的给start设置一个返回值,并不会时时刻刻返回对应的值,这时候我们将所得到的数据,使用AppStorage存入到全局存储当中去,每次调用callback方法时,全局存储中的数据都会更新,便达到了我们的预期效果

3.解决了,刚进入设备时,不会触发CallBack()方法来检测折叠屏的状态,以至于刚进入程序时,设备的尺寸信息是默认的数值

在测试中,发现callback仅仅是检测折叠屏手机的状态变化,在刚刚进入程序时,如果是折叠屏的状态,他并不会触发这个方法,而是先调用的

let currentFoldStatus = display.getFoldStatus();

这个方法来检测一下我们的设备状态,对于getFoldStatus()方法:

FoldStatus10+

当前可折叠设备的折叠状态枚举。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.Window.SessionManager

名称说明
FOLD_STATUS_UNKNOWN0表示设备当前折叠状态未知。
FOLD_STATUS_EXPANDED1表示设备当前折叠状态为完全展开。
FOLD_STATUS_FOLDED2表示设备当前折叠状态为折叠。
FOLD_STATUS_HALF_FOLDED3表示设备当前折叠状态为半折叠。半折叠指完全展开和折叠之间的状态。

 这时候如果是纯手机或者平板的状态,返回值是0,这里我们通过判断他的数值,如果是0我们就直接按照compstr.value(我定义的屏幕尺寸的变量)这个值,来判断我们的设备时什么状态,如果不是0就证明这个设备是一个折叠屏的设备,这时候,通过返回的值是多少,来判断手机的状态是折叠还是展开,然后将对应的数据存入到全局存储中去,这时候,我们的存储数据的代码就应该单独成一个函数,以便于我们在第一次进入程序时可以调用,在每一次更新手机状态时,也可以更新全局存储的数据

针对这一段话,有点晦涩难懂,我画了一个简单的流程图,可以帮助大家理解

以上就是针对这一次的改进做出的一下说明啦,该文章有任何问题或者需要改进的地方,欢迎大家评论指正呀!大家一起进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cx330_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值