Flutter屏障插件barrier_around的使用

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

Flutter屏障插件barrier_around的使用

barrier_around_header

Barrier Around

pub package

一个可以在任何位置为任意小部件创建屏障的Flutter插件。

解决什么问题?

有时我们需要突出显示或展示特定的小部件。如果该小部件是Stack的直接子项,这很容易实现。但是,如果我们想围绕一个嵌套在例如Column中的特定小部件创建一个屏障,这将变得非常复杂。我们可以通过计算位置和大小来尝试实现,但这种方法很快就会变得混乱。

查看演示视频

使用方法

要使用此插件,在你的pubspec.yaml文件中添加barrier_around作为依赖项。

dependencies:
  barrier_around: ^x.x.x

示例

首先,创建一个GlobalKey以标识你想要创建屏障的小部件。

final GlobalKey _barrierKey = GlobalKey();

接下来,将你想要创建屏障的小部件包装在一个BarrierAround小部件中,并为其分配GlobalKey

BarrierAround(
    key: _barrierKey,
    child: yourWidget
)

当你想要显示屏障时,只需调用:

BarrierAroundManager.showBarrier(_barrierKey);

要关闭屏障,只需点击它即可,这种行为默认启用。如果你希望屏障在点击时不消失,可以在BarrierAround小部件中设置dismissOnBarrierTapfalse

如果你想从其他地方关闭屏障,只需调用:

BarrierAroundManager.dismissBarrier(_barrierKey);

屏障自定义

你可以通过以下属性来自定义屏障:

名称 类型 描述 默认值
barrierBorderRadius BorderRadius? 如果你的小部件有圆角,则在这里设置 null
barrierColor Color 屏障的颜色 Colors.black45
barrierOpacity double 屏障的不透明度 0.75
barrierBlur double? 屏障的模糊程度 null
targetPadding EdgeInsets 目标小部件周围的填充 EdgeInsets.zero
onBarrierTap VoidCallback? 点击屏障的回调 null
dismissOnBarrierTap bool 当用户点击屏障时是否应该消失 true
animateBarrier bool 显示/隐藏屏障时是否需要动画 true
animationDuration Duration 如果animateBarriertrue,你可以在这里指定动画持续时间 Duration(milliseconds: 150)

建议和贡献

如果你有任何关于代码改进、错误修复、新功能的建议,或者希望以任何方式做出贡献,请在GitHub上提出问题或私信我Twitter


完整示例代码

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BarrierAround Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Scaffold(
        body: SafeArea(
          child: Center(
            child: BarrierAroundShowcase(),
          ),
        ),
      ),
    );
  }
}

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

  [@override](/user/override)
  State<BarrierAroundShowcase> createState() => _BarrierAroundShowcaseState();
}

class _BarrierAroundShowcaseState extends State<BarrierAroundShowcase> {
  static const textStyle = TextStyle(
    fontSize: 18.0,
    color: Colors.white,
    fontWeight: FontWeight.bold,
  );

  final GlobalKey _redContainerBarrier = GlobalKey();
  final GlobalKey _greenContainerBarrier = GlobalKey();
  final GlobalKey _blueContainerBarrier = GlobalKey();

