Flutter多屏幕布局插件multi_screen_layout的使用

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

Flutter多屏幕布局插件multi_screen_layout的使用

multi_screen_layout 是一个用于Flutter应用程序的插件,旨在简化多屏幕用户界面的构建。它提供了一系列的Widget,使得开发者可以轻松地为不同类型的设备(如Surface Duo、Galaxy Z Fold等)创建适应多屏幕布局的应用程序。

支持的设备

  • Surface Duo
  • Surface Duo 2
  • Galaxy Z Fold 1 (Flex Mode)
  • Galaxy Z Fold 2 (Flex Mode)
  • Galaxy Z Flip (Flex Mode)

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  multi_screen_layout: ^3.1.0

app/build.gradle 文件中添加以下依赖:

dependencies { 
    implementation "androidx.window:window:1.0.0-rc01"
    implementation 'androidx.window:window-java:1.0.0-rc01'
}

测试

如果你没有物理设备,可以使用Android Studio中的特定模拟器进行测试:

  • 6.7 Horizontal Fold-in 模拟器
  • 7.6 Fold-in with outer display 模拟器
  • 8 Fold-out 模拟器
  • Surface Duo 模拟器

布局

TwoPageLayout

TwoPageLayout 用于在双屏设备上显示两个Widget,每个屏幕显示一个Widget。在折叠屏设备上,当屏幕可以分割为两个内容区域时,TwoPageLayout 会将两个Widget分别显示在两个内容区域中。在单屏设备或应用仅运行在一个屏幕上时,只会显示 child

示例代码:

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return TwoPageLayout(
      child: Scaffold(
        body: Center(child: Text('Hello from page 1!')),
      ),
      secondChild: Scaffold(
        body: Center(child: Text('Hello from page 2!')),
      ),
    );
  }
}

Surface Duo 示例:

Two Page 1

Two Page 2

Samsung Z Fold 2 Flex Mode 示例:

查看视频

MasterDetailLayout

MasterDetailLayoutTwoPageLayout 类似,但它更适合用于主从视图布局,特别是在有相关“更深入”的内容时。例如,当你有一个项目列表,点击某个项目后可以查看该项目的详细信息。

在单屏设备或应用仅运行在一个屏幕上时,master 会首先显示。当 isSelectedtrue 时,detail 会作为新页面显示在 master 之上,类似于使用 Navigator.push。在双屏设备上,masterdetail 会同时显示,不会发生导航。

示例代码:

class MasterDetailLayoutExample extends StatefulWidget {
  [@override](/user/override)
  _MasterDetailLayoutExampleState createState() => _MasterDetailLayoutExampleState();
}

class _MasterDetailLayoutExampleState extends State<MasterDetailLayoutExample> {
  int selectedItem;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MasterDetailLayout(
      master: EmailList(onItemSelected: (selected) {
        setState(() {
          selectedItem = selected;
        });
      }),
      detail: EmailDetail(itemNumber: selectedItem),
      isSelected: selectedItem != null,
    );
  }
}

Surface Duo 示例:

MasterDetail

Samsung Z Fold 2 Flex Mode 示例:

查看视频

直接数据访问

对于高级用例,你可以直接访问多屏幕信息,而不仅仅是使用上述布局Widget。

MultiScreenInfo

MultiScreenInfo 是一个Widget,允许你在Widget树中直接访问设备信息,并在数据变化时自动重建。

示例代码:

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: MultiScreenInfo(
        builder: (info) {
          return Column(
            children: <Widget>[
              Text('The below information is from the Surface Duo SDK'),
              Text('isAppSpanned: ${info.surfaceDuoInfoModel.isSpanned}'),
              Text('hingeAngle: ${info.surfaceDuoInfoModel.hingeAngle}'),
            ],
          );
        },
      ),
    );
  }
}
PlatformHandlers

如果你需要在Widget树之外访问设备信息,可以使用平台调用。

SurfaceDuoPlatformHandler 示例:

Future getSurfaceDuoInfo() async {
  var hingeAngle = await SurfaceDuoPlatformHandler.getHingeAngle();
  var isDual = await SurfaceDuoPlatformHandler.getIsDual();
  var isSpanned = await SurfaceDuoPlatformHandler.getIsSpanned();
  var nonFunctionalBounds = await SurfaceDuoPlatformHandler.getNonFunctionalBounds();
}

完整示例Demo

下面是一个完整的示例应用,展示了如何使用 TwoPageLayoutMasterDetailLayout

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

void main() {
  runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return TwoPageLayout(
      child: MainPage(),
      secondChild: SecondPage(),
    );
  }
}

