Only showing the front side when pressing the nextButton of a flash card app using the flip_card dependency [FLUTTER]

259

So here's what I added to my code to make sure every time the user decides to see the next card, it shows the front side of the next card, not the back side:

First I defined a global variable:

  GlobalKey<FlipCardState> cardKey = GlobalKey<FlipCardState>();

then it's passed to the key property of flip_card package:

FlipCard(
          key: cardKey,

Then I use the variable to check the status of card whether the front of card is shown or the back, if the back side is shown then it will be toggled to show the front side of the next card when clicking on the "next card button":

onPressed: () {
            if(cardKey.currentState != null) { //null safety
              if (!cardKey.currentState!.isFront) {
                cardKey.currentState!.toggleCard();
              }
            }
            
          },

Adding to the onPressed property of the "next card" button.

Share:
259
Admin
Author by

Admin

Updated on December 11, 2022

Comments

  • Admin
    Admin over 1 year

    I have a flashcard app using flutter in android studio, I am very new at android studio and flutter. So every time the user flips, it shows the back side of the card. If the card is showing the back side while the user is pressing the next button, the card automatically shows the back side of the proceeding cards. What i wanted to do is only show the front side each time the user presses the next button.

    I have 3 classes, a flip_card.dart [my animations], Flash.dart [buttons, widgets, front/back image lists, etc.], main.dart [main, only calls the class].
    
    I do not know what to do, either call the animation when it is played to a function? or to call a local "bool isFront" inside the animation when it is played. 
    
    this is my whole flip_dart.dart
    
    library flip_card;
    
    import 'dart:math';
    import 'package:flutter/material.dart';
    import 'Flash.dart';
    
    enum FlipDirection {
      VERTICAL,
      HORIZONTAL,
    }
    
    class AnimationCard extends StatelessWidget {
      AnimationCard({this.child, this.animation, this.direction});
    
      final Widget child;
      final Animation<double> animation;
      final FlipDirection direction;
    
      @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
          animation: animation,
          builder: (BuildContext context, Widget child) {
            var transform = Matrix4.identity();
            transform.setEntry(3, 2, 0.001);
            if (direction == FlipDirection.VERTICAL) {
              transform.rotateX(animation.value);
            } else {
              transform.rotateY(animation.value);
            }
            return Transform(
              transform: transform,
              alignment: Alignment.center,
              child: child,
            );
          },
          child: child,
        );
      }
    }
    
    class FlipCard extends StatefulWidget {
      final Widget front;
      final Widget back;
      final int speed = 500;
      final FlipDirection direction;
    
      const FlipCard(
          {Key key,
            @required this.front,
            @required this.back,
            this.direction = FlipDirection.HORIZONTAL})
          : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        return _FlipCardState();
      }
    }
    
    class _FlipCardState extends State<FlipCard>
        with SingleTickerProviderStateMixin {
      AnimationController controller;
      Animation<double> _frontRotation;
      Animation<double> _backRotation;
    
      bool isFront = true;
    
      @override
      void initState() {
        super.initState();
        controller = AnimationController(
            duration: Duration(milliseconds: widget.speed), vsync: this);
        _frontRotation = TweenSequence(
          <TweenSequenceItem<double>>[
            TweenSequenceItem<double>(
              tween: Tween(begin: 0.0, end: pi / 2)
                  .chain(CurveTween(curve: Curves.linear)),
              weight: 50.0,
            ),
            TweenSequenceItem<double>(
              tween: ConstantTween<double>(pi / 2),
              weight: 50.0,
            ),
          ],
        ).animate(controller);
        _backRotation = TweenSequence(
          <TweenSequenceItem<double>>[
            TweenSequenceItem<double>(
              tween: ConstantTween<double>(pi / 2),
              weight: 50.0,
            ),
            TweenSequenceItem<double>(
              tween: Tween(begin: -pi / 2, end: 0.0)
                  .chain(CurveTween(curve: Curves.linear)),
              weight: 50.0,
            ),
          ],
        ).animate(controller);
      }
    
      _toggleCard() {
        if (isFront) {
          controller.forward();
    //      if(_nextImage()){
    //
    //      }
        } else {
          controller.reverse();
        }
        isFront = !isFront;
      }
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: _toggleCard,
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              AnimationCard(
                animation: _frontRotation,
                child: widget.front,
                direction: widget.direction,
              ),
              AnimationCard(
                animation: _backRotation,
                child: widget.back,
                direction: widget.direction,
              ),
            ],
          ),
        );
      }
    
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    }
    
    
    
    And this is my Flash.dart 
    import 'flip_card.dart';
    import 'package:flutter/material.dart';
    
    class Flashcard extends StatefulWidget {
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<Flashcard> {
      int photoIndex = 0;  //startfirstpage
      bool isFront = true;
      var playerProgress = 0;
      List<String> photos = [ //front
    
        'assets/c1v1f.png',
        'assets/c1v2f.png',
        'assets/c1v3f.png',
        'assets/c1v4f.png',
        'assets/c1v5f.png',
        'assets/c1v6f.png',
        'assets/c1v7f.png',
        'assets/c1v8f.png',
        'assets/c1v9f.png',
        'assets/c1v10f.png',
    
      ];
    
      List<String> photos1 = [ //back
    
        'assets/c1v1b.png',
        'assets/c1v2b.png',
        'assets/c1v3b.png',
        'assets/c1v4b.png',
        'assets/c1v5b.png',
        'assets/c1v6b.png',
        'assets/c1v7b.png',
        'assets/c1v8b.png',
        'assets/c1v9b.png',
        'assets/c1v10b.png',
    
      ];
      var bookmarkicon = "assets/bookmarkoff.png";
      var bookmarkOff = "assets/bookmarkoff.png";
      var bookmarkOn = "assets/bookmarkon.png";
    
      void _previousImage() { // prev
        setState(() {
          photoIndex = photoIndex > 0 ? photoIndex - 1 : 0;
        });
      }
    
      void _nextImage() {
        // next
          setState(() {
            photoIndex = photoIndex < photos.length - 1 ? photoIndex + 1 : photoIndex;
            playerProgress += 10;
            print(playerProgress);
            print(photoIndex);
    //      if(isFront){
    //        photoIndex--;
    //      }
          Flashcard();
          });
        }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold( //title_page
            appBar: new AppBar(
              title: new Text('Category 時'),
              centerTitle: true,
            ),
            body: Column( //content
    
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Center(
                  child: Stack(
                    children: <Widget>[
                      Container(
    
                        child: FlipCard(
                          direction: FlipDirection.HORIZONTAL,
                          front: Material( //front_side
                            child: Container(
                              decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25.0),
                                  image: DecorationImage(
                                      image: AssetImage(photos[photoIndex]), //images front
                                      fit: BoxFit.cover)),
                            ),
                            elevation: 20.0,
                            borderRadius: BorderRadius.all(Radius.circular(40.0)),
                          ),
                          back: Material( //back_side
                            child: Container(
                              decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25.0),
                                  image: DecorationImage(
                                      image: AssetImage(photos1[photoIndex]), // images back
                                      fit: BoxFit.cover)),
                            ),
                            elevation: 20.0,
                            borderRadius: BorderRadius.all(Radius.circular(40.0)),
                          ),
                        ),
    
                        height: 400.0,//flashcard
                        width: 370.0,
    
    
                      ),
                      Positioned(
                        top: 380.0, //dots
                        left: 25.0,
                        right: 25.0,
                        child: SelectedPhoto(numberOfDots: photos.length, 
                       photoIndex: photoIndex),
                      )
                    ],
                  ),
                ),
                Row(
    
                  mainAxisAlignment: MainAxisAlignment.center,
    
                  children: <Widget>[
                    RaisedButton(
                      child: Text('Prev', textScaleFactor: 1.3,),
                      onPressed: _previousImage,
                      elevation: 10.0,
                      color: Colors.redAccent,
                      textColor: Colors.white,
                    ),
                    SizedBox(width: 10.0), //space
                    ButtonTheme( //bookmark
                      minWidth: 10,
                      height: 10,
                      child: RaisedButton(
                        child: Image.asset(bookmarkicon, scale: 3.5,),
                        color: Colors.transparent,
                        onPressed: (){
                          if(this.bookmarkicon=='assets/bookmarkoff.png'){
                            print(this.bookmarkicon +" is clicked");
                            setState(() {
                              bookmarkicon = bookmarkOn;
                            });
                            this.bookmarkicon = 'assets/bookmarkon.png';
    
                          }
                          else if(this.bookmarkicon=='assets/bookmarkon.png'){
                            print(this.bookmarkicon +" is clicked");
                            this.bookmarkicon = 'assets/bookmarkoff.png';
                            setState(() {
                              bookmarkicon = bookmarkOff;
                            });
                          }
                          //any implementation for bookmark will be here ;)
                        },
    
                      ),
                    ),
                    SizedBox(width: 10.0), //space
                    RaisedButton(
                      child: Text('Next', textScaleFactor: 1.3,),
                      onPressed:_nextImage,
                      elevation: 10.0,
                      color: Colors.redAccent,
                      textColor: Colors.white,
                    )
                  ],
                )
              ],
            ));
      }
    }
    
    class SelectedPhoto extends StatelessWidget {
    
      final int numberOfDots;
      final int photoIndex;
    
      SelectedPhoto({this.numberOfDots, this.photoIndex});
    
      Widget _inactivePhoto() {
        return new Container(
            child: new Padding(
              padding: const EdgeInsets.only(left: 3.0, right: 3.0),
              child: Container(
                height: 8.0,
                width: 8.0,
                decoration: BoxDecoration(
                    color: Colors.grey,
                    borderRadius: BorderRadius.circular(4.0)
                ),
              ),
            )
        );
      }
    
      Widget _activePhoto() {
        return Container(
          child: Padding(
            padding: EdgeInsets.only(left: 3.0, right: 3.0),
            child: Container(
              height: 10.0,
              width: 10.0,
              decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(5.0),
                  boxShadow: [
                    BoxShadow(
                        color: Colors.grey,
                        spreadRadius: 0.0,
                        blurRadius: 2.0
                    )
                  ]
              ),
            ),
          ),
        );
      }
    
      List<Widget> _buildDots() {
        List<Widget> dots = [];
    
        for(int i = 0; i< numberOfDots; ++i) {
          dots.add(
              i == photoIndex ? _activePhoto(): _inactivePhoto()
          );
        }
    
        return dots;
      }
    
    
      @override
      Widget build(BuildContext context) {
        return new Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: _buildDots(),
          ),
        );
      }
    }
    

    The code works, but when the user pressed next, it will display the next card even though it is the back side showing.