  bool tapped = false;

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _createRedContainer(),
          const SizedBox(height: 16.0),
          _createGreenContainer(),
          const SizedBox(height: 16.0),
          _createBlueContainer(),
        ],
      ),
    );
  }

  _createRedContainer() {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          BarrierAroundManager.showBarrier(_redContainerBarrier);
        },
        child: BarrierAround(
          key: _redContainerBarrier,
          animateBarrier: false,
          child: Container(
            padding: const EdgeInsets.all(16.0),
            color: Colors.red.withOpacity(0.9),
            width: double.infinity,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: const [
                Text(
                  "Animate: false",
                  style: textStyle,
                ),
                Text(
                  "Barrier blur: 0.0",
                  style: textStyle,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  _createGreenContainer() {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          BarrierAroundManager.showBarrier(_greenContainerBarrier);
        },
        child: BarrierAround(
          key: _greenContainerBarrier,
          barrierBorderRadius: BorderRadius.circular(16.0),
          barrierBlur: 15.0,
          animationDuration: const Duration(seconds: 1),
          onBarrierTap: () {
            setState(() {
              tapped = true;
            });

            Future.delayed(const Duration(seconds: 2), () {
              setState(() {
                tapped = false;
              });
            });
          },
          child: Container(
            padding: const EdgeInsets.all(16.0),
            decoration: BoxDecoration(
              color: Colors.green.withOpacity(0.9),
              borderRadius: BorderRadius.circular(16.0),
            ),
            width: double.infinity,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                const Text(
                  "Animate: true",
                  style: textStyle,
                ),
                const Text(
                  "Animation duration: 1 second",
                  style: textStyle,
                ),
                const Text(
                  "Barrier blur: 15.0",
                  style: textStyle,
                ),
                const Text(
                  "Barrier border radius: 16.0",
                  style: textStyle,
                ),
                Text(
                  !tapped
                      ? "onBarrierTap: Not tapped yet..."
                      : "onBarrierTap: TAPPED!",
                  style: textStyle,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  _createBlueContainer() {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          BarrierAroundManager.showBarrier(_blueContainerBarrier);
        },
        child: BarrierAround(
          key: _blueContainerBarrier,
          barrierBorderRadius: BorderRadius.circular(32.0),
          barrierBlur: 5.0,
          barrierColor: Colors.teal,
          targetPadding: const EdgeInsets.all(4.0),
          child: Container(
            padding: const EdgeInsets.all(16.0),
            decoration: BoxDecoration(
              color: Colors.blue.withOpacity(0.9),
              borderRadius: BorderRadius.circular(32.0),
            ),
            width: double.infinity,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: const [
                Text(
                  "Animate: true",
                  style: textStyle,
                ),
                Text(
                  "Barrier blur: 5.0",
                  style: textStyle,
                ),
                Text(
                  "Barrier border radius: 32.0",
                  style: textStyle,
                ),
                Text(
                  "Barrier color: teal",
                  style: textStyle,
                ),
                Text(
                  "Target padding: 4.0",
                  style: textStyle,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是如何在Flutter项目中使用barrier_around插件的一个示例。barrier_around是一个Flutter插件,它允许你在指定的widget周围添加一个半透明的屏障。这在创建模态对话框、聚焦特定区域等场景中非常有用。

首先,你需要在你的pubspec.yaml文件中添加barrier_around依赖:

dependencies:
  flutter:
    sdk: flutter
  barrier_around: ^latest_version  # 请替换为实际的最新版本号

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

接下来是一个完整的示例,展示如何使用barrier_around

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  bool _isBarrierVisible = false;

  void _toggleBarrier() {
    setState(() {
      _isBarrierVisible = !_isBarrierVisible;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Barrier Around Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You can click the button to toggle the barrier around the focused widget.',
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _toggleBarrier,
              child: Text('Toggle Barrier'),
            ),
            SizedBox(height: 40),
            BarrierAround(
              visible: _isBarrierVisible,
              color: Colors.black.withOpacity(0.5),
              barrierConstraints: BoxConstraints(
                minHeight: 200,
                minWidth: 200,
              ),
              child: FocusWidget(),
            ),
          ],
        ),
      ),
    );
  }
}

class FocusWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.lightBlue,
        borderRadius: BorderRadius.circular(16),
      ),
      padding: EdgeInsets.all(16),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'This is the focused widget.',
            style: TextStyle(fontSize: 20, color: Colors.white),
          ),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {},
            child: Text('Click Me', style: TextStyle(color: Colors.white)),
          ),
        ],
      ),
    );
  }
}

在这个示例中:

  1. MyApp是我们的主应用类,它包含了一个MaterialApp
  2. MyHomePage是我们的主页面,它包含一个按钮和一个BarrierAround widget。
  3. _toggleBarrier方法用于切换屏障的可见性。
  4. BarrierAround widget包裹了一个FocusWidget,当屏障可见时,它会围绕FocusWidget显示一个半透明的屏障。
  5. FocusWidget是我们想要聚焦的widget,它包含了一些文本和一个按钮。

你可以根据需要调整BarrierAround的参数,例如colorbarrierConstraints,以符合你的应用需求。

回到顶部