Flutter引导页插件introduction_screen的使用

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

Flutter引导页插件introduction_screen的使用

introduction_screen 是一个用于在应用程序首次启动时展示介绍页面的Flutter插件,允许你向用户解释你的应用。这个插件设计精美且高度可定制。

安装

要使用 introduction_screen 插件,你需要将其添加到项目的 pubspec.yaml 文件中作为依赖项:

dependencies:
  introduction_screen: ^3.1.14

示例代码

下面是一个完整的示例,展示了如何使用 introduction_screen 创建一个带有多个页面的引导页,并且包含了跳过、下一步和完成按钮的功能。

主程序入口

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

void main() => runApp(const App());

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

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle.dark.copyWith(statusBarColor: Colors.transparent),
    );

    return MaterialApp(
      title: 'Introduction screen',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: const OnBoardingPage(),
    );
  }
}

引导页实现

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

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

class OnBoardingPageState extends State<OnBoardingPage> {
  final introKey = GlobalKey<IntroductionScreenState>();

  void _onIntroEnd(context) {
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const HomePage()),
    );
  }

  Widget _buildFullscreenImage() {
    return Image.asset(
      'assets/fullscreen.jpg',
      fit: BoxFit.cover,
      height: double.infinity,
      width: double.infinity,
      alignment: Alignment.center,
    );
  }

  Widget _buildImage(String assetName, [double width = 350]) {
    return Image.asset('assets/$assetName', width: width);
  }

  @override
  Widget build(BuildContext context) {
    const bodyStyle = TextStyle(fontSize: 19.0);

    const pageDecoration = PageDecoration(
      titleTextStyle: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w700),
      bodyTextStyle: bodyStyle,
      bodyPadding: EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0),
      pageColor: Colors.white,
      imagePadding: EdgeInsets.zero,
    );

    return IntroductionScreen(
      key: introKey,
      globalBackgroundColor: Colors.white,
      allowImplicitScrolling: true,
      autoScrollDuration: 3000,
      infiniteAutoScroll: true,
      globalHeader: Align(
        alignment: Alignment.topRight,
        child: SafeArea(
          child: Padding(
            padding: const EdgeInsets.only(top: 16, right: 16),
            child: _buildImage('flutter.png', 100),
          ),
        ),
      ),
      globalFooter: SizedBox(
        width: double.infinity,
        height: 60,
        child: ElevatedButton(
          child: const Text(
            'Let\'s go right away!',
            style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
          ),
          onPressed: () => _onIntroEnd(context),
        ),
      ),
      pages: [
        PageViewModel(
          title: "Fractional shares",
          body:
              "Instead of having to buy an entire share, invest any amount you want.",
          image: _buildImage('img1.jpg'),
          decoration: pageDecoration,
        ),
        PageViewModel(
          title: "Learn as you go",
          body:
              "Download the Stockpile app and master the market with our mini-lesson.",
          image: _buildImage('img2.jpg'),
          decoration: pageDecoration,
        ),
        PageViewModel(
          title: "Kids and teens",
          body:
              "Kids and teens can track their stocks 24/7 and place trades that you approve.",
          image: _buildImage('img3.jpg'),
          decoration: pageDecoration,
        ),
        PageViewModel(
          title: "Full Screen Page",
          body:
              "Pages can be full screen as well.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc id euismod lectus, non tempor felis. Nam rutrum rhoncus est ac venenatis.",
          image: _buildFullscreenImage(),
          decoration: pageDecoration.copyWith(
            contentMargin: const EdgeInsets.symmetric(horizontal: 16),
            fullScreen: true,
            bodyFlex: 2,
            imageFlex: 3,
            safeArea: 100,
          ),
        ),
        PageViewModel(
          title: "Another title page",
          body: "Another beautiful body text for this example onboarding",
          image: _buildImage('img2.jpg'),
          footer: ElevatedButton(
            onPressed: () {
              introKey.currentState?.animateScroll(0);
            },
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.lightBlue,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8.0),
              ),
            ),
            child: const Text(
              'FooButton',
              style: TextStyle(color: Colors.white),
            ),
          ),
          decoration: pageDecoration.copyWith(
            bodyFlex: 6,
            imageFlex: 6,
            safeArea: 80,
          ),
        ),
        PageViewModel(
          title: "Title of last page - reversed",
          bodyWidget: const Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text("Click on ", style: bodyStyle),
              Icon(Icons.edit),
              Text(" to edit a post", style: bodyStyle),
            ],
          ),
          decoration: pageDecoration.copyWith(
            bodyFlex: 2,
            imageFlex: 4,
            bodyAlignment: Alignment.bottomCenter,
            imageAlignment: Alignment.topCenter,
          ),
          image: _buildImage('img1.jpg'),
          reverse: true,
        ),
      ],
      onDone: () => _onIntroEnd(context),
      onSkip: () => _onIntroEnd(context), // You can override onSkip callback
      showSkipButton: true,
      skipOrBackFlex: 0,
      nextFlex: 0,
      showBackButton: false,
      back: const Icon(Icons.arrow_back),
      skip: const Text('Skip', style: TextStyle(fontWeight: FontWeight.w600)),
      next: const Icon(Icons.arrow_forward),
      done: const Text('Done', style: TextStyle(fontWeight: FontWeight.w600)),
      curve: Curves.fastLinearToSlowEaseIn,
      controlsMargin: const EdgeInsets.all(16),
      controlsPadding: kIsWeb
          ? const EdgeInsets.all(12.0)
          : const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
      dotsDecorator: const DotsDecorator(
        size: Size(10.0, 10.0),
        color: Color(0xFFBDBDBD),
        activeSize: Size(22.0, 10.0),
        activeShape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(25.0)),
        ),
      ),
      dotsContainerDecorator: const ShapeDecoration(
        color: Colors.black87,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(8.0)),
        ),
      ),
    );
  }
}

