Code Monkey home page Code Monkey logo

flutter_intro's People

Contributors

hellohejinyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

flutter_intro's Issues

An issue when using Intro on ExpansionPanelRadioList

Hello,

Thank you for your awesome project. But I found a problem that if you use it in an ExpansionPanelRadioList, it will repeat some steps after one of the expansion panel expanded.

For example, you setup an intro step 100 for one of the expansion panel's headerBuilder, and intro step 101, 102 for other components in the page.

At step 101, I expanded the panel in the buttonTextBuilder, the step will be 100 again.

Normally, the order should be 100, 101, 102. But due to the problem, the order became 100, 101, 100, 102

I guess the problem is because of the rebuild of the panel. I decide whether to add an intro step temporarily to solve this problem by observing if the panel is expanded.

OverlayBuilder 中StepWidgetParams的onNext跟onPrev为null

StepWidgetParams(
group: introStepBuilder.group,
order: introStepBuilder.order,
onNext: hasNextStep ? _render : null,
onPrev: hasPrevStep
? () {
_render(reverse: true);
}
: null,
onFinish: _onFinish,
screenSize: _screenSize,
size: _widgetSize,
offset: _widgetOffset,
),
在有下一步的情况下自定义OverlayBuilder使用不了onNext、onPrev方法,经测试hasNextStep、hasPrevStep判断有误

Available on windows desktop ?

Hi, I'm trying to use this package as a desktop application, but I couldn't get it to work. However, I ran it in the mobile application. Then I saw that there is no web support in flutter 3, I wonder if it is not available for desktop applications at the moment?

如果一次性使用?

第一次进去 App,需要使用框架介绍,后续就不用介绍,目前能实现这个功能吗?

StatelessWidget and Statefulwidget

Can this work in stateless widget ? Or only stateful?
I have this error :
E/flutter ( 7192): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FlutterIntroException: The context does not contain an Intro widget.
E/flutter ( 7192): #0 Intro.of (package:flutter_intro/flutter_intro.dart:389:7)
E/flutter ( 7192): #1 _IntroStepBuilderState.initState. (package:flutter_intro/intro_step_builder.dart:60:34)
E/flutter ( 7192): #2 new Future.delayed. (dart:async/future.dart:427:39)
E/flutter ( 7192): #3 Timer._createTimer. (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 7192): #4 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter ( 7192): #5 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter ( 7192): #6 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
E/flutter ( 7192):

Can't work with tabview with floating action button

hi, when I start to run this page with 3 tabs and has it's floating action button(FAB), and I want to intro each FAB when tab was changed.
But I found when I press FAB to start intro, only tab 1 will show intro effect.
Then switch to tab 2 or tab 3, the FAB not display intro effect.

Below is my sample code, please help me.
Thank you very much.

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'My App',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: Intro(
          padding: EdgeInsets.zero,
          borderRadius: const BorderRadius.all(Radius.circular(4)),
          maskColor: const Color.fromRGBO(0, 0, 0, .6),
          child: const MyHomePage(title: 'Flutter Demo Home Page'),
        ));
  }
}

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

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;
  List tabs = ["Tab1", "Tab2", "Tab3"];
  int _tabIndex = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: tabs.length, vsync: this);

    _tabController.addListener(() {
      var index = _tabController.index;
      switch (index) {
        case 0:
          setState(() {
            _tabIndex = 0;
          });
          break;
        case 1:
          setState(() {
            _tabIndex = 1;
          });
          break;
        case 2:
          setState(() {
            _tabIndex = 2;
          });
          break;
        default:
          break;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("App Name"),
        bottom: TabBar(
          controller: _tabController,
          tabs: tabs.map((e) => Tab(text: e)).toList(),
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: tabs.map((e) {
          return KeepAliveWrapper(
            child: Container(
              alignment: Alignment.center,
              child: Text(e, textScaleFactor: 5),
            ),
          );
        }).toList(),
      ),
      floatingActionButton: _buildFab(),
    );
  }

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

  Widget _buildFab() {
    return IntroStepBuilder(
      order: 1,
      group: _getGroupName(),
      text: 'page: $_tabIndex',
      builder: (context, key) => FloatingActionButton(
          key: key,
          backgroundColor: _getBgColor(),
          onPressed: () {
            Intro.of(context).start(group: _getGroupName());
          },
          child: Icon(_getIconData(), color: Colors.white, size: 25)),
    );
  }

  String _getGroupName() {
    String name = 'group$_tabIndex';
    print('group name:$name');
    return name;
  }

  Color _getBgColor() {
    switch (_tabIndex) {
      case 0:
        return Colors.green;
      case 1:
        return Colors.red;
      case 2:
        return Colors.blue;
      default:
        return Colors.black;
    }
  }

  IconData _getIconData() {
    switch (_tabIndex) {
      case 0:
        return Icons.add;
      case 1:
        return Icons.access_time;
      case 2:
        return Icons.add_a_photo;
      default:
        return Icons.abc_sharp;
    }
  }
}

