Thursday, 15 July 2021

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

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.



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

No comments:

Post a Comment