Search code examples
androiduser-interfaceflutterdartuser-experience

How to make opaque tutorial screen in flutter?


I want to make tutorial screen that show to user at beginning. it's like below :

enter image description here

my specific question, how to make some certain elements will show normally and other are opaque ?

also the arrow and text, how to make them point perfectly based on mobile device screen size (mobile responsiveness) ?


Solution

  • As RoyalGriffin mentioned, you can use highlighter_coachmark library, and I am also aware of the error you are getting, the error is there because you are using RangeSlider class which is imported from 2 different packages. Can you try this example in your app and check if it is working?

    1. Add highlighter_coachmark to your pubspec.yaml file

      dependencies:
        flutter:
          sdk: flutter
      
        highlighter_coachmark: ^0.0.3
      
    2. Run flutter packages get


    Example:

    import 'package:highlighter_coachmark/highlighter_coachmark.dart';
    
    void main() => runApp(MaterialApp(home: HomePage()));
    
    class HomePage extends StatefulWidget {
      @override
      State<HomePage> createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      GlobalKey _fabKey = GlobalObjectKey("fab"); // used by FAB
      GlobalKey _buttonKey = GlobalObjectKey("button"); // used by RaisedButton
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            key: _fabKey, // setting key
            onPressed: null,
            child: Icon(Icons.add),
          ),
          body: Center(
            child: RaisedButton(
              key: _buttonKey, // setting key
              onPressed: showFAB,
              child: Text("RaisedButton"),
            ),
          ),
        );
      }
    
      // we trigger this method on RaisedButton click
      void showFAB() {
        CoachMark coachMarkFAB = CoachMark();
        RenderBox target = _fabKey.currentContext.findRenderObject();
    
        // you can change the shape of the mark
        Rect markRect = target.localToGlobal(Offset.zero) & target.size;
        markRect = Rect.fromCircle(center: markRect.center, radius: markRect.longestSide * 0.6);
    
        coachMarkFAB.show(
          targetContext: _fabKey.currentContext,
          markRect: markRect,
          children: [
            Center(
              child: Text(
                "This is called\nFloatingActionButton",
                style: const TextStyle(
                  fontSize: 24.0,
                  fontStyle: FontStyle.italic,
                  color: Colors.white,
                ),
              ),
            )
          ],
          duration: null, // we don't want to dismiss this mark automatically so we are passing null
          // when this mark is closed, after 1s we show mark on RaisedButton
          onClose: () => Timer(Duration(seconds: 1), () => showButton()),
        );
      }
    
      // this is triggered once first mark is dismissed
      void showButton() {
        CoachMark coachMarkTile = CoachMark();
        RenderBox target = _buttonKey.currentContext.findRenderObject();
    
        Rect markRect = target.localToGlobal(Offset.zero) & target.size;
        markRect = markRect.inflate(5.0);
    
        coachMarkTile.show(
          targetContext: _fabKey.currentContext,
          markRect: markRect,
          markShape: BoxShape.rectangle,
          children: [
            Positioned(
              top: markRect.bottom + 15.0,
              right: 5.0,
              child: Text(
                "And this is a RaisedButton",
                style: const TextStyle(
                  fontSize: 24.0,
                  fontStyle: FontStyle.italic,
                  color: Colors.white,
                ),
              ),
            )
          ],
          duration: Duration(seconds: 5), // this effect will only last for 5s
        );
      }
    }
    

    Output:

    enter image description here