Flutter窗口管理插件yaru_window的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter窗口管理插件yaru_window的使用

yaru_window 是一个用于与顶层Flutter窗口进行交互的插件。它提供了丰富的API来管理窗口的状态和行为,如最大化、最小化、关闭确认等。

插件信息

示例代码

以下是一个完整的示例Demo,展示了如何使用 yaru_window 来管理窗口的各种状态和行为。

main.dart

import 'package:flutter/material.dart';
import 'package:yaru/yaru.dart';
import 'package:yaru_window/yaru_window.dart';

Future<void> main() async {
  await YaruWindow.ensureInitialized();

  runApp(
    YaruTheme(
      builder: (context, yaru, child) {
        return MaterialApp(
          theme: yaru.theme,
          darkTheme: yaru.darkTheme,
          debugShowCheckedModeBanner: false,
          home: const HomePage(),
        );
      },
    ),
  );
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    YaruWindow.of(context).onClose(() => showConfirmationDialog(context));
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.transparent,
      body: Row(
        children: [
          Expanded(child: ColorSelector()),
          Expanded(child: StateView()),
        ],
      ),
    );
  }
}

Future<bool> showConfirmationDialog(BuildContext context) async {
  if (!context.mounted) return true;
  if (ModalRoute.of(context)?.isCurrent == false) return false;
  return showDialog(
    context: context,
    builder: (context) {
      return AlertDialog(
        title: const Text('Close window?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, true),
            child: const Text('Yes'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text('No'),
          ),
        ],
      );
    },
  ).then((value) => value == true);
}

class StateView extends StatelessWidget {
  const StateView({super.key});

  @override
  Widget build(BuildContext context) {
    final window = YaruWindow.of(context);
    return StreamBuilder<YaruWindowState>(
      stream: window.states(),
      builder: (context, snapshot) {
        final state = snapshot.data;
        debugPrint(state?.toString());
        return ListView(
          padding: const EdgeInsets.all(20),
          children: [
            ListTile(
              title: const Text('Active'),
              subtitle: Text('${state?.isActive}'),
            ),
            ListTile(
              title: const Text('Brightness'),
              trailing: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ElevatedButton(
                    onPressed: () => window.setBrightness(Brightness.light),
                    child: const Text('Light'),
                  ),
                  const SizedBox(width: 10),
                  ElevatedButton(
                    onPressed: () => window.setBrightness(Brightness.dark),
                    child: const Text('Dark'),
                  ),
                ],
              ),
            ),
            ListTile(
              title: const Text('Closable'),
              subtitle: Text('${state?.isClosable}'),
              trailing: ElevatedButton(
                onPressed: (state?.isClosable ?? false) ? window.close : null,
                child: const Text('Close'),
              ),
            ),
            ListTile(
              title: const Text('Fullscreen'),
              subtitle: Text('${state?.isFullscreen}'),
              trailing: ElevatedButton(
                onPressed: state?.isFullscreen != true ? window.fullscreen : null,
                child: const Text('Fullscreen'),
              ),
            ),
            ListTile(
              title: Text(
                'Maximizable ${(state?.isMaximized ?? false) ? '(maximized)' : ''}',
              ),
              subtitle: Text('${state?.isMaximizable}'),
              trailing: ElevatedButton(
                onPressed: (state?.isMaximizable ?? false) ? window.maximize : null,
                child: const Text('Maximize'),
              ),
            ),
            ListTile(
              title: Text(
                'Minimizable ${(state?.isMinimized ?? false) ? '(minimized)' : ''}',
              ),
              subtitle: Text('${state?.isMinimizable}'),
              trailing: ElevatedButton(
                onPressed: (state?.isMinimizable ?? false) ? window.minimize : null,
                child: const Text('Minimize'),
              ),
            ),
            ListTile(
              title: const Text('Movable'),
              subtitle: Text('${state?.isMovable}'),
              trailing: GestureDetector(
                onPanStart: (_) => window.drag(),
                child: ElevatedButton(
                  onPressed: () {},
                  child: const Text('Drag'),
                ),
              ),
            ),
            ListTile(
              title: const Text('Restorable'),
              subtitle: Text('${state?.isRestorable}'),
              trailing: ElevatedButton(
                onPressed: (state?.isRestorable ?? false) ? window.restore : null,
                child: const Text('Restore'),
              ),
            ),
            ListTile(
              title: const Text('Menu'),
              trailing: ElevatedButton(
                onPressed: window.showMenu,
                child: const Text('Show'),
              ),
            ),
            ListTile(
              title: const Text('Title'),
              subtitle: Text('${state?.title}'),
              trailing: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ElevatedButton(
                    onPressed: window.showTitle,
                    child: const Text('Show'),
                  ),
                  const SizedBox(width: 10),
                  ElevatedButton(
                    onPressed: window.hideTitle,
                    child: const Text('Hide'),
                  ),
                  const SizedBox(width: 10),
                  ElevatedButton(
                    onPressed: () {
                      showDialog(
                        context: context,
                        builder: (context) => AlertDialog(
                          title: const Text('Title'),
                          content: TextFormField(
                            autofocus: true,
                            initialValue: state?.title,
                            onFieldSubmitted: Navigator.of(context).pop,
                            onChanged: window.setTitle,
                          ),
                        ),
                      );
                    },
                    child: const Text('Edit'),
                  ),
                ],
              ),
            ),
            ListTile(
              title: const Text('Visible'),
              subtitle: Text('${state?.isVisible}'),
              trailing: ElevatedButton(
                onPressed: () => window
                    .hide()
                    .then((_) => Future.delayed(const Duration(seconds: 2)))
                    .then((_) => window.show()),
                child: const Text('Hide 2s'),
              ),
            ),
          ],
        );
      },
    );
  }
}

