L o a d i n g . . .
主打一个C++
文章详情

flutter显示系统悬浮窗口,ios、android的所有应用之上

Posted on 2025-05-01 01:46:49 by 主打一个C++

效果图:

image.png

所需权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>#后台可选

插件:

system_alert_window: ^2.0.7
share_plus:

android配置:

compileSdk = 36
ndkVersion = "27.0.12077973"

测试代码:

import 'dart:async';
import 'dart:developer';
import 'dart:isolate';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:share_plus/share_plus.dart';
import 'package:system_alert_window/system_alert_window.dart';

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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: SizedBox(
        width: 32.0,
        height: 32.0,
        child: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            IconButton(
              onPressed: () {
                debugPrint("悬浮按钮被按下");
              },
              icon: const Icon(Icons.settings, color: Colors.red, size: 32.0),
            )
          ],
        )
      ),
    );
  }
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

@pragma("vm:entry-point")
void overlayMain() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MaterialApp(debugShowCheckedModeBanner: false, home: HomePage()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  bool _isShowingWindow = false;
  bool _isUpdatedWindow = false;
  SystemWindowPrefMode prefMode = SystemWindowPrefMode.OVERLAY;
  static const String _mainAppPort = 'MainApp';
  final _receivePort = ReceivePort();
  SendPort? homePort;
  String? latestMessageFromOverlay;

  @override
  void initState() {
    super.initState();
    _initPlatformState();
    _requestPermissions();
    if (homePort != null) return;
    final res = IsolateNameServer.registerPortWithName(
      _receivePort.sendPort,
      _mainAppPort,
    );
    log("$res: OVERLAY");
    _receivePort.listen((message) {
      log("message from OVERLAY: $message");
    });
  }

  @override
  void dispose() {
    super.dispose();
  }

  //平台消息是异步的,因此采用异步方法进行初始化。
  Future<void> _initPlatformState() async {
    await SystemAlertWindow.enableLogs(true);
    String? platformVersion;
    // 平台消息可能会失败,因此使用try/catch PlatformException
    try {
      platformVersion = await SystemAlertWindow.platformVersion;
    } on PlatformException {
      platformVersion = '未能获取平台版本。';
    }

//如果在异步平台运行时从树中删除了小部件
//消息正在传输中,丢弃回复而不是呼叫
//setState来更新不存在的外观。
    if (!mounted) return;
    if (platformVersion != null)
      setState(() {
        _platformVersion = platformVersion!;
      });
  }

  Future<void> _requestPermissions() async {
    await SystemAlertWindow.requestPermissions(prefMode: prefMode);
  }

  void _showOverlayWindow() async {
    if (!_isShowingWindow) {
      await SystemAlertWindow.sendMessageToOverlay('show system window');
      SystemAlertWindow.showSystemWindow(
        height: 200,
        width: MediaQuery.of(context).size.width.floor(),
        gravity: SystemWindowGravity.CENTER,
        prefMode: prefMode,
        layoutParamFlags: [SystemWindowFlags.FLAG_NOT_FOCUSABLE],
      );
      setState(() {
        _isShowingWindow = true;
      });
    } else if (!_isUpdatedWindow) {
      await SystemAlertWindow.sendMessageToOverlay('update system window');
      SystemAlertWindow.updateSystemWindow(
        height: 200,
        width: MediaQuery.of(context).size.width.floor(),
        gravity: SystemWindowGravity.CENTER,
        prefMode: prefMode,
        layoutParamFlags: [
          SystemWindowFlags.FLAG_NOT_FOCUSABLE,
          SystemWindowFlags.FLAG_NOT_TOUCHABLE,
        ],
        // isDisableClicks: true
      );
      setState(() {
        _isUpdatedWindow = true;
        SystemAlertWindow.sendMessageToOverlay(_isUpdatedWindow);
      });
    } else {
      setState(() {
        _isShowingWindow = false;
        _isUpdatedWindow = false;
        SystemAlertWindow.sendMessageToOverlay(_isUpdatedWindow);
      });
      SystemAlertWindow.closeSystemWindow(prefMode: prefMode);
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text(
            '带flutterview的系统警报窗口示例应用程序',
          ),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              Text('Running on: $_platformVersion\n'),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: MaterialButton(
                  onPressed: _showOverlayWindow,
                  textColor: Colors.white,
                  child: !_isShowingWindow
                      ? Text("Show system alert window")
                      : !_isUpdatedWindow
                      ? Text("Update system alert window")
                      : Text("Close system alert window"),
                  color: Colors.deepOrange,
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: MaterialButton(
                  onPressed: () => SystemAlertWindow.sendMessageToOverlay(
                    "message from main",
                  ),
                  textColor: Colors.white,
                  child: Text("send message to overlay"),
                  color: Colors.deepOrange,
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                ),
              ),
              TextButton(
                onPressed: () async {
                  String? logFilePath = await SystemAlertWindow.getLogFile;
                  if (logFilePath != null && logFilePath.isNotEmpty) {
                    final files = <XFile>[];
                    files.add(XFile(logFilePath, name: "Log File from SAW"));
                    await Share.shareXFiles(files);
                  } else {
                    print("Path is empty");
                  }
                },
                child: Text("Share Log file"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}


*转载请注明出处:原文链接:https://cpp.vin/page/152.html

作者近期文章
提示
×
确定
数据库执行: 7次 总耗时: 0.01s
页面加载耗时: 



wechat +447752296473
wechat cpp-blog