Flutter滑动完成任务插件swipe_to_complete的使用

Flutter滑动完成任务插件swipe_to_complete的使用

swipe_to_complete 是一个Flutter插件,它可以帮助你轻松地在应用中实现滑动确认操作。该插件提供了两种滑动方向:水平和垂直。用户需要根据选择的方向拖动操作按钮来触发回调函数。

插件演示

Video

开始使用

  1. 确定使用的类型
    你需要先确定是使用水平滑动还是垂直滑动。可以通过 SwiperType 枚举来选择:

    enum SwiperType {
      horizontal,  // 水平滑动
      vertical;    // 垂直滑动
    }
    
  2. 使用 NewSwiper 小部件
    NewSwiper 是该插件的核心小部件,用于实现滑动确认操作。你可以通过以下方式使用它:

    NewSwiper({
      Key? key,
      SwiperType type = SwiperType.horizontal,  // 默认为水平滑动
      required FutureOr<void> Function() callback,  // 滑动完成后的回调函数
    })
    

完整示例Demo

下面是一个完整的示例代码,展示了如何在Flutter应用中使用 swipe_to_complete 插件。该示例包括两个页面:一个用于水平滑动,另一个用于垂直滑动。

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Swipe Action Demo'),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Swipe Action Widget offers two types of Call to Actions',
            ),
          ],
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          ElevatedButton(
            onPressed: () => Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => const SeabornSunrisePage(),
              ),
            ),
            child: const Text('Horizontal CTA'),  // 水平滑动按钮
          ),
          const SizedBox(height: 10),
          ElevatedButton(
            onPressed: () => Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => const EasternSunrisePage(),
              ),
            ),
            child: const Text('Vertical CTA'),  // 垂直滑动按钮
          ),
        ],
      ),
    );
  }
}

// 水平滑动页面
class SeabornSunrisePage extends StatefulWidget {
  const SeabornSunrisePage({super.key});

  [@override](/user/override)
  State<SeabornSunrisePage> createState() => _SeabornSunrisePageState();
}