主页实现

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

  void _onBackToIntro(context) {
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const OnBoardingPage()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text("This is the screen after Introduction"),
            const SizedBox(height: 16.0),
            ElevatedButton(
              onPressed: () => _onBackToIntro(context),
              child: const Text('Back to Introduction'),
            ),
          ],
        ),
      ),
    );
  }
}

参数列表

IntroductionScreen 参数

  • pages: 需要显示的页面列表。
  • showNextButton: 是否显示“下一步”按钮,默认为 true
  • showDoneButton: 是否显示“完成”按钮,默认为 true
  • showSkipButton: 是否显示“跳过”按钮,默认为 false
  • showBackButton: 是否显示“返回”按钮,默认为 false
  • done: “完成”按钮的文本或小部件。
  • skip: “跳过”按钮的文本或小部件。
  • next: “下一步”按钮的文本或小部件。
  • back: “返回”按钮的文本或小部件。
  • onDone: 点击“完成”按钮时的回调函数。
  • onSkip: 点击“跳过”按钮时的回调函数。
  • onChange: 页面切换时的回调函数。
  • dotsDecorator: 自定义点指示器的样式。
  • dotsContainerDecorator: 自定义点容器的样式。
  • globalBackgroundColor: 全局背景颜色。
  • baseBtnStyle: 按钮的基础样式。
  • skipStyle: “跳过”按钮的样式。
  • nextStyle: “下一步”按钮的样式。
  • doneStyle: “完成”按钮的样式。
  • backStyle: “返回”按钮的样式。

PageViewModel 参数

  • title: 页面标题。
  • body: 页面正文。
  • image: 页面图片。
  • footer: 页面底部的小部件。
  • decoration: 页面装饰。
  • reverse: 是否反转图像和内容的位置,默认为 false
  • useScrollView: 是否使用 ScrollView,默认为 true
  • scrollViewKeyboardDismissBehavior: 键盘行为,默认为 manual

通过这些参数,你可以轻松创建一个功能丰富且美观的引导页。


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

1 回复

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


当然,以下是如何在Flutter项目中使用introduction_screen插件来创建引导页的示例代码。introduction_screen插件允许你轻松地创建漂亮的引导页(或欢迎页)来介绍你的应用功能。

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

dependencies:
  flutter:
    sdk: flutter
  introduction_screen: ^2.1.0  # 请确保使用最新版本

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

接下来,你可以在你的Flutter应用中创建一个引导页。以下是一个完整的示例,包括主页面和引导页的配置:

import 'package:flutter/material.dart';
import 'package:introduction_screen/introduction_screen.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(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  bool _showIntroduction = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo'),
      ),
      body: _showIntroduction
          ? _buildIntroductionScreen()
          : Center(child: Text('Welcome to the app!')),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // You can add logic to show introduction again if needed
          // setState(() => _showIntroduction = true);
        },
        tooltip: 'Show Introduction',
        child: Icon(Icons.info),
      ),
    );
  }

  Widget _buildIntroductionScreen() {
    return IntroductionScreen(
      pages: [
        IntroductionPage(
          title: "Welcome!",
          imageUrl: "assets/images/welcome.png",  // 确保你有这个图片资源
          description: "Thank you for downloading our app!",
        ),
        IntroductionPage(
          title: "Feature 1",
          imageUrl: "assets/images/feature1.png",
          description: "This is the first amazing feature!",
          footer: Footer(
            title: "GET STARTED",
            backgroundColor: Colors.blue,
            elevation: 10.0,
            onPress: () {
              // Handle button press
              Navigator.of(context).pop(); // 假设点击后关闭引导页
            },
          ),
        ),
        IntroductionPage(
          title: "Feature 2",
          imageUrl: "assets/images/feature2.png",
          description: "This is the second amazing feature!",
        ),
        // 可以添加更多页面
      ],
      showSkipButton: true,
      skip: Text('Skip'),
      next: Text('Next'),
      done: Text('Done'),
      onDone: () {
        // 当引导页完成时执行的逻辑
        setState(() => _showIntroduction = false);
      },
      onSkip: () {
        // 当用户点击跳过按钮时执行的逻辑
        setState(() => _showIntroduction = false);
      },
      globalBackgroundColor: Colors.white,
      dotsDecorator: DotsDecorator(
        size: const_space_16,
        activeSize: const_space_22,
        activeColor: Colors.deepOrange,
        spacing: const_space_16,
        activeShape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12.5),
        ),
      ),
    );
  }
}

// 常量定义,可以根据需要调整
const double const_space_16 = 16.0;
const double const_space_22 = 22.0;

在这个示例中:

  1. 我们首先导入了必要的包,包括introduction_screen
  2. MyApp类中,我们设置了基本的MaterialApp结构。
  3. MyHomePage是一个有状态的组件,用于管理是否显示引导页。
  4. _buildIntroductionScreen方法构建引导页,包括多个IntroductionPage
  5. 我们定义了引导页的标题、图片、描述和页脚按钮。
  6. onDoneonSkip回调用于处理用户完成引导页或跳过引导页时的逻辑。

确保将示例中的图片资源路径替换为你实际项目中的路径。运行这个示例,你将看到一个引导页序列,用户可以通过点击“Next”按钮导航,或者点击“Skip”按钮跳过。完成所有页面后,用户将看到应用的主页。

回到顶部