Flutter故事展示插件flutter_story的使用

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

Flutter故事展示插件flutter_story的使用

简介

flutter_story 是一个用于在Flutter应用中创建类似Instagram、WhatsApp、Telegram和Facebook等平台的故事展示功能的插件。它支持多种平台,包括Android、iOS、Linux、macOS、Web和Windows。

特性

  • 支持在故事中添加图片、视频、文本等组件。
  • 支持暂停、播放、下一帧、上一帧以及通过触摸进行拖动操作。
  • 支持自定义底部栏(带有消息框或自定义组件)、点赞按钮和转发按钮。
  • 每个故事卡片都有动画进度指示器。

安装

首先,在pubspec.yaml文件中添加flutter_story依赖:

dependencies:
  flutter_story: ^1.0.1

然后在Dart代码中导入该插件:

import 'package:flutter_story/flutter_story.dart';

使用示例

简单用法

下面是一个简单的使用示例:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Story(
        children: [
          StoryUser(
            avatar: Image.asset("assets/user_avatar.jpg"),
            label: const Text("UserName"),
            children: const [
              StoryCard(
                child: Center(
                  child: Text("This is the story card widget",
                    style: TextStyle(color: Colors.white),),
                ),
              )
            ],
          )
        ],
      ),
    ),
  );
}

自定义用法

您可以根据需要自定义更多属性,例如控制器、自动播放、高度、颜色等:

StoryController storyController = StoryController();

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Story(
            controller: storyController,
            children: [
              StoryUser(
                userId: 1,
                avatar: Image.asset("assets/user_avatar.jpg"),
                label: const Text("UserName"),
                children: [
                  StoryCard(
                    childOverlay: Center(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          ElevatedButton(
                            onPressed: () => storyController.pauseStory(),
                            child: const Text("Pause"),
                          ),
                          ElevatedButton(
                            onPressed: () => storyController.playStory(),
                            child: const Text("Play"),
                          ),
                          ElevatedButton(
                            onPressed: () =>
                                storyController.setStoryCardVisited(
                                    storyIndex: 0,
                                    cardIndex/XMLSchema=0,
                                    visited: true),
                            child: const Text("Set story card visited"),
                          ),
                          ElevatedButton(
                            onPressed: () =>
                                storyController.setStoryCardVisitedByUserId(
                                    userId: 1, cardIndex: 0, visited: true),
                            child: const Text(
                                "Set story card visited by user id"),
                          ),
                          ElevatedButton(
                            onPressed: () => storyController.closeStory(),
                            child: const Text("Close"),
                          ),
                        ],
                      ),
                    ),
                  )
                ],
              )
            ],
          ),
          Center(
            child: Column(
              children: [
                ElevatedButton(
                  onPressed: () => storyController.openStory(context,
                      storyIndex: 0, cardIndex: 0),
                  child: const Text("Open story"),
                ),
                ElevatedButton(
                  onPressed: () => storyController.openStoryByUserId(context,
                      userId: 1, cardIndex: 0),
                  child: const Text("Open story by user id"),
                ),
              ],
            ),
          )
        ],
      ),
    ),
  );
}

更复杂的示例

以下是一个更复杂的示例,展示了如何使用Story.builder方法构建动态故事列表:

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

  @override
  State<StoryExamplePage> createState() => _StoryExamplePageState();
}

class _StoryExamplePageState extends State<StoryExamplePage> {
  StoryController storyController = StoryController();
  late List<StoryModel> stories;