How to use IntroStepBuilder in ListTile?

Great package!, but I have one issue, how to use this package to ListTile?, specifically I want to use the IntroStepBuilder in the index 0 of my ListTile, is it possible?

Issue with Library on Android Web - Introstep Highlighting and Background Darkening Not Working

Hi,
I am encountering an issue when using the library on Android Web. When running the application on a web browser on an Android phone, the introstep feature does not work as expected. The element is not highlighted, and the background is not darkened, making the text unreadable. Interestingly, the issue seems to be specific to Android devices, as it works flawlessly on other platforms. Screenshots from an iPhone 12 Pro show the correct behavior, while those from a Pixel 6 do not.

Zrzut ekranu 2024-01-11 161430 Zrzut ekranu 2024-01-11 161450

[bug] Closing the page will cause this package to fail

hi,
I used IntroStepBuilder in different pages of my app. And in order to explain all my pages, I need to move through the pages with Get.to( ()=> NewPage()) like:

IntroStepBuilder(
        order: 15,
        overlayBuilder: (StepWidgetParams params) => IntroWidget( //my custom card intro widget
          introText[14],
          params,
          previousCallBack: () async{ //when client click on previous button
               Get.back();
               await Future.delayed(Duration(seconds: 1));
               params.onPrev!();
          }
          nextCallBack: () async { //when client click on next button
             Get.to( ()=> NewPage());
             await Future.delayed(Duration(milliseconds: 1000));
             params.onNext!();
          },
        ),
        builder: (context, key) => Container(
          key: key,
          child: ....
         )
    )

Now I want to close the existing page and go back to the main page and enter another page from there.
The first problem is that you have to delay the code params.onNext!(); run Because the full page is not loaded. I think it should have a listener to load the next IntroStepBuilder whenever the full page is loaded. The next problem is that Get.back(); It causes the code params.onNext!(); have the following error

E/flutter ( 4333): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
E/flutter ( 4333): #0 Element.widget (package:flutter/src/widgets/framework.dart:3474:31)
E/flutter ( 4333): #1 debugCheckHasMediaQuery. (package:flutter/src/widgets/debug.dart:296:17)
E/flutter ( 4333): #2 debugCheckHasMediaQuery (package:flutter/src/widgets/debug.dart:311:4)
E/flutter ( 4333): #3 MediaQuery._of (package:flutter/src/widgets/media_query.dart:1169:12)
E/flutter ( 4333): #4 MediaQuery.of (package:flutter/src/widgets/media_query.dart:1165:12)
E/flutter ( 4333): #5 Intro._render (package:flutter_intro/flutter_intro.dart:199:30)
E/flutter ( 4333): #6 _TargetEditorPageState.build.. (package:habi/app/pages/basePages/targetEditorPage.dart:309:27)
E/flutter ( 4333):

Exception on Tab view with floating action button

hi,
Thank you for your previous reply, but I found another issue with switching tab by pressing tab or slide.
I want to start intro FAB automatically when tab was switched, so I call Intro.of(context).start() in onWidgetLoad() which in FAB.
Then switching tab by pressing tab or sliding with gesture, I will get some exception.
I am using version 3.2.1 of flutter_intro package.
The below is my sample code, please help me.
Thank you very much.

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'My App',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: Intro(
          padding: EdgeInsets.zero,
          borderRadius: const BorderRadius.all(Radius.circular(4)),
          maskColor: const Color.fromRGBO(0, 0, 0, .6),
          child: const MyHomePage(title: 'Flutter Demo Home Page'),
        ));
  }
}

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

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;
  List tabs = ["Tab1", "Tab2", "Tab3"];
  int _tabIndex = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: tabs.length, vsync: this);

    _tabController.addListener(() {
      var index = _tabController.index;
      switch (index) {
        case 0:
          setState(() {
            _tabIndex = 0;
          });
          break;
        case 1:
          setState(() {
            _tabIndex = 1;
          });
          break;
        case 2:
          setState(() {
            _tabIndex = 2;
          });
          break;
        default:
          break;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IntroStepBuilder(
          group: 'group0',
          order: 1,
          text: 'Navigation Menu',
          builder: (context, key) => IconButton(
            key: key,
            onPressed: () {
              // Scaffold.of(context).openDrawer();
            },
            icon: const Icon(Icons.menu),
          ),
        ),
        title: const Text("App Name"),
        bottom: TabBar(
          controller: _tabController,
          tabs: tabs.map((e) => Tab(text: e)).toList(),
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: tabs.map((e) {
          return KeepAliveWrapper(
            child: Container(
              alignment: Alignment.center,
              child: Text(e, textScaleFactor: 5),
            ),
          );
        }).toList(),
      ),
      floatingActionButton: _buildFab(),
    );
  }

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

  Widget _buildFab() {
    return IntroStepBuilder(
      order: 2,
      group: _getGroupName(),
      text: 'page: $_tabIndex',
      onWidgetLoad: () {
        Intro.of(context).start(group: _getGroupName());
      },
      builder: (context, key) => FloatingActionButton(
          key: key,
          backgroundColor: _getBgColor(),
          onPressed: () {
          },
          child: Icon(_getIconData(), color: Colors.white, size: 25)),
    );
  }

  String _getGroupName() {
    String name = 'group$_tabIndex';
    print('group name:$name');
    return name;
  }

  Color _getBgColor() {
    switch (_tabIndex) {
      case 0:
        return Colors.green;
      case 1:
        return Colors.red;
      case 2:
        return Colors.blue;
      default:
        return Colors.black;
    }
  }

  IconData _getIconData() {
    switch (_tabIndex) {
      case 0:
        return Icons.add;
      case 1:
        return Icons.access_time;
      case 2:
        return Icons.add_a_photo;
      default:
        return Icons.abc_sharp;
    }
  }
}