class ColorSelector extends StatefulWidget {
  const ColorSelector({super.key});

  @override
  State<ColorSelector> createState() => _ColorSelectorState();
}

class _ColorSelectorState extends State<ColorSelector> {
  Color? _color;

  @override
  Widget build(BuildContext context) {
    _color ??= Theme.of(context).colorScheme.surface;
    return Column(
      children: [
        const Spacer(),
        const Padding(
          padding: EdgeInsets.all(20),
          child: Align(
            alignment: Alignment.topLeft,
            child: Text('Color'),
          ),
        ),
        ColorPicker(
          color: _color!,
          enableShadesSelection: false,
          pickersEnabled: const {
            ColorPickerType.accent: false,
            ColorPickerType.primary: false,
            ColorPickerType.custom: false,
            ColorPickerType.wheel: true,
          },
          onColorChanged: (color) {
            setState(() => _color = color.withOpacity(_color!.opacity));
            YaruWindow.of(context).setBackground(_color!);
          },
        ),
        const Spacer(),
        const Padding(
          padding: EdgeInsets.all(20),
          child: Align(
            alignment: Alignment.topLeft,
            child: Text('Opacity'),
          ),
        ),
        Slider(
          value: _color!.opacity,
          onChanged: (value) {
            setState(() => _color = _color!.withOpacity(value));
            YaruWindow.of(context).setBackground(_color!);
          },
        ),
        const Spacer(),
      ],
    );
  }
}

关键功能点

  1. 初始化:在应用启动时调用 YaruWindow.ensureInitialized() 确保插件已正确初始化。
  2. 窗口状态监听:通过 StreamBuilder 监听窗口状态的变化,并根据状态更新UI。
  3. 窗口操作:提供了一系列方法来操作窗口,如最大化、最小化、全屏、关闭确认等。
  4. 背景颜色设置:允许用户选择并设置窗口的背景颜色和透明度。

希望这个示例能够帮助你更好地理解和使用 yaru_window 插件!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter窗口管理插件yaru_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter窗口管理插件yaru_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用yaru_window插件进行窗口管理的代码示例。yaru_window是一个允许你更精细地控制Flutter应用窗口行为的插件,比如在桌面平台上调整窗口大小、设置全屏模式等。

首先,确保你已经在pubspec.yaml文件中添加了yaru_window依赖:

dependencies:
  flutter:
    sdk: flutter
  yaru_window: ^最新版本号  # 替换为实际最新版本号

然后,运行flutter pub get来获取依赖。

接下来,我们来看一个具体的代码示例,展示如何使用yaru_window进行窗口管理:

import 'package:flutter/material.dart';
import 'package:yaru_window/yaru_window.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Yaru Window Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final YaruWindow _window = YaruWindow();

  @override
  void initState() {
    super.initState();
    // 初始化时设置窗口标题
    _window.setTitle('My Flutter App');
    
    // 监听窗口关闭事件
    _window.onClose.listen((_) {
      // 这里你可以执行一些清理操作
      print('Window is closing');
      // 阻止默认关闭行为(可选)
      // _window.close.cancel();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Yaru Window Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () {
                // 设置窗口大小
                _window.setSize(800, 600);
              },
              child: Text('Set Window Size'),
            ),
            ElevatedButton(
              onPressed: () {
                // 切换全屏模式
                _window.toggleFullScreen();
              },
              child: Text('Toggle Full Screen'),
            ),
            ElevatedButton(
              onPressed: () {
                // 最小化窗口
                _window.minimize();
              },
              child: Text('Minimize Window'),
            ),
            ElevatedButton(
              onPressed: () {
                // 最大化窗口
                _window.maximize();
              },
              child: Text('Maximize Window'),
            ),
            ElevatedButton(
              onPressed: () {
                // 关闭窗口
                _window.close();
              },
              child: Text('Close Window'),
            ),
          ],
        ),
      ),
    );
  }
}

代码说明

  1. 依赖导入:在pubspec.yaml文件中添加yaru_window依赖。
  2. 初始化:在initState方法中,通过_window.setTitle设置窗口标题,并通过_window.onClose.listen监听窗口关闭事件。
  3. 按钮操作:在UI中,我们添加了几个按钮来演示如何使用yaru_window插件进行窗口管理,包括设置窗口大小、切换全屏模式、最小化窗口、最大化窗口和关闭窗口。

请注意,yaru_window插件的具体API可能会随着版本更新而变化,因此建议查阅最新的官方文档(如果可用)以获取最新的使用方法和API。

回到顶部