class _SeabornSunrisePageState extends State<SeabornSunrisePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _opacity;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 300));
    _opacity = Tween<double>(begin: 0, end: 0.65).animate(_controller);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          SingleChildScrollView(
            child: Column(
              children: [
                Stack(
                  children: [
                    Container(
                      clipBehavior: Clip.hardEdge,
                      decoration: const BoxDecoration(
                        borderRadius: BorderRadius.vertical(
                          bottom: Radius.circular(42),
                        ),
                      ),
                      child: Image.asset('assets/ocean.png'),  // 背景图片
                    ),
                    const Positioned(
                      left: 24,
                      bottom: 36,
                      child: Text(
                        'Seaborn Sunrise Cruise',  // 标题
                        style: TextStyle(
                          fontSize: 24,
                          color: Colors.white,
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                const DetailsRow(dkey: 'Boarding', value: '21 July 2023, 09:00hrs'),  // 详细信息行
                const DetailsRow(dkey: 'Nos.', value: '2 PAX'),
                const DetailsRow(dkey: 'Seats', value: 'EA22, EA23'),
                const SizedBox(height: 12),
                Builder(builder: (context) {
                  return NewSwiper(
                    type: SwiperType.horizontal,  // 水平滑动
                    callback: () => showBottomSheet(
                      context: context,
                      builder: (context) {
                        return BottomSheetContent(
                          controller: _controller,
                        );
                      },
                    ),
                  );
                }),
              ],
            ),
          ),
          SizedBox(
            height: 650,
            child: AnimatedBuilder(
              animation: _controller,
              builder: (context, child) => Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter,
                    stops: const [0, 100],
                    colors: [
                      Colors.black.withOpacity(_opacity.value),
                      Colors.transparent
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 垂直滑动页面
class EasternSunrisePage extends StatefulWidget {
  const EasternSunrisePage({super.key});

  [@override](/user/override)
  State<EasternSunrisePage> createState() => _EasternSunrisePageState();
}

class _EasternSunrisePageState extends State<EasternSunrisePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _opacity;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 300));
    _opacity = Tween<double>(begin: 0, end: 0.65).animate(_controller);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Column(
            children: [
              Stack(
                children: [
                  Container(
                    height: 500,
                    width: MediaQuery.of(context).size.width,
                    clipBehavior: Clip.hardEdge,
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.vertical(
                        bottom: Radius.circular(42),
                      ),
                    ),
                    child: Image.asset(
                      'assets/balloon.png',  // 背景图片
                      fit: BoxFit.cover,
                    ),
                  ),
                  Positioned(
                    left: 0,
                    bottom: 0,
                    child: Container(
                      height: 100,
                      width: MediaQuery.of(context).size.width,
                      decoration: BoxDecoration(
                        color: Colors.black.withOpacity(0.6),
                        borderRadius: const BorderRadius.vertical(
                          bottom: Radius.circular(42),
                        ),
                      ),
                      child: const Padding(
                        padding: EdgeInsets.only(left: 24),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Text(
                              'Eastern Sunrise Experience',  // 标题
                              style: TextStyle(
                                fontSize: 24,
                                color: Colors.white,
                                fontWeight: FontWeight.w300,
                              ),
                            ),
                            Text(
                              '21 July 2023, 09:00 hrs',  // 详细信息
                              style: TextStyle(
                                fontSize: 16,
                                color: Colors.white,
                                fontWeight: FontWeight.w300,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 10),
              Builder(
                builder: (context) {
                  return NewSwiper(
                    type: SwiperType.vertical,  // 垂直滑动
                    callback: () => showBottomSheet(
                      context: context,
                      builder: (context) {
                        return BottomSheetContent(
                          controller: _controller,
                        );
                      },
                    ),
                  );
                },
              ),
            ],
          ),
          SizedBox(
            height: 500,
            child: AnimatedBuilder(
              animation: _controller,
              builder: (context, child) => Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter,
                    stops: const [0, 100],
                    colors: [
                      Colors.black.withOpacity(_opacity.value),
                      Colors.transparent
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 底部弹出内容
class BottomSheetContent extends StatefulWidget {
  const BottomSheetContent({super.key, required this.controller});

  final AnimationController controller;

  [@override](/user/override)
  State<BottomSheetContent> createState() => _BottomSheetContentState();
}

class _BottomSheetContentState extends State<BottomSheetContent> {
  [@override](/user/override)
  void initState() {
    super.initState();

    widget.controller.forward();  // 动画开始
  }

  [@override](/user/override)
  void dispose() {
    widget.controller.reverse();  // 动画结束
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      width: MediaQuery.of(context).size.width,
      decoration: const BoxDecoration(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      child: const Center(
        child: Icon(
          Icons.check_circle,  // 确认图标
          color: Colors.black,
        ),
      ),
    );
  }
}

// 详细信息行
class DetailsRow extends StatelessWidget {
  const DetailsRow({super.key, required this.dkey, required this.value});

  final String dkey;
  final String value;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        mainAxisSize: MainAxisSize.max,
        children: [
          Text(
            dkey,
            style: detailsFontStyle,  // 自定义字体样式
          ),
          Text(
            value,
            style: detailsFontStyle.copyWith(
              fontWeight: FontWeight.normal,
            ),
          ),
        ],
      ),
    );
  }
}

const detailsFontStyle = TextStyle(
  color: Color(0xff373737),
  fontSize: 16,
  fontWeight: FontWeight.w300,
);

更多关于Flutter滑动完成任务插件swipe_to_complete的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter滑动完成任务插件swipe_to_complete的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用swipe_to_complete插件的一个简单示例。这个插件允许你通过滑动操作来完成某个任务。以下代码将展示如何集成和使用该插件。

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

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

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

接下来,你可以在你的Flutter应用中实现滑动完成任务的功能。以下是一个简单的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Swipe to Complete Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Swipe to Complete Demo'),
        ),
        body: SwipeToCompleteList(
          items: List.generate(
            20,
            (index) => 'Item $index',
          ),
          onCompleted: (index) {
            print('Item $index completed');
            // 你可以在这里添加完成任务后的逻辑,比如更新状态等
          },
          itemBuilder: (context, index, item) {
            return ListTile(
              title: Text(item),
            );
          },
        ),
      ),
    );
  }
}

class SwipeToCompleteList extends StatefulWidget {
  final List<String> items;
  final Function(int index) onCompleted;
  final Widget Function(BuildContext context, int index, String item) itemBuilder;

  SwipeToCompleteList({
    required this.items,
    required this.onCompleted,
    required this.itemBuilder,
  });

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

class _SwipeToCompleteListState extends State<SwipeToCompleteList> {
  final List<bool> _isCompleted = List.filled(widget.items.length, false);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: widget.items.length,
      itemBuilder: (context, index) {
        return SwipeToComplete(
          key: ValueKey('item_$index'),
          isCompleted: _isCompleted[index],
          onSwipe: () {
            setState(() {
              _isCompleted[index] = !_isCompleted[index];
              if (_isCompleted[index]) {
                widget.onCompleted(index);
              }
            });
          },
          child: widget.itemBuilder(context, index, widget.items[index]),
        );
      },
    );
  }
}

在这个示例中:

  1. SwipeToCompleteList是一个自定义的StatefulWidget,它接受一个字符串列表items,一个完成任务时的回调onCompleted,以及一个用于构建列表项的itemBuilder
  2. _SwipeToCompleteListStatebuild方法中,我们使用ListView.builder来构建列表。
  3. 对于每个列表项,我们使用SwipeToComplete包裹itemBuilder返回的Widget。SwipeToComplete接受一个isCompleted标志,以及一个onSwipe回调,当用户滑动完成时,这个回调会被触发。
  4. 当用户滑动完成时,我们更新_isCompleted列表的对应项,并调用widget.onCompleted回调。

请注意,swipe_to_complete插件的实际API可能有所不同,因此你可能需要查阅最新的文档或源代码以获取准确的用法。上述代码是一个基于假设的示例,用于展示如何集成和使用类似功能的插件。

回到顶部