Flutter展示演示显示屏插件presentation_displays的使用

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

Flutter展示演示显示屏插件presentation_displays的使用

插件简介

presentation_displays 是一个支持iOS和Android平台的Flutter插件,允许应用程序在两个屏幕上运行。它通过创建Flutter代码中的Widget,并将其传递给原生代码侧转换为FlutterEngine并保存到FlutterEngineCache中以供后续使用。然后定义需要显示的Display(通过displayId),从FlutterEngineCache获取FlutterEngine并将其传输到Dialog Presentation作为View进行显示。

主要功能:

  • 获取连接设备列表及其信息。
  • 将数据从主屏幕传输到次级屏幕。
  • 在次级屏幕上接收数据。
  • 设置新的入口点用于初始化次级屏幕。

示例代码详解

1. 配置路由生成函数

Route<dynamic> generateRoute(RouteSettings settings) {
  switch (settings.name) {
    case '/':
      return MaterialPageRoute(builder: (_) => const DisplayManagerScreen());
    case 'presentation':
      return MaterialPageRoute(builder: (_) => const SecondaryScreen());
    default:
      return MaterialPageRoute(
          builder: (_) => Scaffold(
                body: Center(
                    child: Text('No route defined for ${settings.name}')),
              ));
  }
}

此函数根据路由名称返回相应的页面。

2. 初始化应用与次级屏幕入口

void main() {
  debugPrint('first main');
  runApp(const MyApp());
}

@pragma('vm:entry-point')
void secondaryDisplayMain() {
  debugPrint('second main');
  runApp(const MySecondApp());
}

这里定义了两个入口点:一个是主应用程序的入口,另一个是专门用于次级屏幕的应用程序入口。

3. 定义主应用与次级应用

class MySecondApp extends StatelessWidget {
  const MySecondApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      onGenerateRoute: generateRoute,
      initialRoute: 'presentation',
    );
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      onGenerateRoute: generateRoute,
      initialRoute: '/',
    );
  }
}

这两个类分别定义了主应用和次级应用的布局结构。

4. 创建按钮组件

class Button extends StatelessWidget {
  final String title;
  final VoidCallback? onPressed;

  const Button({Key? key, required this.title, this.onPressed})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.all(4.0),
      child: ElevatedButton(
        onPressed: onPressed,
        child: Text(
          title,
          style: const TextStyle(fontSize: 25),
        ),
      ),
    );
  }
}

这是一个简单的按钮组件,可以方便地复用。

5. 显示管理界面

class DisplayManagerScreen extends StatefulWidget {
  const DisplayManagerScreen({Key? key}) : super(key: key);

  @override
  _DisplayManagerScreenState createState() => _DisplayManagerScreenState();
}

class _DisplayManagerScreenState extends State<DisplayManagerScreen> {
  // ... 省略部分代码 ...
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              _getDisplays(),
              _showPresentation(),
              _hidePresentation(),
              _transferData(),
              _getDisplayeById(),
              _getDisplayByIndex(),
            ],
          ),
        ),
      ),
    );
  }

  // ... 省略部分代码 ...
}

该界面提供了几个操作按钮,包括获取所有显示设备、显示/隐藏次级屏幕、传输数据等。

6. 次级屏幕UI

class SecondaryScreen extends StatefulWidget {
  const SecondaryScreen({Key? key}) : super(key: key);

  @override
  _SecondaryScreenState createState() => _SecondaryScreenState();
}

class _SecondaryScreenState extends State<SecondaryScreen> {
  String value = "init";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SecondaryDisplay(
      callback: (dynamic argument) {
        setState(() {
          value = argument;
        });
      },
      child: Container(
        color: Colors.white,
        child: Center(
          child: Text(value),
        ),
      ),
    ));
  }
}

这是次级屏幕上显示的内容,其中包含了一个接收来自主屏幕的数据并更新显示内容的功能。

注意事项

  • 对于iOS平台,可能需要在AppDelegate中添加一些特定的代码来确保正常工作。
  • 测试时,请确保设备支持USB C 3.0及以上版本或HDMI输出。
  • 当前版本已支持Android发布构建,并且示例应用程序已经过测试,可以在Android平板和iOS平板上正常使用。

通过以上步骤和提供的完整示例代码,您可以轻松地在项目中集成presentation_displays插件,实现多屏展示功能。


更多关于Flutter展示演示显示屏插件presentation_displays的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter展示演示显示屏插件presentation_displays的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用presentation_displays插件来展示演示显示屏的示例代码。这个插件允许你在连接到主显示设备的其他显示设备上展示内容,例如投影仪或外部显示器。

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

dependencies:
  flutter:
    sdk: flutter
  presentation_displays: ^0.x.x  # 请使用最新版本号

然后,运行flutter pub get来安装依赖。

接下来,是一个简单的示例代码,展示如何使用presentation_displays插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Presentation Displays Example'),
        ),
        body: PresentationScreen(),
      ),
    );
  }
}

class PresentationScreen extends StatefulWidget {
  @override
  _PresentationScreenState createState() => _PresentationScreenState();
}

class _PresentationScreenState extends State<PresentationScreen> {
  PresentationDisplay? _currentDisplay;
  PresentationDisplayConnection? _connection;
  bool _isPresenting = false;

  @override
  void initState() {
    super.initState();
    _initializePresentationDisplays();
  }

  Future<void> _initializePresentationDisplays() async {
    PresentationDisplayList displays = await PresentationDisplayList.requestAvailability();
    if (displays.availableDisplays.isNotEmpty) {
      setState(() {
        _currentDisplay = displays.availableDisplays.first;
      });
    } else {
      print('No available displays.');
    }
  }

  Future<void> _startPresentation() async {
    if (_currentDisplay == null) return;

    _connection = await _currentDisplay!.requestConnection();
    if (_connection != null) {
      setState(() {
        _isPresenting = true;
      });

      // 创建一个新的Widget来在演示显示屏上显示
      _connection!.startPresentation(
        context,
        MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('Presentation Display'),
            ),
            body: Center(
              child: Text('This is displayed on the presentation display!'),
            ),
          ),
        ),
      );
    }
  }

  Future<void> _stopPresentation() async {
    if (_connection != null) {
      await _connection!.close();
      setState(() {
        _isPresenting = false;
        _connection = null;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('Current Display: ${_currentDisplay?.displayName ?? 'None'}'),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: _isPresenting ? _stopPresentation : _startPresentation,
            child: Text(_isPresenting ? 'Stop Presentation' : 'Start Presentation'),
          ),
        ],
      ),
    );
  }

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

代码说明

  1. 依赖安装:在pubspec.yaml中添加presentation_displays插件依赖。
  2. 初始化:在initState方法中调用_initializePresentationDisplays来请求可用的演示显示屏列表。
  3. 显示列表:如果检测到可用的演示显示屏,将其设置为_currentDisplay
  4. 开始演示_startPresentation方法请求与当前显示屏的连接,并在连接成功后启动一个新的Widget树进行显示。
  5. 停止演示_stopPresentation方法关闭与演示显示屏的连接。
  6. 按钮控制:通过按钮控制开始和停止演示。

请确保在实际使用时处理错误和异常情况,例如检查_connection是否成功建立,以及处理连接失败的情况。这个示例提供了一个基本的框架,你可以根据需要进行扩展和修改。

回到顶部