Flutter可滚动面板插件scrollable_panel的使用

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

Flutter可滚动面板插件scrollable_panel的使用

scrollable_panel 是一个用于Flutter的插件,它允许用户通过拖动来展开和滚动内容,类似于Google地图应用中的“附近地点”面板。本文将介绍如何使用这个插件,并提供一个完整的示例demo。

插件特性

  • builder: 用于定义内部面板视图的构建器。
  • controller: 控制面板状态(如打开、关闭等)。
  • defaultPanelState: 设置默认面板状态。
  • defaultPanelSize: 设置默认面板高度因子。
  • minPanelSize: 设置最小面板高度因子。
  • maxPanelSize: 设置最大面板高度因子。
  • onOpen, onClose, onExpand: 面板状态变化时的回调函数。

PanelController 动作

  • open(): 打开面板。
  • expand(): 展开面板。
  • close(): 关闭面板。
  • animateTo(double value): 动画到指定高度。

使用示例

以下是一个完整的示例代码,展示如何在Flutter应用中使用scrollable_panel插件。

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

void main() => runApp(MyApp());

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

class MyHomePage extends StatefulWidget {
  MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  PanelController _panelController = PanelController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(kToolbarHeight),
        child: _AnimatedAppBar(panelController: _panelController),
      ),
      body: Stack(
        children: [
          Positioned.fill(
            child: _FirstView(controller: _panelController),
          ),
          ScrollablePanel(
            defaultPanelState: PanelState.close,
            controller: _panelController,
            onOpen: () => print('onOpen'),
            onClose: () => print('onClose'),
            onExpand: () => print('onExpand'),
            builder: (context, controller) {
              return SingleChildScrollView(
                controller: controller,
                child: _SecondView(),
              );
            },
          ),
        ],
      ),
    );
  }
}

class _AnimatedAppBar extends StatefulWidget {
  const _AnimatedAppBar({
    Key? key,
    required this.panelController,
  }) : super(key: key);

  final PanelController panelController;

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

class __AnimatedAppBarState extends State<_AnimatedAppBar> with SingleTickerProviderStateMixin {
  late final Animation _animation;
  late final AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
    widget.panelController.animation?.addListener(() {
      if (widget.panelController.animation!.value >= 0.8) {
        _animationController.value = (0.2 - (1.0 - widget.panelController.animation!.value)) * 5;
      } else {
        _animationController.value = 0;
      }
    });
    _animation = ColorTween(begin: Colors.white, end: Colors.red).animate(_animationController);
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        return Material(
          elevation: 4.0,
          color: _animation.value,
          child: SafeArea(
            bottom: false,
            top: true,
            child: Container(
              height: kToolbarHeight,
              child: const Center(child: Text('scrollable panel')),
            ),
          ),
        );
      },
    );
  }
}

class _FirstView extends StatelessWidget {
  const _FirstView({
    Key? key,
    required this.controller,
  }) : super(key: key);

  final PanelController controller;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ElevatedButton(onPressed: () => controller.open(), child: const Text('open panel')),
        ElevatedButton(onPressed: () => controller.close(), child: const Text('close panel')),
        ElevatedButton(onPressed: () => controller.expand(), child: const Text('expand panel')),
      ],
    );
  }
}

class _SecondView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    const double circularBoxHeight = 16.0;
    final Size size = MediaQuery.of(context).size;
    return LayoutBuilder(
      builder: (context, constraints) {
        return ConstrainedBox(
          constraints: BoxConstraints(minHeight: size.height + kToolbarHeight + 44.0),
          child: Container(
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: const BorderRadius.only(topLeft: Radius.circular(circularBoxHeight), topRight: Radius.circular(circularBoxHeight)),
              border: Border.all(color: Colors.blue),
            ),
            child: const Center(child: Text("second")),
          ),
        );
      },
    );
  }
}

总结

通过上述示例,您可以轻松地在Flutter应用中集成scrollable_panel插件,实现类似Google地图应用中的可滚动面板效果。希望这个示例能帮助您快速上手并应用于实际项目中。


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

1 回复

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


当然,以下是一个关于如何在Flutter中使用scrollable_panel插件的示例代码。scrollable_panel插件允许你创建一个可滚动的面板,这在创建复杂UI时非常有用。首先,确保你已经在pubspec.yaml文件中添加了scrollable_panel依赖:

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

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

以下是一个简单的示例,展示如何使用ScrollablePanel来创建一个可滚动的面板:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scrollable Panel Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Scrollable Panel Demo'),
        ),
        body: Center(
          child: ScrollablePanelDemo(),
        ),
      ),
    );
  }
}

class ScrollablePanelDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'This is a demo of ScrollablePanel in Flutter.',
            style: TextStyle(fontSize: 24),
          ),
          SizedBox(height: 20),
          ScrollablePanel(
            // 设置面板的最小高度和最大高度
            minHeight: 100,
            maxHeight: 300,
            // 设置初始高度(可选)
            initialHeight: 200,
            // 设置面板内容
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: List.generate(
                50,
                (index) => Padding(
                  padding: const EdgeInsets.only(left: 16.0, bottom: 8.0),
                  child: Text(
                    'Item $index',
                    style: TextStyle(fontSize: 18),
                  ),
                ),
              ),
            ),
            // 设置面板头部(可选)
            header: Container(
              color: Colors.grey[300],
              padding: EdgeInsets.all(8.0),
              child: Text(
                'Panel Header',
                style: TextStyle(fontSize: 18, color: Colors.black),
              ),
            ),
            // 设置面板底部控制按钮(可选)
            footer: Container(
              color: Colors.grey[300],
              padding: EdgeInsets.all(8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  TextButton(
                    onPressed: () {
                      // 收缩面板
                      ScrollablePanel.of(context)?.collapse();
                    },
                    child: Text('Collapse'),
                  ),
                  TextButton(
                    onPressed: () {
                      // 展开面板到最大高度
                      ScrollablePanel.of(context)?.expand();
                    },
                    child: Text('Expand'),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

在这个示例中:

  1. ScrollablePanel 被用来创建一个可滚动且可调整高度的面板。
  2. minHeightmaxHeight 属性定义了面板的最小和最大高度。
  3. initialHeight 属性定义了面板的初始高度。
  4. headerfooter 属性允许你添加面板的头部和底部控件,比如按钮。
  5. child 属性定义了面板的内容。

运行这个示例应用,你将看到一个带有可调整高度面板的页面,面板内容超出了初始高度时可以滚动,同时有按钮可以控制面板的收缩和展开。

回到顶部