Media queries enable dynamic UI adjustments based on device attributes like screen dimensions, resolution, orientation, and color depth. They form the foundation of responsive application design, ensuring consistent and optimal user experiences across diverse hardware. Typical use cases include adaptive layouts, typography scaling, conditional element visibility, and dark mode support.
Implementation Workflow
To utilize media queries, first import the required module:
import query from '@ohos.mediaquery';
Define a media condition and obtain a listener handle using matchMediaSync. For instance, to detect landscape orientation:
let orientationHandle = query.matchMediaSync('(orientation: landscape)');
Attach a callback to the handle to respond to state changes:
handleOrientationChange(result: mediaquery.MediaQueryResult) {
if (result.matches) {
// Apply landscape styles
} else {
// Apply portrait styles
}
}
orientationHandle.on('change', handleOrientationChange);
Condition Syntax
Media query strings follow the pattern: [media-type] [media-logic-operations] [(media-feature)].
Example: screen and (device-type: tv) or (resolution < 2) evaluates to true if the device is a TV or its resolution is less than 2.
Media Types
| Type | Description |
|---|---|
| screen | Matches screen-based devices. |
Logical Operators
| Keyword | Description |
|---|---|
| and | Combines multiple conditions; all must match. |
| or | Combines multiple conditions; at least one must match. |
| not | Negates a specific condition. |
| only | Applies the rule exclusively to the specified device type. |
| , (comma) | Groups seperate queries to apply identical rules. |
Range Operators
| Operator | Meaning | Example |
|---|---|---|
| < | Less than | screen and (max-width: 768) |
| > | Greater than | screen and (min-width: 768) |
| <= | Less than or equal to | screen and (max-height: 1024) |
| >= | Greater than or equal to | screen and (min-height: 1024) |
Media Features
| Feature | Description |
|---|---|
| height | Viewport drawable area height. |
| min-height | Minimum viewport height. |
| max-height | Maximum viewport height. |
| width | Viewport drawable area width. |
| min-width | Minimum viewport width. |
| max-width | Maximum viewport width. |
| resolution | Device resolution (dpi, dppx, dpcm). |
| min-resolution | Minimum device resolution. |
| max-resolution | Maximum device resolution. |
| orientation | Screen orientation (portrait or landscape). |
| device-height | Physical device height. |
| min-device-height | Minimum physical device height. |
| max-device-height | Maximum physical device height. |
| device-width | Physical device width. |
| min-device-width | Minimum physical device width. |
| max-device-width | Maximum physical device width. |
| device-type | Device category (default, tablet). |
| round-screen | Boolean indicating a circular screen. |
| dark-mode | Boolean indicating system dark mode. |
Practical Example
Implementing a component that changes its background color and label based on screen orientation:
import query from '@ohos.mediaquery';
import window from '@ohos.window';
import { common } from '@ohos.app.ability.common';
let orientationCallback = null;
@Entry
@Component
struct OrientationAdaptation {
@State bgColor: string = '#4169E1';
@State modeLabel: string = 'Portrait Mode';
landscapeListener = query.matchMediaSync('(orientation: landscape)');
onOrientationShift(matchResult: mediaquery.MediaQueryResult) {
if (matchResult.matches) {
this.bgColor = '#32CD32';
this.modeLabel = 'Landscape Mode';
} else {
this.bgColor = '#4169E1';
this.modeLabel = 'Portrait Mode';
}
}
aboutToAppear() {
orientationCallback = this.onOrientationShift.bind(this);
this.landscapeListener.on('change', orientationCallback);
}
forceOrientation(isLandscape: boolean) {
let uiContext = getContext(this) as common.UIAbilityContext;
window.getLastWindow(uiContext).then((targetWindow) => {
targetWindow.setPreferredOrientation(isLandscape ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT);
});
}
build() {
Column({ space: 30 }) {
Text(this.modeLabel)
.fontSize(24)
.fontColor(Color.White)
Button('Switch to Landscape')
.onClick(() => this.forceOrientation(true))
Button('Switch to Portrait')
.onClick(() => this.forceOrientation(false))
}
.width('100%')
.height('100%')
.backgroundColor(this.bgColor)
.justifyContent(FlexAlign.Center)
}
}