在视频播放、股票K线分析、AR模型预览等应用中,详情页通常采用竖屏布局以适配常规操作。为提供更沉浸、更专业的交互体验,目前提供了以下三种场景:
横屏模式下,内容展示区域更大、细节更清晰,尤其适合视频全屏播放、K线图表横向展开以及AR模型的全景预览,从而显著提升视觉体验与操作效率。
场景一:从列表进入视频播放页面,提供一个按钮通过setPreferredOrientation(window.Orientation.LANDSCAPE)设置横屏来控制屏幕的显示方向为横屏,点击后进入横屏,退出页面后通过setPreferredOrientation(window.Orientation.PORTRAIT)恢复到竖屏。
@Entry
@Component
struct MainPage {
// 单页面设置横屏(页面之间设置横竖屏切换)
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
build() {
Column() {
List({ space: 20, initialIndex: 0 }) {
ForEach(this.arr, (item: number) => {
ListItem() {
Text('' + item)
.width('100%')
.height(100)
.fontSize(16)
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(0xFFFFFF);
}
.onClick(() => {
this.getUIContext().getRouter().pushUrl({ url: 'pages/OrientationTest' });
});
}, (item: number) => item.toString());
}
.listDirection(Axis.Vertical) // 排列方向
.scrollBar(BarState.Off)
.friction(0.6)
.divider({
strokeWidth: 2,
color: 0xFFFFFF,
startMargin: 20,
endMargin: 20
}) // 每行之间的分界线
.edgeEffect(EdgeEffect.Spring); // 边缘效果设置为Spring
}
.justifyContent(FlexAlign.Center)
.width('100%')
.backgroundColor('#f1f3f5')
.height('100%');
}
} import { window } from '@kit.ArkUI';
@Entry
@Component
struct OrientationTest {
aboutToDisappear(): void {
window.getLastWindow(this.getUIContext().getHostContext()).then((win) => {
// 退出页面后重置方向,设置为竖屏
win.setPreferredOrientation(window.Orientation.PORTRAIT);
});
}
build() {
Column() {
Button('退出播放页面')
.backgroundColor('#0a59f7')
.onClick(() => {
this.getUIContext().getRouter().back();
})
.margin({ top: 50 });
// 点击按钮后通过setPreferredOrientation设置页面横屏
Button('横屏播放')
.backgroundColor('#0a59f7')
.margin({ top: 50 })
.onClick(() => {
window.getLastWindow(this.getUIContext().getHostContext()).then((win: window.Window) => {
win.setPreferredOrientation(window.Orientation.LANDSCAPE);
});
});
}
.width('100%')
.height('100%');
}
} 效果如下:
播放页面竖屏 | 播放页面横屏 |
|---|---|
|
|
// 沉浸式模式下实现页面内横竖屏切换
aboutToAppear(): void {
// 开启沉浸式
window.getLastWindow(this.getUIContext().getHostContext()).then(win => {
win.setWindowLayoutFullScreen(true);
});
} onFullChange() {
window.getLastWindow(this.getUIContext().getHostContext()).then(win => {
this.isLandscape = !this.isLandscape;
win.setPreferredOrientation(this.isLandscape ? window.Orientation.LANDSCAPE :
window.Orientation.PORTRAIT);
}); 完整代码如下:
import { window } from '@kit.ArkUI';
@Entry
@Component
export struct Page {
@State isLandscape: boolean = false;
// 沉浸式模式下实现页面内横竖屏切换
aboutToAppear(): void {
// 开启沉浸式
window.getLastWindow(this.getUIContext().getHostContext()).then(win => {
win.setWindowLayoutFullScreen(true);
});
}
build() {
Stack() {
Stack() {
// 实际使用时替换为真实的图片
Image($r('app.media.img'))
.width('100%')
.aspectRatio(16 / 9)
.constraintSize({
maxWidth: '100%',
maxHeight: '100%'
});
if (this.isLandscape) {
Row({ space: 10 }) {
Blank()
Image($r('app.media.arrow_down_right_and_arrow_up_left'))
.width(24)
.height(24)
.onClick(() => {
this.onFullChange();
});
}
.width('100%')
.alignItems(VerticalAlign.Center)
.padding({
left: 44, right: 44, bottom: 20
});
} else {
Text('全屏切换')
.borderWidth(1)
.borderRadius('50%')
.borderColor(Color.White)
.fontColor(Color.White)
.fontSize(14)
.padding({
left: 10,
right: 10,
top: 5,
bottom: 5
})
.onClick(() => {
this.onFullChange();
})
.offset({
y: 50
});
}
}
.alignContent(Alignment.Bottom);
}
.backgroundColor('#000')
.width('100%')
.height('100%');
}
onFullChange() {
window.getLastWindow(this.getUIContext().getHostContext()).then(win => {
this.isLandscape = !this.isLandscape;
win.setPreferredOrientation(this.isLandscape ? window.Orientation.LANDSCAPE :
window.Orientation.PORTRAIT);
});
}
} 效果如下:
播放页面竖屏 | 播放页面横屏 |
|---|---|
|
|
场景三:设置指定页面在手机上只允许竖屏显示,在PAD上只允许横屏显示。
import { UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
AppStorage.setOrCreate('windowStage', windowStage);
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
}; import { window } from '@kit.ArkUI';
import { deviceInfo } from '@kit.BasicServicesKit';
@Entry
@Component
struct PadAndPhonePage {
@State message: string = 'Hello World';
// 在手机上竖屏显示,在pad上横屏显示
aboutToAppear(): void {
window.getLastWindow(this.getUIContext().getHostContext()).then(win => {
win.setWindowLayoutFullScreen(true);
});
let windowStage = AppStorage.get('windowStage') as window.WindowStage;
let windowClass: window.Window | undefined = undefined;
windowStage.getMainWindow((err: BusinessError, data) => {
const errCode: number = err.code;
if (errCode) {
console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
return;
}
windowClass = data;
// 获取设备类型
let deviceTypeInfo: string = deviceInfo.deviceType;
console.info(`the value of the deviceType is:${deviceTypeInfo}`);
let orientation = window.Orientation.AUTO_ROTATION;
// 判断设备是手机or平板,来设置窗口显示方向
if (deviceTypeInfo == 'phone') {
orientation = window.Orientation.PORTRAIT;
this.message = '当前的设备是:phone';
} else if (deviceTypeInfo == 'tablet') {
orientation = window.Orientation.LANDSCAPE;
this.message = '当前的设备是:tablet';
}
try {
windowClass.setPreferredOrientation(orientation, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error(`Failed to set window orientation. Cause code: ${err.code}, message: ${err.message}`);
return;
}
console.info('Succeeded in setting window orientation.');
});
} catch (exception) {
console.error(`Failed to set window orientation. Cause code: ${exception.code}, message: ${exception.message}`);
}
});
}
build() {
RelativeContainer() {
Text(this.message)
.fontSize(25)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
});
}
// 实际使用时替换为真实的图片
.backgroundImage($r('app.media.img'))
.height('100%')
.width('100%');
}
} 效果如下:
手机上竖屏 | 平板上横屏 |
|---|---|
|
|
Q:横竖屏切换的时候,底部安全区域怎么适配。
A:可以设置expandSafeArea属性,动态改变edges的值,在横屏时配置为[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM],设置当前页面横屏状态。
Q:应用在前台设置LANDSCAPE后,再将window锁定状态为LOCKED。应用进入后台后,再返回前台,设置的LOCKED状态被取消且变成竖屏。
A:LOCKED旋转策略,会跟随当前屏幕朝向启动。应用退出到后台后,桌面会旋转到竖屏,再次打开应用,应用也会跟随桌面旋转到竖屏,这是规格。维持原来的旋转策略(LANDSCAPE)就可以,不需要更改成LOCKED。
Q:横竖屏旋转适配Orientation设置UNSPECIFIED和AUTO_ROTATION有什么区别。
A:1.UNSPECIFIED由系统判定,在桌面时是否可旋转,所以手机上不会发生旋转,PAD会旋转。2.AUTO_ROTATION是跟随传感器自动旋转,手机和PAD上都会旋转。
Q:在平板上调用getPreferredOrientation获取窗口显示方向返回0,如何获取当前屏幕实际的横竖屏状态?
A:返回值0对应window.Orientation.UNSPECIFIED,表示未定义方向模式,由系统判定。若需获取当前屏幕实际的横竖屏状态,可通过display.getDefaultDisplaySync().orientation属性来判断屏幕当前所处的横竖屏状态。