Here is two types exception I got

======== Exception caught by widgets library =======================================================
The following FlutterIntroException was thrown building RotationTransition(listenable: AnimationController#1859d(⏭ 1.000; paused)➩CurveTween(curve: Cubic(0.42, 0.00, 1.00, 1.00))➩Tween<double>(0.875 → 1.0)➩1.0➩TrainHoppingAnimation(next: _AnimationSwap<double>(AnimationController#0fe8e(⏭ 1.000; paused)➩Tween<double>(0.75 → 1.0)➩1.0, AnimationController#0fe8e(⏭ 1.000; paused)➩CurveTween(curve: Threshold)➩1.0➪ReverseAnimation)), state: _AnimatedState#8d1a2):
The current context is null, because there is no widget in the tree that matches this global key. Please check whether the key in IntroStepBuilder(group: group2, order: 2) has forgotten to bind. If you are already bound, it means you have encountered a bug, please let me know.

The relevant error-causing widget was: 
  Scaffold Scaffold:file:///C:/Users/EthanLee/AndroidProject/Sarun/flutter/QVPN/lib/main2.dart:86:12
When the exception was thrown, this was the stack: 
#0      Intro._render (package:flutter_intro/flutter_intro.dart:217:7)
#1      Intro.start (package:flutter_intro/flutter_intro.dart:407:5)
#2      _MyHomePageState._buildFab.<anonymous closure> (package:qvpn/main2.dart:133:27)
#3      _IntroStepBuilderState.didUpdateWidget (package:flutter_intro/intro_step_builder.dart:83:28)
#4      StatefulElement.update (package:flutter/src/widgets/framework.dart:5652:55)
#5      Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#6      SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6765:14)
#7      Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building RotationTransition(listenable: AnimationController#0c617(⏭ 1.000; paused)➩CurveTween(curve: Cubic(0.42, 0.00, 1.00, 1.00))➩Tween<double>(0.875 → 1.0)➩1.0➩TrainHoppingAnimation(next: _AnimationSwap<double>(AnimationController#8b518(⏭ 1.000; paused)➩Tween<double>(0.75 → 1.0)➩1.0, AnimationController#8b518(⏭ 1.000; paused)➩CurveTween(curve: Threshold)➩1.0➪ReverseAnimation)), state: _AnimatedState#bba98):
Null check operator used on a null value

The relevant error-causing widget was: 
  Scaffold Scaffold:file:///C:/Users/EthanLee/AndroidProject/Sarun/flutter/QVPN/lib/main2.dart:86:12
When the exception was thrown, this was the stack: 
#0      _IntroStepBuilderState.didUpdateWidget (package:flutter_intro/intro_step_builder.dart:80:61)
#1      StatefulElement.update (package:flutter/src/widgets/framework.dart:5652:55)
#2      Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#3      SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6765:14)
#4      Element.updateChild (package:flutter/src/widgets/framework.dart:3824:15)
#5      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5505:16)
#6      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5643:11)
#7      Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)

Possible to use with other plugins that wrap the root widget?

There may be an obvious solution to this, but I'm trying to figure out how to use both flutter_intro and catcher, and they both wrap the root widget without returning a widget.

I can't provide Intro() as the rootWidget to Catcher(), and I can't provide Catcher() as the child to Intro(), since neither return a widget.

Does this make them incompatible, or are there any other options to implement Intro without having to remove catcher?

Global Key issue

I am getting Multiple Global Key issues in my app when I try to show 2 or 3 IntroStepBuilder.

How to initialize a second intro sequence on the same page?

Hi,

Thanks for this nice package!

I just wanted to know how to initialize the Intro if we plan to start a second intro sequence (the first being on app launch) on the same Page, only after the user performs an operation or presses a button.

How would both Intro objects differentiate between each other's step order number 1?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.