您的位置:首页 > 房产 > 家装 > 【 OpenHarmony 系统应用源码解析 】-- Launcher 桌面布局

【 OpenHarmony 系统应用源码解析 】-- Launcher 桌面布局

2024/10/5 20:23:46 来源:https://blog.csdn.net/pepsimaxin/article/details/141748611  浏览:    关键词:【 OpenHarmony 系统应用源码解析 】-- Launcher 桌面布局

一、计算桌面布局参数

📄 common/src/main/ets/default/viewmodel/LayoutViewModel.tscalculateDesktop(): any {Log.showInfo(TAG, 'calculateDesktop start');/*** 01. 计算桌面布局参数*//*** 获取桌面布局的边距值 mMargin,用于计算实际的可用宽度*/let margin = this.mLauncherLayoutStyleConfig.mMargin;/*** 根据屏幕宽度 mScreenWidth 和边距计算实际可用的宽度 realWidth,边距在两侧都有,所以要乘以 2*/let realWidth = this.mScreenWidth - 2 * margin;/*** 计算实际可用高度 realHeight* 工作区高度 mWorkSpaceHeight 减去指示器高度 mIndicatorHeight 和系统顶部高度 mSysUITopHeight*/let realHeight = this.mWorkSpaceHeight - this.mIndicatorHeight - this.mSysUITopHeight;/*** 检查导航栏状态 mNavigationBarStatus* 如果导航栏存在,则从 realHeight 中减去系统底部高度 mSysBottomHeight*/if (this.mNavigationBarStatus) {realHeight = realHeight - this.mLauncherLayoutStyleConfig.mSysBottomHeight;}...}

1.1 边距

let margin = this.mLauncherLayoutStyleConfig.mMargin;

这里的 this.mLauncherLayoutStyleConfig 是 LauncherLayoutStyleConfig 类,它有两个子类:

在这里插入图片描述

  1. 如果你的设备是 Phone 类型,那么就会从 PhoneLauncherLayoutStyleConfig 里面去取 mMargin 值:
📄 product/phone/src/main/ets/common/PhoneLauncherLayoutStyleConfig.tsmMargin = PhonePresetStyleConstants.DEFAULT_LAYOUT_MARGIN;

进而读取 PhonePresetStyleConstants 里面默认配置的 DEFAULT_LAYOUT_MARGIN 值:

📄 product/phone/src/main/ets/common/constants/PhonePresetStyleConstants.tsstatic readonly DEFAULT_LAYOUT_MARGIN = 12;
  1. 如果你的设备是 Pad 类型,那么就会从 PadLauncherLayoutStyleConfig 里面去取 mMargin 值:
📄 product/pad/src/main/ets/common/PadLauncherLayoutStyleConfig.tsmMargin = PadPresetStyleConstants.DEFAULT_LAYOUT_MARGIN;

进而读取 PadPresetStyleConstants 里面默认配置的 DEFAULT_LAYOUT_MARGIN 值:

📄 product/phone/src/main/ets/common/constants/PhonePresetStyleConstants.tsstatic readonly DEFAULT_LAYOUT_MARGIN = 82;

1.2 可用宽度

let realWidth = this.mScreenWidth - 2 * margin;

我们来看看 mScreenWidth(屏幕宽度)是从哪里来的:

📄 common/src/main/ets/default/viewmodel/LayoutViewModel.tsinitScreen(navigationBarStatus?: string): void {this.mScreenWidth = AppStorage.get('screenWidth');this.mScreenHeight = AppStorage.get('screenHeight');...
}

通过 AppStorage.get() 获取的,那肯定有地方 AppStorage.setOrCreate() 了。

  1. 如果设备是 Phone 类型
📄 product/phone/src/main/ets/pages/EntryView.etsaboutToAppear(): void {Log.showInfo(TAG, 'aboutToAppear');...this.getWindowSize();...
}private getWindowSize(): void {try {this.screenWidth = px2vp(windowManager.getWindowWidth());this.screenHeight = px2vp(windowManager.getWindowHeight());AppStorage.setOrCreate('screenWidth', this.screenWidth);AppStorage.setOrCreate('screenHeight', this.screenHeight);} catch (error) {Log.showError(TAG, `getWindowWidth or getWindowHeight error: ${error}`);}
}
  1. 如果设备是 Pad 类型
