初步解决自适应问题

This commit is contained in:
JackLee 2026-03-17 22:26:44 +08:00
parent 6e73610503
commit 68e72767dd
9 changed files with 309 additions and 27 deletions

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2025 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.
*/
// [Start Common_ContextUtils]
export class ContextUtils {
public static context: Context | undefined;
static setContext(context: Context): void {
ContextUtils.context = context;
}
static getContext(uiContext?: UIContext): Context | undefined {
if (uiContext) {
return uiContext.getHostContext();
}
return ContextUtils.context;
}
}
// [End Common_ContextUtils]

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 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.
*/
// [Start Common_PixelUtils]
import { hilog } from '@kit.PerformanceAnalysisKit';
import { display } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export class PixelUtils {
public static uiContext: UIContext | undefined;
static setUIContext(uiContext: UIContext): void {
PixelUtils.uiContext = uiContext;
}
static vp2px(vpValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtils.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
let displayClass = display.getDefaultDisplaySync();
let density = displayClass.densityPixels;
return vpValue * density;
}
return _uiContext.vp2px(vpValue)
}
static fp2px(fpValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtils.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return undefined;
}
return _uiContext.fp2px(fpValue)
}
lpx2px(lpxValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtils.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return undefined;
}
return _uiContext.lpx2px(lpxValue)
}
}
// [End Common_PixelUtils]

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 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.
*/
// [Start Common_Utils]
// common/Utils.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0000;
export class PixelUtil {
static uiContext: UIContext | undefined;
static setUIContext(uiContext: UIContext): void {
PixelUtil.uiContext = uiContext;
}
static removeUIContext(): void {
PixelUtil.uiContext = undefined;
}
static vp2px(vpValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtil.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return undefined;
}
return _uiContext.vp2px(vpValue)
}
static fp2px(fpValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtil.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return undefined;
}
return _uiContext.fp2px(fpValue)
}
lpx2px(lpxValue: number, uiContext?: UIContext): number | undefined {
let _uiContext = uiContext ?? PixelUtil.uiContext;
if (!_uiContext || !_uiContext.isAvailable()) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return undefined;
}
return _uiContext.lpx2px(lpxValue)
}
}
// [End Common_Utils]

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2025 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.
*/
// [Start Common_WindowUtils]
// common/WindowUtils.ets
import { display, window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0000;
export class WindowUIContextUtils {
public static activeUIContext: UIContext | undefined;
static registerWindowCallback(windowClass: window.Window): void {
try {
windowClass.on('windowEvent', (event: window.WindowEventType) => {
if (event === window.WindowEventType.WINDOW_ACTIVE) {
try {
let uiContext = windowClass.getUIContext();
WindowUIContextUtils.activeUIContext = uiContext;
} catch (exception) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext, ${exception}`);
}
}
});
} catch (exception) {
console.error(`Failed to unregister callback. Cause: ${exception}`);
}
}
static unregisterWindowCallback(windowClass: window.Window): void {
windowClass.off('windowEvent');
}
static setActiveUIContext(uiContext: UIContext): void {
WindowUIContextUtils.activeUIContext = uiContext;
}
static vp2px(vpValue: number, uiContext?: UIContext): number {
let _uiContext = uiContext ?? WindowUIContextUtils.activeUIContext;
if (!_uiContext || !_uiContext.isAvailable()) {
let displayClass = display.getDefaultDisplaySync();
let density = displayClass.densityPixels;
return vpValue * density;
}
return _uiContext.vp2px(vpValue);
}
}
// [End Common_WindowUtils]

View File

@ -1,7 +1,8 @@
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { AppStorageV2 } from '@kit.ArkUI';
import { window,display,AppStorageV2} from '@kit.ArkUI';
import { WindowUIContextUtils } from '../common/WindowUtils';
import { PixelUtils } from '../common/UIContext';
const DOMAIN = 0x0000;
@ -22,13 +23,45 @@ export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
let window = windowStage.getMainWindowSync();
// 注册主窗的回调。
WindowUIContextUtils.registerWindowCallback(window);
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
hilog.error(DOMAIN, 'Tag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
AppStorage.setOrCreate('windowStage', windowStage);
let uiContext = window.getUIContext();
PixelUtils.setUIContext(uiContext);
// 主窗获焦可能早于loadContent完成需要在成功后设置保证有效。
WindowUIContextUtils.setActiveUIContext(uiContext)
if (!uiContext) {
hilog.error(DOMAIN, 'testTag', `Can't get UIContext`);
return;
}
let screenWidth:number=display.getDefaultDisplaySync().width;
let screenHeight:number=display.getDefaultDisplaySync().height;
//定义新的宽度和高度(单位:虚拟像素)
const newWidth: number = screenWidth-uiContext.px2vp(200);
const newHeight: number = screenHeight-uiContext.px2vp(400);
//基于物理分辨率在长和高上分别缩小200vp
windowStage.getMainWindow((err, mainWindow) => {
if (err.code) {
console.error(`Failed to obtain the main window. Code: ${err.code}, message: ${err.message}`);
return;
}
mainWindow.moveWindowTo(uiContext.px2vp(100),uiContext.px2vp(100))
//调用resize方法修改窗口大小
mainWindow.resize(newWidth, newHeight, (err) => {
if (err.code) {
console.error(`Failed to resize the window. Code: ${err.code}, message: ${err.message}`);
return;
}
console.info(`Succeeded in resizing the window to ${newWidth}x${newHeight}.`);
});
});
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}

View File

@ -0,0 +1,27 @@
//一个复合式折叠组件
@ComponentV2
export struct Expandable {
// 通过属性传入的标题和内容
@Param title: string|undefined=undefined;
// 控制内容区域显示与隐藏的状态
@Consumer('isSubExpanded') isSubExpanded: boolean=true;
build(){
// 标题行
Row({ space: 5 }) {
// 切换按钮,显示向上或向下箭头
Button(this.isSubExpanded ? '▲' : '▼')
.type(ButtonType.Normal)
.fontSize(14)
.onClick(() => {
// 点击按钮时,切换 isSubExpanded 状态
this.isSubExpanded = !this.isSubExpanded;
})
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.alignSelf(ItemAlign.Center)
}.width('100%')
}
}

View File

@ -6,7 +6,7 @@ export function ExecuteCommand(event:TitleButton){
if(event?.eEvent=='Execute_LoadModel'){
OCCTLoadModel(undefined,undefined)
}else if(event?.eEvent=='Execute_CreateSubWindow'){
CreateAndShowSubWindow(event.ePage);
CreateAndShowSubWindow(event.eName,event.ePage);
}else if(event?.eEvent=='Execute_ExitSubWindow'){
CloseSubWindow();
}

View File

@ -1,9 +1,9 @@
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
import { window,UIContext} from '@kit.ArkUI';
let subWindow: window.Window | undefined = undefined;
export async function CreateAndShowSubWindow(pages:string) {
export async function CreateAndShowSubWindow(name:string,pages:string) {
try {
const windowStage = AppStorage.get('windowStage') as window.WindowStage;
if(windowStage==null){
@ -11,35 +11,36 @@ export async function CreateAndShowSubWindow(pages:string) {
return;
}
let options: window.SubWindowOptions = {
title: '子窗口',
title: name,
decorEnabled: true,
isModal: false,
maximizeSupported: false,
zLevel:-1,
outlineEnabled:true,
};
await windowStage.createSubWindowWithOptions('subWindow', options).then((data) => {
subWindow = data;
subWindow.setResizeByDragEnabled(true, (err: BusinessError) => {
console.log("设置拖拽缩放", `报错信息:${err.code}, ${err.message}`)
})
//子窗口创建成功后,设置子窗口的位置、大小及相关属性等。
subWindow.moveWindowTo(150, 300)
subWindow.moveWindowTo(150, 15)
//子窗口重置大小
subWindow.resize(500, 900);
subWindow.resize(800, 1200);
subWindow.setUIContent(pages, (err: BusinessError) => {
if (err.code) {
console.error("加载页面失败:", err);
return;
}
})
// 显示窗口
subWindow?.showWindow((err) => {
subWindow.showWindow((err) => {
if (err.code) {
console.error("显示窗口失败:", err);
}
});
})
})
} catch (error) {
console.error('Failed to create or show sub window:', (error as BusinessError).message);
}

View File

@ -1,18 +1,29 @@
import { Expandable } from '../CustomStyle/Expandable';
@Entry
@ComponentV2
struct SWExtrude {
// 控制内容区域显示与隐藏的状态
@Provider('isSubExpanded') isExpanded:boolean=true;
build() {
Column({ space: 5 }) {
Column(){
Row({ space: 20 }) {
Blank().width(8);
Expandable({title:"拉伸"});
Row(){
// 内容区域,使用条件渲染来控制显示与隐藏
if (this.isExpanded) {
Text('*选择曲线(0)').width(px2vp(35)).height(px2vp(35))
Blank().width('30%')
Button('绘制曲线').width(px2vp(35)).height(px2vp(35))
Button('选择曲线').width(px2vp(35)).height(px2vp(35))
}
.justifyContent(FlexAlign.SpaceBetween)
.height(56)
.width('100%')
.padding({ left: 10 })
.backgroundColor('#f2f2f2');
}.width('100%').height('100%');
}.justifyContent(FlexAlign.Start)
}
}.width('100%') // 容器宽度
.padding(15) // 内边距
.backgroundColor('#ffffff') // 背景色
.borderRadius(8) // 边框圆角
.shadow({ radius: 4, color: '#1f000000', offsetX: 2, offsetY: 2 }) // 添加阴影
.margin({ top: 5, left: 5, bottom: 5, right: 5 })
}
}