  @override
  void initState() {
    super.initState();
    stories = getStories();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          physics: const BouncingScrollPhysics(),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Story.builder(
                  controller: storyController,
                  itemCount: stories.length,
                  itemBuilder: (context, index) {
                    StoryModel s = stories[index];
                    return StoryUser(
                      avatar: s.avatar,
                      label: s.label,
                      children: s.cards == null
                          ? []
                          : s.cards!
                              .map((card) => StoryCard(
                                    onVisited: (cardIndex) {
                                      setState(() {
                                        card.visited = true;
                                      });
                                    },
                                    footer: StoryCardFooter(
                                      messageBox: StoryCardMessageBox(
                                        child: Center(
                                          child: SizedBox(
                                            width: MediaQuery.of(context)
                                                    .size
                                                    .width /
                                                1.5,
                                            height: MediaQuery.of(context)
                                                    .size
                                                    .width /
                                                1.5,
                                            child: Column(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.center,
                                              children: [
                                                Row(
                                                  mainAxisAlignment:
                                                      MainAxisAlignment
                                                          .spaceAround,
                                                  children: [
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "😂",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "😮",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "😍",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                  ],
                                                ),
                                                const SizedBox(height: 30),
                                                Row(
                                                  mainAxisAlignment:
                                                      MainAxisAlignment
                                                          .spaceAround,
                                                  children: [
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "😢",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "👏",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                    MaterialButton(
                                                      minWidth: 0,
                                                      padding: EdgeInsets.zero,
                                                      shape:
                                                          const CircleBorder(),
                                                      child: const Text(
                                                        "🔥",
                                                        style: TextStyle(
                                                            fontSize: 32),
                                                      ),
                                                      onPressed: () {},
                                                    ),
                                                  ],
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      ),
                                      likeButton: StoryCardLikeButton(
                                        onLike: (cardLike) {},
                                      ),
                                      forwardButton: StoryCardForwardButton(
                                        onForward: (cardIndex) {},
                                      ),
                                    ),
                                    color: card.color,
                                    visited: card.visited,
                                    cardDuration: card.duration,
                                    childOverlay: card.childOverlay,
                                    child: card.child,
                                  ))
                              .toList(),
                    );
                  }),
              Container(
                margin: const EdgeInsets.fromLTRB(0, 5, 0, 20),
                decoration: BoxDecoration(
                  border: Border(
                    top: BorderSide(width: 1, color: Colors.grey.withAlpha(50)),
                  ),
                ),
                child: Column(
                  children: [
                    getPost(
                        name: "Benjamin",
                        avatar: "assets/avatar1.jpg",
                        image: "assets/post1.jpg"),
                    getPost(
                        name: "Liam",
                        avatar: "assets/avatar2.jpg",
                        image: "assets/post2.jpg"),
                    getPost(
                        name: "Oliver",
                        avatar: "assets/avatar3.jpg",
                        image: "assets/post3.jpg"),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  List<StoryModel> getStories() {
    List<StoryModel> storyList = [];
    for (int i = 1; i <= 10; i++) {
      storyList.add(StoryModel(
          id: i + 2,
          avatar: Image.asset("assets/avatar$i.jpg"),
          label: Text(
            userLabel(i),
            style: const TextStyle(color: Colors.black),
          ),
          cards: [
            storyCard1(i),
            storyCard2(i),
          ]));
    }
    return storyList;
  }

  // 其他辅助函数和类定义...
}

总结

flutter_story插件为Flutter应用提供了强大的故事展示功能,支持多种自定义选项和丰富的交互体验。通过上述示例代码,您可以快速集成并定制适合您应用需求的故事展示功能。


这段Markdown文档详细介绍了如何安装和使用`flutter_story`插件,并提供了完整的示例代码供参考。希望这对您有所帮助!

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用flutter_story插件来展示故事的代码示例。假设你已经有一个Flutter项目,并且已经添加了flutter_story依赖到你的pubspec.yaml文件中。

首先,确保在pubspec.yaml中添加依赖:

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

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

接下来,在你的Flutter项目中创建一个页面来展示故事。这里有一个简单的示例:

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

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

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

class StoryScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Story Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: StoryWidget(
          stories: [
            StoryPage(
              imageProvider: NetworkImage('https://example.com/story1.jpg'),
              caption: Text('This is the first page of the story.'),
            ),
            StoryPage(
              imageProvider: NetworkImage('https://example.com/story2.jpg'),
              caption: Text('This is the second page of the story.'),
            ),
            StoryPage(
              imageProvider: NetworkImage('https://example.com/story3.jpg'),
              caption: Text('This is the third page of the story.'),
            ),
          ],
          onCompleted: () {
            // 当故事展示完成时执行的回调
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('Story completed!'),
              ),
            );
          },
        ),
      ),
    );
  }
}

class StoryPage extends StatelessWidget {
  final ImageProvider imageProvider;
  final Widget caption;

  const StoryPage({Key? key, required this.imageProvider, required this.caption})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Expanded(
          child: Image(
            image: imageProvider,
            fit: BoxFit.cover,
          ),
        ),
        SizedBox(height: 20),
        caption,
      ],
    );
  }
}

在上面的代码中,我们创建了一个StoryScreen页面,它包含一个StoryWidget,该小部件接受一个stories列表,每个故事页面都是一个StoryPage对象。StoryPage对象包含一个图片和一个标题(caption)。

请注意,上面的StoryWidgetStoryPage并不是flutter_story插件实际提供的组件,因为flutter_story插件的具体API可能会有所不同。这个示例旨在展示如何组织一个故事展示页面的基本结构。

然而,由于flutter_story插件的API可能会有所不同,你可能需要查阅其官方文档或示例代码来了解如何正确使用该插件。假设flutter_story插件提供了一个类似功能的组件,你可能需要按照如下方式使用:

// 假设flutter_story插件提供了StoryViewer组件
import 'package:flutter_story/flutter_story.dart' as story;

// ...

child: story.StoryViewer(
  stories: [
    story.StoryPage(
      imageUrl: 'https://example.com/story1.jpg',
      caption: 'This is the first page of the story.',
    ),
    // ... 其他页面
  ],
  onCompleted: () {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Story completed!'),
      ),
    );
  },
),

请注意,上面的story.StoryViewerstory.StoryPage是假设的API,你需要根据flutter_story插件的实际文档进行调整。

为了获得最准确的信息,请查阅flutter_story插件的官方文档和示例代码。

回到顶部