📄 product/pad/src/main/ets/pages/EntryView.etsaboutToAppear(): void {Log.showInfo(TAG, 'aboutToAppear');...this.getWindowSize();...
}private getWindowSize(): void {try {this.screenWidth = px2vp(windowManager.getWindowWidth());this.screenHeight = px2vp(windowManager.getWindowHeight());AppStorage.setOrCreate('screenWidth', this.screenWidth);AppStorage.setOrCreate('screenHeight', this.screenHeight);} catch (error) {Log.showError(TAG, `getWindowWidth or getWindowHeight error: ${error}`);}
}

可以发现,逻辑一摸一样。

我们带着看下 windowManager.getWindowWidth() 里面的逻辑:

📄 common/src/main/ets/default/manager/WindowManager.tsgetWindowWidth(): number {if (this.mDisplayData == null) {this.mDisplayData = this.getWindowDisplayData();}// 获取显示设备的屏幕宽度return this.mDisplayData?.width as number;
}private getWindowDisplayData(): display.Display | null {let displayData: display.Display | null = null;try {// @ohos.display ==> 获取当前默认的 display 对象displayData = display.getDefaultDisplaySync();} catch(err) {Log.showError(TAG, `display.getDefaultDisplaySync error: ${JSON.stringify(err)}`);}return displayData;
}

我现在手上的设备是 Pad,打个 Log 看看:

com.ohos.launcher     I     @@@ pepsimaxin : 屏幕宽度 ==> this.mScreenWidth = 1280

二、计算列数、行数及间距

接下来我们继续分析第 2 部分代码:

📄 common/src/main/ets/default/viewmodel/LayoutViewModel.tscalculateDesktop(): any {Log.showInfo(TAG, 'calculateDesktop start');/*** 01. 计算桌面布局参数*/---------------------------------------------------/*** 02. 计算列数、行数及间距*//*** 获取每个应用图标的尺寸 mAppItemSize*/let itemSize = this.mLauncherLayoutStyleConfig.mAppItemSize;/*** 获取最小网格间距 mGridGutter*/let minGutter = this.mLauncherLayoutStyleConfig.mGridGutter;/*** 计算可以容纳多少列图标:~~ 是双重按位取反操作符,用于快速向下取整*/let column = ~~((realWidth + minGutter) / (itemSize + minGutter));/*** 计算列之间剩余的宽度 userWidth*/let userWidth = (realWidth + minGutter - (itemSize + minGutter) * column);/*** 重新计算列间距 gutter*/let gutter = (userWidth / (column - 1)) + minGutter;/*** 类似列的计算,计算可以容纳多少行图标*/let row = ~~((realHeight + gutter) / (itemSize + gutter));/*** 计算顶部边距 marginTop,用于使图标在垂直方向上居中*/let marginTop = ((realHeight + gutter - (itemSize + gutter) * row) / 2);...}

2.1 应用图标大小

let itemSize = this.mLauncherLayoutStyleConfig.mAppItemSize;

又碰到 LauncherLayoutStyleConfig 了,那么图标尺寸肯定不同设备配置不一样了:

// Phone
mAppItemSize = PhonePresetStyleConstants.DEFAULT_APP_LAYOUT_SIZE;
static readonly DEFAULT_APP_LAYOUT_SIZE = 80;// Pad
mAppItemSize = PadPresetStyleConstants.DEFAULT_APP_LAYOUT_SIZE;
static readonly DEFAULT_APP_LAYOUT_SIZE = 96;  

2.2 最小网格间距

let minGutter = this.mLauncherLayoutStyleConfig.mGridGutter;

同理,我们直接看配置信息:

// Phone
mGridGutter = PhonePresetStyleConstants.DEFAULT_APP_LAYOUT_MIN_GUTTER;
static readonly DEFAULT_APP_LAYOUT_MIN_GUTTER = 5;// Pad
mGridGutter = PadPresetStyleConstants.DEFAULT_APP_LAYOUT_MIN_GUTTER;
static readonly DEFAULT_APP_LAYOUT_MIN_GUTTER = 6;

2.3 图标列数

// 计算容纳多少列图标
let column = ~~((realWidth + minGutter) / (itemSize + minGutter));

例如我手里的平板,我们打个 Log 看下数据:

pid-1360              I     @@@ pepsimaxin : 桌面布局边距 ==> margin = 82
pid-1360              I     @@@ pepsimaxin : 屏幕宽度 ==> this.mScreenWidth = 1280
com.ohos.launcher     D     @@@ pepsimaxin : realWidth = 1116, minGutter = 6, itemSize = 96
com.ohos.launcher     D     @@@ pepsimaxin : column = 11

看下平板效果:

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com