Flutter悬浮上拉卡片插件floating_pullup_card的使用

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

Flutter悬浮上拉卡片插件 floating_pullup_card 的使用

floating_pullup_card 是一个用于Flutter的漂亮且可自定义的浮动上拉样式卡片。以下是该插件的安装和使用方法。

💻 安装

在你的 pubspec.yaml 文件中的 dependencies: 部分添加以下行:

dependencies:
  floating_pullup_card: <latest version>

请将 <latest version> 替换为最新的版本号,可以从 pub.dev 获取最新版本号。

使用

基础示例

你可以非常简单地开始使用这个插件,只需添加以下代码:

FloatingPullUpCardLayout(
  child: Container(
    decoration: BoxDecoration(color: Colors.purple[100]),
    child: Placeholder(),
  ),
  body: Column(
    children: <Widget>[
      PlaceholderLines(
        count: 10,
        align: TextAlign.center,
      ),
    ],
  ),
)

其中:

  • body 是嵌套在卡片内的小部件。
  • child 是主布局内容。

高级示例

你可以通过定义自定义构建器或属性(如 widthheightcolor 等)进行高度自定义:

FloatingPullUpCardLayout(
  dismissable: _dismissable,
  state: _floatingCardState,
  dragHandleBuilder: _customDragHandle ? _customDragHandleBuilder : null,
  cardBuilder: _customCard ? _customCardBuilder : null,
  collpsedStateOffset: _customCollapsedOffset ? (maxHeight, _) => maxHeight * .75 : null,
  autoPadding: _autoPadd,
  body: Container(
    child: SingleChildScrollView(
      child: Column(
        children: <Widget>[
          PlaceholderLines(
            count: 4,
            align: TextAlign.center,
          ),
          // ... more content
        ],
      ),
    ),
  ),
  child: Container(
    decoration: BoxDecoration(color: Colors.grey[300]),
    height: double.infinity,
    width: double.infinity,
    child: SingleChildScrollView(
      child: // ... Some content
    ),
  ),
)

完整API

以下是插件提供的完整API:

/// The [Widget] to be used as the content of the main layout, not the card content
final Widget child;

/// The [Widget] to be used as the content of the floating card
final Widget body;

/// Set a custom [height] for the floating card,
/// defaults to `86%` of total height of parent container or screen height if no finite height can be assumed
final double height;

/// Set a custom [width] for the floating card,
/// defaults to `100%` of total width of parent container or screen width if no finite width can be assumed
final double width;

/// Set a [cardElevation] for the material,
/// defaults to `4`
final double cardElevation;

/// If true , the card can be dragged until it's hidden from screen
/// defaults to [false]
final bool dismissable;

/// Sets the [state] of the floating card,
/// See enum [FloatingPullUpState] for more details
/// Defaults to [FloatingPullUpState.collapsed]
final FloatingPullUpState state;

/// Set a custom card [color] to the card background
/// defaults to [Colors.white]
///
/// This doesn't take any effect if using [cardBuilder] is defined
final Color cardColor;

/// Called each time the [FloatingPullUpState] is changed
final ValueChanged<FloatingPullUpState> onStateChange;

/// Defines a custom [dragHandleBuilder]
final DragHandleBuilder dragHandleBuilder;

/// Defines a custom [cardBuilder]
final FloatingCardBuilder cardBuilder;

/// Set a custom [borderRadius] of the default Card material
///
/// This doesn't take any effect if using [cardBuilder] is defined
final BorderRadius borderRadius;

/// If true, this automatically adds padding to the [child] container,
/// avoiding the card to float on top of [child] content
/// defaults to [true]
final autoPadding;

/// Sets a custom function that return a custom `Y Offset`  for state [FloatingPullUpState.collapsed]
/// Please take into account that offset start from top to bottom
StateOffsetFunction collpsedStateOffset;

/// Sets a custom function that return a custom `Y Offset`  for state [FloatingPullUpState.hidden]
/// Please take into account that offset start from top to bottom
StateOffsetFunction hiddenStateOffset;

/// Sets a custom function that return a custom `Y Offset`  for state [FloatingPullUpState.uncollapsed]
/// Please take into account that offset start from top to bottom
StateOffsetFunction uncollpsedStateOffset;

/// Defines a callback to be called when a user taps outside the card
/// If function returns [FloatingPullUpState] it will change state to the returned one
/// Take into account that this is not getting called if a widget inside body is already handling a `Gesture`
final FloatingPullUpState Function() onOutsideTap;

/// If true, this will show an overlay behind the card that obscures content behind
/// Defaults to [false]
final bool withOverlay;

/// Defines the `color` of the overlay, this only takes effect if [withOverlayOption] is true
final Color overlayColor;

示例Demo

以下是一个完整的示例demo,展示了如何使用 floating_pullup_card 插件:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/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 StatelessWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: Text("Basic Example"),
              onPressed: () {
                Navigator.of(context).push(MaterialPageRoute(builder: (_) {
                  return BasicScreen();
                }));
              },
            ),
            ElevatedButton(
              child: Text("Advanced Example"),
              onPressed: () {
                Navigator.of(context).push(MaterialPageRoute(builder: (_) {
                  return AdvancedScreen();
                }));
              },
            ),
          ],
        ),
      ),
    );
  }
}

class BasicScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Basic Example'),
      ),
      body: FloatingPullUpCardLayout(
        child: Container(
          decoration: BoxDecoration(color: Colors.purple[100]),
          child: Placeholder(),
        ),
        body: Column(
          children: <Widget>[
            PlaceholderLines(
              count: 10,
              align: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }
}

class AdvancedScreen extends StatelessWidget {
  final bool _dismissable = true;
  final FloatingPullUpState _floatingCardState = FloatingPullUpState.collapsed;
  final bool _customDragHandle = true;
  final bool _customCard = true;
  final bool _customCollapsedOffset = true;
  final bool _autoPadd = true;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Advanced Example'),
      ),
      body: FloatingPullUpCardLayout(
        dismissable: _dismissable,
        state: _floatingCardState,
        dragHandleBuilder: _customDragHandle ? _customDragHandleBuilder : null,
        cardBuilder: _customCard ? _customCardBuilder : null,
        collpsedStateOffset: _customCollapsedOffset ? (maxHeight, _) => maxHeight * .75 : null,
        autoPadding: _autoPadd,
        body: Container(
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                PlaceholderLines(
                  count: 4,
                  align: TextAlign.center,
                ),
                // ... more content
              ],
            ),
          ),
        ),
        child: Container(
          decoration: BoxDecoration(color: Colors.grey[300]),
          height: double.infinity,
          width: double.infinity,
          child: SingleChildScrollView(
            child: // ... Some content
          ),
        ),
      ),
    );
  }

  Widget _customDragHandleBuilder(double percentage) {
    return Container(
      height: 20,
      color: Colors.transparent,
      child: Center(
        child: Container(
          width: 50,
          height: 5,
          decoration: BoxDecoration(
            color: Colors.grey,
            borderRadius: BorderRadius.circular(12.0),
          ),
        ),
      ),
    );
  }

  Widget _customCardBuilder(double percentage, double maxHeight, double maxWidth) {
    return Material(
      elevation: 4,
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(16),
        topRight: Radius.circular(16),
      ),
      child: Container(
        width: maxWidth,
        height: maxHeight,
        color: Colors.white,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: <Widget>[
              Expanded(
                child: Placeholder(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter悬浮上拉卡片插件floating_pullup_card的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter悬浮上拉卡片插件floating_pullup_card的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 floating_pullup_card Flutter 插件的示例代码。这个插件允许你在应用中实现悬浮上拉卡片的效果。

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

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

然后运行 flutter pub get 来获取依赖。

接下来,你可以在你的 Flutter 应用中使用这个插件。以下是一个简单的示例,展示如何在 Scaffold 中添加一个悬浮上拉卡片:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  bool _isPulledUp = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    )..addListener(() {
      setState(() {});
    });
  }

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

  void _pullUp() {
    setState(() {
      _isPulledUp = !_isPulledUp;
    });

    if (_isPulledUp) {
      _controller.forward();
    } else {
      _controller.reverse();
    }
  }

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;

    return Scaffold(
      appBar: AppBar(
        title: Text('Floating Pullup Card Demo'),
      ),
      body: Stack(
        children: [
          Positioned(
            bottom: 0,
            left: 0,
            right: 0,
            child: FloatingPullupCard(
              card: Container(
                color: Colors.white,
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text('这是一个悬浮上拉卡片'),
                      SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: () => Navigator.pop(context),
                        child: Text('关闭'),
                      ),
                    ],
                  ),
                ),
              ),
              pullupHeight: screenHeight * 0.6, // 上拉后的高度
              isPulledUp: _isPulledUp,
              animationValue: _controller.value,
              onPullUp: () => _pullUp(),
            ),
          ),
          Positioned(
            bottom: 20,
            left: (screenWidth - 56) / 2,
            child: FloatingActionButton(
              onPressed: () => _pullUp(),
              tooltip: '上拉卡片',
              child: Icon(Icons.expand_more),
            ),
          ),
        ],
      ),
    );
  }
}

代码解释:

  1. 依赖导入:在 pubspec.yaml 中添加 floating_pullup_card 依赖。
  2. UI 搭建
    • 使用 Scaffold 作为基本布局。
    • Stack 中放置一个 PositionedFloatingPullupCard 组件。
    • 提供一个 FloatingActionButton 来触发上拉动作。
  3. 状态管理
    • 使用 StatefulWidgetAnimationController 来管理卡片的上拉和下拉状态。
    • _pullUp 方法切换 _isPulledUp 状态,并触发动画。
  4. 卡片内容
    • FloatingPullupCardcard 属性定义卡片的内容。
    • pullupHeight 属性定义卡片上拉后的高度。
    • isPulledUpanimationValue 属性分别控制卡片的状态和动画。
    • onPullUp 属性定义上拉动作的回调。

这个示例展示了如何使用 floating_pullup_card 插件来创建一个悬浮上拉卡片效果,并在用户点击按钮时触发上拉动作。你可以根据需要进一步自定义卡片的内容和动画效果。

回到顶部