class MainPage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main Page'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text('This page always displays!'),
          ),
          Expanded(
            child: ListView(
              children: [
                ListTile(
                  title: Text('Two Page Layout Example'),
                  trailing: Icon(Icons.chevron_right),
                  onTap: () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (_) => TwoPageLayoutExample()));
                  },
                ),
                ListTile(
                  title: Text('Master Detail Layout Example'),
                  trailing: Icon(Icons.chevron_right),
                  onTap: () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (_) => MasterDetailLayoutExample()));
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  final bool showAppBar;

  const SecondPage({
    Key key,
    this.showAppBar = true,
  }) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: showAppBar
          ? AppBar(
              title: Text('Second Page'),
            )
          : null,
      backgroundColor: Colors.tealAccent,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(24),
              child: Text(
                'Hello from page 2! This only displays when spanned across 2 '
                'displays or the device posture is half opened. Also known as '
                'Samsung\'s Flex Mode.',
                textAlign: TextAlign.center,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class TwoPageLayoutExample extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return TwoPageLayout(
      child: Scaffold(
        body: Center(child: Text('Page 1')),
      ),
      secondChild: Scaffold(
        body: Center(child: Text('Page 2')),
      ),
    );
  }
}

class MasterDetailLayoutExample extends StatefulWidget {
  [@override](/user/override)
  _MasterDetailLayoutExampleState createState() => _MasterDetailLayoutExampleState();
}

class _MasterDetailLayoutExampleState extends State<MasterDetailLayoutExample> {
  int selectedItem;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MasterDetailLayout(
      master: EmailList(onItemSelected: (selected) {
        setState(() {
          selectedItem = selected;
        });
      }),
      detail: EmailDetail(itemNumber: selectedItem),
      isSelected: selectedItem != null,
    );
  }
}

class EmailList extends StatelessWidget {
  final Function(int) onItemSelected;

  EmailList({this.onItemSelected});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 10,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text('Email $index'),
          onTap: () => onItemSelected(index),
        );
      },
    );
  }
}

class EmailDetail extends StatelessWidget {
  final int itemNumber;

  EmailDetail({this.itemNumber});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Email Detail'),
      ),
      body: Center(
        child: Text('Detail for Email $itemNumber'),
      ),
    );
  }
}

更多关于Flutter多屏幕布局插件multi_screen_layout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多屏幕布局插件multi_screen_layout的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter的multi_screen_layout插件的示例代码。multi_screen_layout插件允许你在Flutter应用中创建多屏幕布局,这在开发如分屏应用或跨设备协作应用时非常有用。

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

dependencies:
  flutter:
    sdk: flutter
  multi_screen_layout: ^x.y.z  # 请替换为最新版本号

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

接下来是一个简单的示例代码,展示了如何使用multi_screen_layout插件来创建一个双屏幕布局。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MultiScreenHome(),
    );
  }
}

class MultiScreenHome extends StatefulWidget {
  @override
  _MultiScreenHomeState createState() => _MultiScreenHomeState();
}

class _MultiScreenHomeState extends State<MultiScreenHome> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Multi Screen Layout Example'),
      ),
      body: MultiScreenLayout(
        // 监听屏幕连接状态变化
        onScreenConnectionChange: (screens) {
          print('Screen connection changed: $screens');
        },
        // 默认布局
        defaultLayout: LayoutConfiguration(
          orientation: LayoutOrientation.horizontal,
          screens: 2,
          // 屏幕间分隔线颜色
          dividerColor: Colors.black,
          // 屏幕间分隔线宽度
          dividerThickness: 4.0,
        ),
        // 构建屏幕内容
        builder: (context, screenId, screenInfo) {
          switch (screenId) {
            case 0:
              return Center(
                child: Text('Screen 1'),
              );
            case 1:
              return Center(
                child: Text('Screen 2'),
              );
            default:
              return Container();
          }
        },
      ),
    );
  }
}

解释

  1. 依赖添加:在pubspec.yaml文件中添加multi_screen_layout依赖。

  2. MultiScreenLayout Widget

    • onScreenConnectionChange:这是一个回调,当屏幕连接状态改变时会触发。例如,当连接或断开第二个屏幕时。
    • defaultLayout:定义了默认的布局配置,包括布局方向(水平或垂直)、屏幕数量、分隔线颜色和宽度。
    • builder:用于构建每个屏幕的内容。screenId是屏幕的标识符,从0开始。screenInfo包含有关当前屏幕的信息,如尺寸和位置。
  3. 屏幕内容:在builder函数中,根据screenId返回不同的内容。在这个示例中,屏幕1显示“Screen 1”,屏幕2显示“Screen 2”。

注意事项

  • multi_screen_layout插件需要在支持多屏幕的设备或模拟器上运行,以便看到效果。
  • 你可以根据需要调整布局配置和屏幕内容。

这个示例提供了一个基本的框架,你可以在此基础上根据具体需求进行扩展和定制。

回到顶部