UI适配不同分辨率
随着越来越多的设备采用高分辨率显示屏(如2K、4K等),在开发过程中遇到的UI适配问题也日益增多。通常,我们会将文本缩放调整为150%或更高,以提高显示效果。然而,这样在本地开发时调整好的UI,放到其他电脑上后,可能会出现显示异常,比如按钮过小、文字过小、图片不合适等,这通常是由分辨率和缩放比例不同引起的。
自适应设计的重要性
如果在页面开发初期即采用自适应设计,便可有效避免因不同分辨率和缩放倍率导致的UI显示问题。然而,如果页面已经开发完成且发现不适配各类分辨率,重新编写代码则会带来较大的工作量。因此,我们可以考虑通过计算调整,使UI在不同分辨率和缩放倍率下保持一致的显示效果。
实现不同分辨率适配的方案
在Electron中,可以通过以下步骤实现页面自适应:
获取屏幕分辨率与缩放比例:使用Electron的screen模块获取当前屏幕的分辨率宽度。假设我们选择一个基准分辨率值(例如1920px),将当前分辨率宽度除以基准值即可得到一个缩放比例。
设置缩放比例:将计算得到的缩放比例赋值给窗口的zoomFactor属性,这样可以确保内容在不同分辨率下的大小保持一致。
动态调整窗口大小:基于缩放比例调整窗口的宽度和高度,以确保UI布局的协调性。
通过这种方式,可以使得UI在不同设备上都能保持相对一致的体验效果,避免重写代码带来的额外工作量。
示例代码
写一个工具类,用来设置窗口的缩放比例和窗口大小,代码如下:
这个工具类是在主进程中使用的。
typescript
import { screen, BrowserWindow } from 'electron'
interface WindowSizeOption {
/**
* 是否居中
*/
center?: boolean
/**
* 窗口大小
*/
size?: {
width: number
height: number
isZoom: boolean
}
}
export default class WindowZoomUtil {
/**
* 基准宽度
*/
private baseWidth: number = 1920
/**
* 获取当前缩放比例
*/
static getZoom(): number {
const display = screen.getPrimaryDisplay()
const { width } = display.size
return width / baseWidth
}
/**
* 监听窗口事件,这些事件可能会重置`zoomFactor`的值,所以需要重新设置一遍
*/
listenerEventOnResetZoom(win: BrowserWindow): void {
win.on('focus', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('show', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('maximize', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('unmaximize', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('restore', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('enter-full-screen', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('leave-full-screen', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.on('kiosk', () => {
WindowZoomUtil.setWindowFactory(win)
})
win.webContents.on('did-finish-load', () => {
WindowZoomUtil.setWindowFactory(win)
})
}
/**
* 设置窗口缩放比例
* @param win 要设置的窗口
*/
static setWindowFactory(win: BrowserWindow): void {
const zoom = WindowZoomUtil.getZoom()
win?.webContents.setZoomFactor(zoom)
}
/**
* 设置窗口尺寸
* @param win 要设置的窗口
* @param options 属性
*/
static setWindowSize(win: BrowserWindow, options?: WindowSizeOption): void {
const zoom = WindowZoomUtil.getZoom()
// 设置窗口尺寸
if (options?.size) {
const [width, height] = win.getSize()
win.setSize(Math.round(width * zoom), Math.round(height * zoom))
} else {
const { width, height, isZoom } = options.size
const w = isZoom ? Math.round(width * zoom) : width
const h = isZoom ? Math.round(height * zoom) : height
win.setSize(w, h)
}
// 设置窗口位置
if (options?.center) {
win.center()
}
}
}
在窗口创建时,调用这个工具类,示例代码:
typescript
import { app, BrowserWindow, screen } from 'electron'
import WindowZoomUtil from './WindowZoomUtil'
function createWindow() {
const win = new BrowserWindow({
// ... 配置项省略
})
// 监听系统缩放倍率的变化
screen.on('display-metrics-changed', (_, display) => {
if (display.id === screen.getPrimaryDisplay().id) {
WindowZoomUtil.setWindowFactory(win)
WindowZoomUtil.setWindowSize(win, { center: true })
}
})
WindowZoomUtil.listenerEventOnResetZoom(win)
win.on('ready-to-show', () => {
win.show()
WindowZoomUtil.setWindowSize(win, { center: true })
})
}
app.whenReady().then(() => {
createWindow()
})