人人都会AI编程

窗口拖拽区域、自定义标题栏实现

更新时间:2026-07-11

在 Tauri 中实现自定义标题栏和窗口拖拽并不复杂,核心思路是:隐藏系统原生标题栏,用前端元素模拟标题栏,并通过 Tauri 提供的拖拽区域属性让用户能拖动窗口。


1. 隐藏原生标题栏

tauri.conf.json 中,为需要自定义标题栏的窗口关闭装饰(decorations):

{
  "app": {
    "windows": [
      {
        "title": "My App",
        "width": 800,
        "height": 600,
        "decorations": false
      }
    ]
  }
}

这样窗口就没有了系统自带的标题栏、最小化/最大化/关闭按钮。剩下的空白区域你可以用 HTML/CSS 全部接管。


2. 前端实现拖拽区域

Tauri 提供了一个特殊的 data-tauri-drag-region 属性,把它加到任意 HTML 元素上,该元素就会变成一个可拖拽的区域(类似于标题栏的作用)。在自定义标题栏的 div 上加上这个属性即可:

<div data-tauri-drag-region class="titlebar">
  <span>我的应用</span>
  <div class="window-controls">
    <button id="minimize">—</button>
    <button id="maximize">□</button>
    <button id="close">✕</button>
  </div>
</div>

配合 CSS,你可以把它固定在窗口顶部,并设置样式:

.titlebar {
  height: 36px;
  background: #2c2c2c;
  display: flex;
  align-items: center;
  padding: 0 12px;
  user-select: none;
}

这样整个 titlebar 区域都可以拖拽,但它的子元素(比如按钮)通常不响应拖拽,因为按钮默认会捕获鼠标事件。如果你希望标题栏上的文字或图标也能拖动,不需要额外处理;但按钮需要正常点击,所以 Tauri 会智能判断:在 data-tauri-drag-region 内,鼠标事件会传递给子元素,如果子元素是可交互的(按钮、输入框等),拖拽会被忽略,操作正常生效。


3. 实现窗口控制按钮

关闭、最小化、最大化按钮需要用 JavaScript 调用 Tauri 的窗口 API。首先确保已安装 @tauri-apps/api

npm install @tauri-apps/api

然后在对应的按钮事件中调用:

import { getCurrentWindow } from '@tauri-apps/api/window';

const currentWindow = getCurrentWindow();

document.getElementById('minimize').addEventListener('click', () => {
  currentWindow.minimize();
});

document.getElementById('maximize').addEventListener('click', async () => {
  const isMaximized = await currentWindow.isMaximized();
  if (isMaximized) {
    currentWindow.unmaximize();
  } else {
    currentWindow.maximize();
  }
});

document.getElementById('close').addEventListener('click', () => {
  currentWindow.close();
});

4. 注意事项

  • 双击最大化:如果你的自定义标题栏需要支持双击最大化,可以手动监听双击事件并调用 toggleMaximize() 或手动判断状态后切换。
  • 右键系统菜单:原生标题栏右键会弹出系统菜单(还原/移动/大小等)。如果想保留,可以在标题栏区域监听 contextmenu 事件,调用 Tauri 的 showWindowMenu(需要 Tauri 2.x 或自行实现菜单)。
  • 拖拽区域与其他交互冲突:如果拖拽区域内有一些需要拖拽的自定义元素(比如滑块),可能会产生冲突。此时可给那些元素添加 data-tauri-drag-region="false" 来排除。
  • 边框阴影和圆角:关闭原生装饰后,窗口可能失去系统自带的阴影。你可以用 CSS 的 box-shadowborder-radius 在窗口根元素上模拟,但注意 macOS 的窗口圆角还需要配合隐藏装饰时的透明边框调整。
  • 性能:由于所有拖拽逻辑由 Tauri 底层处理,前端无需手动计算坐标,所以响应迅速且无卡顿。

一句话总结

通过 decorations: false 隐藏原生标题栏,用 data-tauri-drag-region 实现拖拽,再调用窗口 API 完成控制按钮,就能轻松打造出美观且实用的自定义标题栏。整个过程无需修改 Rust 代码,全部在前端完成。