Survey Quiz App In Flutter

Survey Quiz App In Flutter :

This flutter tutorial post is survey quiz app. That is amazing quiz app in flutter.

This quiz app provide the functionality:
1) Swipe the new question display.
2) Single and multiple select answer.
3) Select the answer, number indicator change color and true sign display.
4) Number indicator click perticular question diplay.
5) All question fill up answer than display report.

Screenshot 1 :

Survey Quiz App In Flutter

Screenshot 2 :

Survey Quiz App In Flutter

Survey Package :

delegate Package
– model Package
– provider Package
– ui Package
– widgets Package

delegate Package :

internect_connectivity_delegate.dart

import 'dart:io';

class NetworkCheckDelegate {
  static Future<bool> check() async {
    try {
      final result = await InternetAddress.lookup('google.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
        return true;
      }
    } on SocketException catch (_) {
      return false;
    }
    return false;
  }
}

jsonparser.delegate.dart

import 'package:survey_app/survey/model/survey.answer.model.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';

class JsonParserDelegate {
  SurveyQuestionModel getQuestionFromJson(
      Map<String, dynamic> data, bool isFromServer) {
    String question = data["question"];
    String type = data["selection_type"];
    String id = data["survey_id"];
    List<SurveyAnswerModel> answers = List();
    if (isFromServer) {
      data["answers"].forEach((each) {
        answers.add(SurveyAnswerModel(answer: each));
      });
    }
    return SurveyQuestionModel(question, answers, type, id)
      ..questionId = data["id"];
  }
}

JsonParserDelegate jsonParserDelegate = JsonParserDelegate();

snackbar_delegate.dart

import 'package:flutter/material.dart';

class SnackBarDelegate {
  static showSnackBar(context, String text, scaffoldKey, {int time}) {
    scaffoldKey.currentState.showSnackBar(SnackBar(
      backgroundColor: Colors.white,
      content: new Text(
        text,
        style: TextStyle(color: Color(0xff3700b3)),
      ),
      duration: Duration(milliseconds: (time == null) ? 400 : time),
    ));
  }
}

model Package :

survey.answer.model.dart

class SurveyAnswerModel {
  String answer;
  int id;

  SurveyAnswerModel({this.answer, this.id});

  factory SurveyAnswerModel.fromMap(Map<String, dynamic> data) {
    return SurveyAnswerModel(answer: data["answer"], id: data["id"]);
  }

  SurveyAnswerModel copyInstance() {
    return SurveyAnswerModel(answer: answer, id: id);
  }
}

survey.question.model.dart

import 'package:survey_app/survey/delegate/jsonparser.delegate.dart';
import 'package:survey_app/survey/model/survey.answer.model.dart';

class SurveyQuestionModel {
  final String question;

  List<SurveyAnswerModel> answerModels;
  final String selectionType; //single,multiple
  int selectedAnsIndexSingle;
  String surveyId;
  int questionId;
  List<int> selectedAnsIndexForMultiple = List();

  SurveyQuestionModel(
      this.question, this.answerModels, this.selectionType, this.surveyId,
      {this.selectedAnsIndexSingle = -1,
      this.selectedAnsIndexForMultiple,
      this.questionId}) {
    if (this.selectedAnsIndexForMultiple == null)
      selectedAnsIndexForMultiple = [];
  }

  SurveyQuestionModel copyInstance() {
    List<int> multipleIndex = List();
    List<SurveyAnswerModel> answers = List();
    this.answerModels.forEach((each) {
      answers.add(each);
    });
    return SurveyQuestionModel(question, answers, selectionType, surveyId,
        selectedAnsIndexSingle: selectedAnsIndexSingle,
        questionId: questionId,
        selectedAnsIndexForMultiple: multipleIndex);
  }

  factory SurveyQuestionModel.fromMap(
      Map<String, dynamic> json, bool isFromServer) {
    return jsonParserDelegate.getQuestionFromJson(json, isFromServer);
  }

  toMapForQuestionTable() {
    return {
      "question": question,
      "selection_type": selectionType,
      "survey_id": surveyId,
    };
  }

  toMapForUserAnswerTable(int surveyedId) {
    List<Map<String, dynamic>> list = List();
    if (selectionType == AnswerSelectionType.SINGLE_ANSWER) {
      list.add({
        "question_id": questionId,
        "answer_id": answerModels[selectedAnsIndexSingle].id,
        "survey_id": surveyId,
        "surveyed_count_id": surveyedId
      });
    } else {
      selectedAnsIndexForMultiple.forEach((each) {
        list.add({
          "question_id": questionId,
          "answer_id": answerModels[each].id,
          "survey_id": surveyId,
          "surveyed_count_id": surveyedId
        });
      });
    }
    return list;
  }

  List<Map<String, dynamic>> toMapForAnswerTable() {
    List<Map<String, dynamic>> list = List();

    answerModels.forEach((each) {
      list.add({
        "survey_id": surveyId,
        "question_id": questionId,
        "answer": each.answer
      });
    });
    return list;

//    if (selectionType == AnswerSelectionType.SINGLE_ANSWER) {
//      return {
//        "survey_id":surveyId,
//        "question_id":questionId,
//        "answer":answers
//      };
//    } else if (selectionType == AnswerSelectionType.MULTIPLE_ANSWER) {}
  }

  getAnswerInString() {
    StringBuffer stringBuffer = StringBuffer();

    for (int i = 0; i < answerModels.length; i++) {
      stringBuffer.write(answerModels[i].answer);

      if (i != answerModels.length - 1) {
        stringBuffer.write(",");
      }
    }
    print(stringBuffer.toString());
    return stringBuffer.toString();
  }
}

class AnswerSelectionType {
  static const String SINGLE_ANSWER = "single";
  static const String MULTIPLE_ANSWER = "multiple";
}

provider Package :

db_provider.dart

import 'dart:async';
import 'dart:io';

import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:survey_app/survey/model/survey.answer.model.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';

class SurveyDatabaseProvider {
  SurveyDatabaseProvider._();

  static final SurveyDatabaseProvider db = SurveyDatabaseProvider._();
  Database _database;
  String surveyQuestionTableName = "survey_question";
  String surveyAnswersTableName = "survey_answer";
  String userAnswersTableName = "user_answer";

  String dbName = "survey.db";

  Future<Database> get database async {
    if (_database != null) return _database;
    _database = await getDatabaseInstance();
    return _database;
  }

  Future<Database> getDatabaseInstance() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, dbName);
    return await openDatabase(path, version: 2,
        onCreate: (Database db, int version) async {
      initiateQuestionTable(db);
      initiateAnswerTable(db);
      initiateUserAnswerTable(db);
    });
  }

  initiateQuestionTable(Database db) async {
    await db.execute("CREATE TABLE $surveyQuestionTableName ("
        "id integer primary key AUTOINCREMENT,"
        "survey_id TEXT,"
        "question TEXT,"
        "selection_type TEXT"
        ")");
  }

  initiateAnswerTable(Database db) async {
    await db.execute("CREATE TABLE $surveyAnswersTableName ("
        "id integer primary key AUTOINCREMENT,"
        "survey_id TEXT,"
        "question_id int,"
        "answer TEXT"
        ")");
  }

  initiateUserAnswerTable(Database db) async {
    await db.execute("CREATE TABLE $userAnswersTableName ("
        "id integer primary key AUTOINCREMENT,"
        "survey_id TEXT,"
        "question_id int,"
        "answer_id int,"
        "surveyed_count_id int"
        ")");
  }

  addSurveyToDatabase(SurveyQuestionModel questions) async {
    int insertId = await insertQuestion(questions);
    questions.questionId = insertId;
    await insertAnswer(questions);
  }

  Future<int> insertQuestion(questions) async {
    final db = await database;
    var raw = await db.insert(
      surveyQuestionTableName,
      questions.toMapForQuestionTable(),
      conflictAlgorithm: ConflictAlgorithm.ignore,
    );
    print("inserted que: $raw");
    return raw;
  }

  Future<int> insertAnswer(questions) async {
    final db = await database;
    List<Map<String, dynamic>> list = questions.toMapForAnswerTable();
    for (Map<String, dynamic> each in list) {
      var raw = await db.insert(
        surveyAnswersTableName,
        each,
        conflictAlgorithm: ConflictAlgorithm.replace,
      );
      print("inserted ans : $raw");
    }

    return 0;
  }

  Future<List<SurveyQuestionModel>> getQuestionBySurveyId(String id) async {
    List<SurveyQuestionModel> list = List();

    final db = await database;
    var response = await db.query(surveyQuestionTableName,
        where: "survey_id = ?", whereArgs: [id]);

    for (Map<String, dynamic> each in response) {
      SurveyQuestionModel model = SurveyQuestionModel.fromMap(each, false);
      List<Map<String, dynamic>> answerResponse =
          await getAnswerBySurveyIdAndQuestionId(
              model.surveyId, model.questionId);
      print(answerResponse);
      List<SurveyAnswerModel> answerModels = List();
      answerResponse.forEach((each) {
        answerModels
            .add(SurveyAnswerModel(answer: each["answer"], id: each["id"]));
      });
      model.answerModels = answerModels;
      list.add(model);
    }
    print(list.length);
    return list;
  }

  Future<List<Map<String, dynamic>>> getAnswerBySurveyIdAndQuestionId(
      String id, int questionId) async {
    final db = await database;
    var response = await db.query(surveyAnswersTableName,
        where: "survey_id = ? and question_id=?", whereArgs: [id, questionId]);
    return response;
  }

  Future<List<SurveyQuestionModel>> getAllQuestions() async {
    List<SurveyQuestionModel> list = List();

    final db = await database;
    var response = await db.query(surveyQuestionTableName);
    for (Map<String, dynamic> each in response) {
      SurveyQuestionModel model = SurveyQuestionModel.fromMap(each, false);
      List<Map<String, dynamic>> answerResponse =
          await getAnswerBySurveyIdAndQuestionId(
              model.surveyId, model.questionId);
      print(answerResponse);
      List<SurveyAnswerModel> answerModels = List();
      answerResponse.forEach((each) {
        answerModels
            .add(SurveyAnswerModel(answer: each["answer"], id: each["id"]));
      });
      model.answerModels = answerModels;
      list.add(model);
    }
    print(list.length);
    return list;
  }

  Future<int> getSurveyedCount() async {
    final db = await database;
    List<Map<String, dynamic>> responses = await db
        .rawQuery("select count(distinct(surveyed_count_id)) count from "
            "$userAnswersTableName");
    if (responses.length > 0)
      return responses[0]['count'];
    else
      return 0;
  }

  Future<bool> saveAnswers(List<SurveyQuestionModel> questions) async {
    final db = await database;
    int getOldSurveyedCount = await getSurveyedCount();

    int newSurveyValue = getOldSurveyedCount + 1;

    for (SurveyQuestionModel question in questions) {
      List<Map<String, dynamic>> answersByUser =
          question.toMapForUserAnswerTable(newSurveyValue);
      for (Map<String, dynamic> answerByUser in answersByUser) {
        var raw = await db.insert(userAnswersTableName, answerByUser);
        print("output: $raw for ${answerByUser["question_id"]}");
      }
    }
    return true;
  }

  getAllSurvey(Database db) async {
    return await db.query(userAnswersTableName,
        columns: ["surveyed_count_id"], distinct: true);
  }

  Future<List<Map<String, dynamic>>> getUserSurveyAnswerBySurveyedId(
      int surveyedId, Database db) async {
    return await db.query(userAnswersTableName,
        where: "surveyed_count_id=?", whereArgs: [surveyedId]);
  }

  getQuestionAnswers(List<SurveyQuestionModel> questions,
      List<Map<String, dynamic>> allAnswers) {
    List<SurveyQuestionModel> questionList = new List();
    questions.forEach((each) {
      questionList.add(each.copyInstance());
    });
    allAnswers.forEach((answers) {
      questionList.forEach((question) {
        if (answers["question_id"] == question.questionId) {
          if (question.selectionType == AnswerSelectionType.SINGLE_ANSWER) {
            question.selectedAnsIndexSingle = answers["answer_id"];
          } else if (question.selectionType ==
              AnswerSelectionType.MULTIPLE_ANSWER) {
            question.selectedAnsIndexForMultiple.add(answers["answer_id"]);
          }
        }
      });
    });
    return questionList;
  }

  Future<List<List<SurveyQuestionModel>>> getSavedSurvey() async {
    final db = await database;
    List<SurveyQuestionModel> questions = await getAllQuestions();

    List<Map<String, dynamic>> userSurveys = await getAllSurvey(db);
    List<List<SurveyQuestionModel>> userSavedSurvey = List();
    for (Map<String, dynamic> eachSurvey in userSurveys) {
      List<Map<String, dynamic>> eachAnswers =
          await getUserSurveyAnswerBySurveyedId(
              eachSurvey["surveyed_count_id"], db);
      userSavedSurvey.add(getQuestionAnswers(questions, eachAnswers));
      print(1);
    }
    print(1);
    return userSavedSurvey;
  }
}

survey.provider.dart

import 'package:flutter/material.dart';
import 'package:survey_app/survey/delegate/internect_connectivity_delegate.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';
import 'package:survey_app/survey/provider/survey.server.dart';

import 'db_provider.dart';

class SurveyProvider with ChangeNotifier {
  List<SurveyQuestionModel> _surveys;

  SurveyProvider();

  getSurveys() async {
    bool isInternetConnected = await NetworkCheckDelegate.check();

    if (_surveys == null || _surveys.length == 0) {
      if (isInternetConnected) _surveys = await surveyServer.getQuestions();
    }
    if (_surveys != null && _surveys.length > 0) {
      List<SurveyQuestionModel> oldRecords = await SurveyDatabaseProvider.db
          .getQuestionBySurveyId(_surveys.first.surveyId);

      if (oldRecords == null || oldRecords.length == 0) {
        for (SurveyQuestionModel each in _surveys) {
          await SurveyDatabaseProvider.db.addSurveyToDatabase(each);
        }
      }
      if (oldRecords == null || oldRecords.length == 0) {
        oldRecords = await SurveyDatabaseProvider.db
            .getQuestionBySurveyId(_surveys.first.surveyId);
      }
      return oldRecords;
    } else {
      List<SurveyQuestionModel> oldRecords =
          await SurveyDatabaseProvider.db.getAllQuestions();
      return oldRecords;
    }
  }

  getSurveyHistory() async {
    return await SurveyDatabaseProvider.db.getSavedSurvey();
  }

  saveSurvey(List<SurveyQuestionModel> questions) async {
    return await SurveyDatabaseProvider.db.saveAnswers(questions);
  }
}

survey.server.dart

import 'dart:convert';

import 'package:http/http.dart';
import 'package:survey_app/survey/delegate/jsonparser.delegate.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';

class SurveyServer {
  Future<List<SurveyQuestionModel>> getQuestions() async {
    List<SurveyQuestionModel> questions = List();
    try {
      Response result =
          await get("http://demo8388355.mockable.io/survey/questions");
      var jsonResult = json.decode(result.body);
      if (result.statusCode == 200) {
        jsonResult["questions"].forEach((each) {
          questions.add(jsonParserDelegate.getQuestionFromJson(each, true));
        });
      }
    } catch (e) {
      print(e);
    }

    return questions;
  }
}

SurveyServer surveyServer = SurveyServer();

ui Package :

page_indicator.dart

import 'package:flutter/material.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';

class PageIndicator extends StatelessWidget {
  final int currentIndex;
  final int pageCount;
  Color bgDarkColor = Color(0xa13700b3);
  final Function onClick;
  List<SurveyQuestionModel> surveyModels;

  PageIndicator(
      this.currentIndex, this.pageCount, this.onClick, this.surveyModels);

  _indicator(bool isActive, int index) {
    bool isAnswered = false;
    if (surveyModels[index].selectionType ==
        AnswerSelectionType.SINGLE_ANSWER) {
      isAnswered = surveyModels[index].selectedAnsIndexSingle != -1;
    } else if (surveyModels[index].selectionType ==
        AnswerSelectionType.MULTIPLE_ANSWER) {
      isAnswered = surveyModels[index].selectedAnsIndexForMultiple != null &&
          surveyModels[index].selectedAnsIndexForMultiple.length > 0;
    }

    return Expanded(
      child: InkWell(
        borderRadius: BorderRadius.all(Radius.circular(20)),
        onTap: () {
          onClick(index);
        },
        child: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            AnimatedContainer(
              height: 4.0,
              decoration: BoxDecoration(
                  color: isActive ? Colors.white70 : Colors.white30,
                  boxShadow: [
                    BoxShadow(
                        color: isActive ? Colors.white70 : Colors.white30,
                        offset: Offset(0.0, 1.0),
                        blurRadius: 10.0)
                  ]),
              duration: Duration(seconds: 2),
              // Provide an optional curve to make the animation feel smoother.
              curve: Curves.fastLinearToSlowEaseIn,
            ),
            CircleAvatar(
              backgroundColor: isActive ? Colors.white : bgDarkColor,
              child: Text(
                "${index + 1}",
                style: TextStyle(
                    color: isActive ? bgDarkColor : Colors.white, fontSize: 20),
              ),
            ),
            isAnswered
                ? Positioned(
                    top: -4,
                    right: 8,
                    child: Icon(
                      Icons.done,
                      color: Colors.green,
                    ),
                  )
                : SizedBox()
          ],
        ),
      ),
    );
  }

  _buildPageIndicators() {
    List<Widget> indicatorList = [];
    for (int i = 0; i < pageCount; i++) {
      indicatorList
          .add(i <= currentIndex ? _indicator(true, i) : _indicator(false, i));
    }
    return indicatorList;
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: _buildPageIndicators(),
    );
  }
}

survey.details.dart

import 'package:flutter/material.dart';

class SurveyDetailsUi extends StatefulWidget {
  @override
  _SurveyDetailsUiState createState() => _SurveyDetailsUiState();
}

class _SurveyDetailsUiState extends State<SurveyDetailsUi> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

survey.history.ui.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';
import 'package:survey_app/survey/provider/survey.provider.dart';

class SurveyHistoryUi extends StatefulWidget {
  @override
  _SurveyHistoryUiState createState() => _SurveyHistoryUiState();
}

class _SurveyHistoryUiState extends State<SurveyHistoryUi> {
  List<List<SurveyQuestionModel>> surveyModels = List();
  bool isLoading = true;
  Color bgColor = Color(0xff6200ee);
  Color bgDarkColor = Color(0xff3700b3);

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      getHistory();
    });
  }

  getHistory() async {
    surveyModels =
        await Provider.of<SurveyProvider>(context).getSurveyHistory();
    setState(() {
      isLoading = false;
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Survey History"),
          backgroundColor: bgColor,
        ),
        body: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  colors: [bgColor, bgColor],
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter)),
          child: isLoading
              ? Center(
                  child: CircularProgressIndicator(),
                )
              : (surveyModels == null || surveyModels.length == 0)
                  ? Center(
                      child: Text(
                        "No Survey "
                        "Record found",
                        style: TextStyle(color: Colors.white, fontSize: 24),
                      ),
                    )
                  : ListView.builder(
                      shrinkWrap: true,
                      itemCount: surveyModels.length,
                      itemBuilder: (context, index) {
                        List<SurveyQuestionModel> eachSurveyList =
                            surveyModels[index];

                        return Column(
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            SizedBox(
                              height: 16,
                            ),
                            Text(
                              "Survey : ${index + 1}",
                              style: TextStyle(
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                  fontSize: 20),
                            ),
                            SizedBox(
                              height: 8,
                            ),
                            ListView.builder(
                                shrinkWrap: true,
                                physics: NeverScrollableScrollPhysics(),
                                itemCount: eachSurveyList.length,
                                itemBuilder: (context, index) {
                                  SurveyQuestionModel questionModel =
                                      eachSurveyList[index];
                                  String text;
                                  int i = 0;
                                  while (text == null) {
                                    if (questionModel.answerModels[i].id ==
                                        questionModel.selectedAnsIndexSingle) {
                                      text =
                                          questionModel.answerModels[i].answer;
                                    }
                                    if (text == null &&
                                        i ==
                                            questionModel.answerModels.length -
                                                1) {
                                      text = "";
                                    }
                                    i++;
                                  }
                                  return Column(
                                    mainAxisSize: MainAxisSize.min,
                                    mainAxisAlignment: MainAxisAlignment.start,
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: <Widget>[
                                      Padding(
                                        padding: const EdgeInsets.all(8.0),
                                        child: Column(
                                            mainAxisSize: MainAxisSize.min,
                                            mainAxisAlignment:
                                                MainAxisAlignment.start,
                                            crossAxisAlignment:
                                                CrossAxisAlignment.start,
                                            children: [
                                              Text(
                                                  "Q: ${questionModel.question}",
                                                  style: TextStyle(
                                                      color: Colors.white,
                                                      fontSize: 16,
                                                      fontWeight:
                                                          FontWeight.w600)),
                                              SizedBox(
                                                height: 8,
                                              ),
                                              (questionModel.selectionType ==
                                                      AnswerSelectionType
                                                          .SINGLE_ANSWER)
                                                  ? Text("A: $text",
                                                      style: TextStyle(
                                                          color: Colors.white,
                                                          fontSize: 16))
                                                  : (questionModel
                                                              .selectionType ==
                                                          AnswerSelectionType
                                                              .MULTIPLE_ANSWER)
                                                      ? ListView.builder(
                                                          shrinkWrap: true,
                                                          physics:
                                                              NeverScrollableScrollPhysics(),
                                                          itemCount: questionModel
                                                              .selectedAnsIndexForMultiple
                                                              .length,
                                                          itemBuilder:
                                                              (context, index) {
                                                            int currentAnsIndex =
                                                                questionModel
                                                                        .selectedAnsIndexForMultiple[
                                                                    index];
                                                            String text;
                                                            int i = 0;
                                                            while (
                                                                text == null) {
                                                              if (questionModel
                                                                      .answerModels[
                                                                          i]
                                                                      .id ==
                                                                  currentAnsIndex) {
                                                                text = questionModel
                                                                    .answerModels[
                                                                        i]
                                                                    .answer;
                                                              }
                                                              if (text ==
                                                                      null &&
                                                                  i ==
                                                                      questionModel
                                                                              .answerModels
                                                                              .length -
                                                                          1) {
                                                                text = "";
                                                              }
                                                              i++;
                                                            }
                                                            return Padding(
                                                              padding:
                                                                  const EdgeInsets
                                                                          .symmetric(
                                                                      vertical:
                                                                          2),
                                                              child: Text(
                                                                "A: $text",
                                                                style: TextStyle(
                                                                    color: Colors
                                                                        .white,
                                                                    fontSize:
                                                                        16),
                                                              ),
                                                            );
                                                          },
                                                        )
                                                      : SizedBox(),
                                            ]),
                                      ),
                                      Divider(
                                        color: Colors.white,
                                      )
                                    ],
                                  );
                                }),
                            SizedBox(
                              height: 4,
                            ),
                          ],
                        );
                      },
                    ),
        ));
  }
}

survey.ui.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:survey_app/survey/delegate/snackbar_delegate.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';
import 'package:survey_app/survey/provider/db_provider.dart';
import 'package:survey_app/survey/provider/survey.provider.dart';
import 'package:survey_app/survey/ui/page_indicator.dart';
import 'package:survey_app/survey/ui/survey_item.dart';
import 'package:survey_app/survey/widgets/custom_app_bar.dart';

class SurveyUi extends StatefulWidget {
  @override
  _SurveyUiState createState() => _SurveyUiState();
}

class _SurveyUiState extends State<SurveyUi> {
  List<SurveyQuestionModel> surveyModels;
  bool isLoading = true;
  PageController pageController = PageController();
  double currentPageValue = 0.0;
  int currentIndexOfPage = 0;
  Color bgColor = Color(0xff6200ee);
  Color bgDarkColor = Color(0xff3700b3);
  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((a) {
      getSurveys();
    });
  }

  getSurveys() async {
    SurveyDatabaseProvider.db.getSurveyedCount();
    surveyModels = await Provider.of<SurveyProvider>(context).getSurveys();
    setState(() {
      isLoading = false;
    });
  }

  saveAnswers(context) async {
    bool isEverythingCorrect = true;
    int i = 0;
    for (SurveyQuestionModel model in surveyModels) {
      if (model.selectionType == AnswerSelectionType.SINGLE_ANSWER) {
        if (model.selectedAnsIndexSingle == -1) {
          SnackBarDelegate.showSnackBar(
              context, "Please select one", _scaffoldKey,
              time: 2000);

          pageController.animateToPage(i,
              duration: Duration(seconds: 2),
              curve: Curves.fastLinearToSlowEaseIn);
          isEverythingCorrect = false;
          break;
        }
        i++;
      }
    }
    if (!isEverythingCorrect) return;

    var result =
        await Provider.of<SurveyProvider>(context).saveSurvey(surveyModels);

    showDialogOnSurveyComplete(context);
    resetAnswers();
  }

  resetAnswers() {
    getSurveys();
    pageController.animateToPage(0,
        duration: Duration(seconds: 3), curve: Curves.fastLinearToSlowEaseIn);
  }

  showDialogOnSurveyComplete(context) {
    showDialog(
        context: context,
        barrierDismissible: false,
        builder: (context) {
          return AlertDialog(
            title: Text("Completed"),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(16))),
            content: Container(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[Text("Thanks for giving feedback")],
              ),
            ),
            actions: <Widget>[
              RaisedButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                padding: EdgeInsets.symmetric(horizontal: 32, vertical: 8),
                color: bgDarkColor,
                child: Text(
                  "Okay",
                  style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.w600,
                      fontSize: 20),
                ),
              )
            ],
          );
        });
  }

  doNext() {
    currentIndexOfPage = currentIndexOfPage + 1;
    pageController.animateToPage(currentIndexOfPage,
        duration: Duration(seconds: 1), curve: ElasticOutCurve(1));
  }

  onClickPageIndicatorItem(int index) {
    pageController.animateToPage(index,
        duration: Duration(seconds: 1), curve: ElasticOutCurve(1));
  }

  onHistoryClick() {
    Navigator.of(context).pushNamed("/history");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
//      appBar: AppBar(
//        title: Text("Test"),
//        actions: <Widget>[
//          IconButton(
//            icon: Icon(Icons.add),
//            onPressed: () async {
//              if (surveyModels != null && surveyModels.length > 0) {
//                surveyModels.forEach((each) async {
//                  await SurveyDatabaseProvider.db.addSurveyToDatabase(each);
//                });
//              }
//            },
//          ),
//          IconButton(
//            icon: Icon(Icons.get_app),
//            onPressed: () async {
//              List<SurveyQuestionModel> oldRecords =
//                  await SurveyDatabaseProvider.db.getAllQuestions();
//              setState(() {
//                isLoading = false;
//                surveyModels = oldRecords;
//              });
//              print(oldRecords.length);
//            },
//          )
//        ],
//      ),
      body: SingleChildScrollView(
        child: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height -
              MediaQuery.of(context).viewPadding.bottom,
          padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  colors: [bgColor, bgColor],
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter)),
          child: Stack(
            children: <Widget>[
              (isLoading)
                  ? Positioned(
                      top: 0,
                      bottom: 0,
                      left: 0,
                      right: 0,
                      child: Center(
                          child: CircularProgressIndicator(
//                  backgroundColor: Color(0xffFFDE01),
                        valueColor:
                            new AlwaysStoppedAnimation<Color>(Colors.white),
                      )),
                    )
                  : SizedBox(),
              (isLoading)
                  ? SizedBox()
                  : (surveyModels.length == 0)
                      ? Center(
                          child: Text(
                            "No surveys for today",
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 18,
                                fontWeight: FontWeight.w600),
                          ),
                        )
                      : Column(
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            CustomAppBar(
                              "Survey",
                              false,
                              false,
                              isHistoryNeeded: true,
                              onHistoryClick: onHistoryClick,
                            ),
                            SizedBox(height: 24),
                            Expanded(
                              child: PageView.builder(
                                itemCount: surveyModels.length,
                                controller: pageController,
                                onPageChanged: (index) {
                                  setState(() {
                                    currentIndexOfPage = index;
                                  });
                                },
                                itemBuilder: (context, index) {
                                  SurveyQuestionModel surveyQuestionModel =
                                      surveyModels[index];

                                  return SurveyItem(surveyQuestionModel,
                                      surveyModels.length, index);
                                },
                                pageSnapping: true,
                                physics: BouncingScrollPhysics(),
                              ),
                            ),
                          ],
                        ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        color: bgColor,
        child: (isLoading || surveyModels == null || surveyModels.length == 0)
            ? SizedBox()
            : Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Container(
                    width: MediaQuery.of(context).size.width - 32,
                    margin: EdgeInsets.all(16),
                    child: RaisedButton(
                      color: Colors.white,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.all(Radius.circular(16))),
                      padding: EdgeInsets.all(16),
                      onPressed: () {
                        if (currentIndexOfPage == surveyModels.length - 1) {
                          saveAnswers(context);
                        } else {
                          doNext();
                        }
                      },
                      child: (currentIndexOfPage == surveyModels.length - 1)
                          ? Text("Submit",
                              style: TextStyle(
                                  color: bgDarkColor,
                                  fontSize: 20,
                                  letterSpacing: 2,
                                  fontWeight: FontWeight.bold))
                          : Text("Next",
                              style: TextStyle(
                                  color: bgDarkColor,
                                  fontSize: 20,
                                  letterSpacing: 2,
                                  fontWeight: FontWeight.bold)),
                    ),
                  ),
                  SizedBox(
                      width: MediaQuery.of(context).size.width,
                      child: Padding(
                        padding: const EdgeInsets.only(left: 8.0),
                        child: PageIndicator(
                            currentIndexOfPage,
                            surveyModels.length,
                            onClickPageIndicatorItem,
                            surveyModels),
                      )),
                  SizedBox(
                    height: 16,
                  )
                ],
              ),
      ),
    );
  }
}

survey_item.dart

import 'package:flutter/material.dart';
import 'package:survey_app/survey/model/survey.question.model.dart';

class SurveyItem extends StatefulWidget {
  final SurveyQuestionModel surveyQuestionModel;
  final int length;
  final int index;

  SurveyItem(this.surveyQuestionModel, this.length, this.index);

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

class _SurveyItemState extends State<SurveyItem> {
  Widget getCheckerIcon(int index) {
    if (widget.surveyQuestionModel.selectionType
            .compareTo(AnswerSelectionType.SINGLE_ANSWER) ==
        0) {
      if (widget.surveyQuestionModel.selectedAnsIndexSingle == -1 ||
          widget.surveyQuestionModel.selectedAnsIndexSingle != index) {
        return Icon(
          Icons.radio_button_unchecked,
          color: Colors.white,
        );
      } else {
        return Icon(Icons.radio_button_checked, color: Colors.white);
      }
    } else if (widget.surveyQuestionModel.selectionType
            .compareTo(AnswerSelectionType.MULTIPLE_ANSWER) ==
        0) {
      if (widget.surveyQuestionModel.selectedAnsIndexForMultiple == null) {
        return Icon(Icons.check_box_outline_blank, color: Colors.white);
      }
      if (widget.surveyQuestionModel.selectedAnsIndexForMultiple.length == 0 ||
          !widget.surveyQuestionModel.selectedAnsIndexForMultiple
              .contains(index)) {
        return Icon(Icons.check_box_outline_blank, color: Colors.white);
      } else {
        return Icon(Icons.check_box, color: Colors.white);
      }
    } else
      return Icon(Icons.radio_button_unchecked, color: Colors.white);
  }

  updateAnswerStatus(index) {
    if (widget.surveyQuestionModel.selectionType.compareTo("single") == 0) {
      widget.surveyQuestionModel.selectedAnsIndexSingle = index;
    } else if (widget.surveyQuestionModel.selectionType.compareTo("multiple") ==
        0) {
      if (widget.surveyQuestionModel.selectedAnsIndexForMultiple != null &&
          widget.surveyQuestionModel.selectedAnsIndexForMultiple
              .contains(index)) {
        widget.surveyQuestionModel.selectedAnsIndexForMultiple.remove(index);
      } else {
        widget.surveyQuestionModel.selectedAnsIndexForMultiple.add(index);
      }
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Text(
          "QUESTION ${widget.index + 1} OF ${widget.length} ",
          style: TextStyle(
              color: Colors.white,
              letterSpacing: 2,
              fontWeight: FontWeight.w600),
        ),
        SizedBox(
          height: 16,
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: Text(widget.surveyQuestionModel.question,
              style: TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                  letterSpacing: 2,
                  fontWeight: FontWeight.bold)),
        ),
        Expanded(
          child: ListView.builder(
              shrinkWrap: true,
              itemCount: widget.surveyQuestionModel.answerModels.length,
              physics: NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                String answer =
                    widget.surveyQuestionModel.answerModels[index].answer;
                return InkWell(
                  onTap: () {
                    updateAnswerStatus(index);
                  },
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Container(
                        padding:
                            EdgeInsets.symmetric(horizontal: 16, vertical: 6),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            Expanded(flex: 1, child: getCheckerIcon(index)),
                            Expanded(
                                flex: 5,
                                child: Text(
                                  answer,
                                  style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 18,
                                      fontWeight: FontWeight.w600),
                                ))
                          ],
                        ),
                      ),
                      Padding(
                          child: ((index + 1) <
                                  widget
                                      .surveyQuestionModel.answerModels.length)
                              ? Divider(
                                  color: Colors.white30,
                                )
                              : SizedBox(),
                          padding: EdgeInsets.symmetric(horizontal: 16)),
                    ],
                  ),
                );
              }),
        ),
      ],
    );
  }
}

widgets Package :

custom_app_bar.dart

import 'package:flutter/material.dart';

class CustomAppBar extends StatelessWidget {
  final String title;
  final bool isBackNeeded;
  final bool isEndNeeded;
  final bool isHistoryNeeded;
  final Function onHistoryClick;

  CustomAppBar(this.title, this.isBackNeeded, this.isEndNeeded,
      {this.isHistoryNeeded = false, this.onHistoryClick});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 96,
      padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
      alignment: Alignment.bottomCenter,
      child: Row(
        children: <Widget>[
          (isBackNeeded)
              ? Icon(
                  Icons.arrow_back_ios,
                  color: Colors.white,
                )
              : SizedBox(),
          Spacer(),
          Text(
            title,
            style: TextStyle(
                color: Colors.white, fontWeight: FontWeight.w600, fontSize: 24),
          ),
          Spacer(),
          (isEndNeeded)
              ? Icon(
                  Icons.close,
                  color: Colors.white,
                )
              : SizedBox(),
          (isHistoryNeeded)
              ? IconButton(
                  onPressed: onHistoryClick,
                  icon: Icon(
                    Icons.history,
                    color: Colors.white,
                  ))
              : SizedBox()
        ],
      ),
    );
  }
}

pubspec.yaml

name: survey_app
description: A new Flutter application.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  http:
  provider:
  sqflite:
  path_provider:
  path:

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:survey_app/survey/provider/survey.provider.dart';
import 'package:survey_app/survey/ui/survey.history.ui.dart';
import 'package:survey_app/survey/ui/survey.ui.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Tutorial',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: ChangeNotifierProvider<SurveyProvider>(
            builder: (_) => SurveyProvider(), child: SurveyUi()),
        routes: {
          "/history": (context) => ChangeNotifierProvider<SurveyProvider>(
              builder: (_) => SurveyProvider(), child: SurveyHistoryUi()),
        });
  }
}

The flutter tutorial  is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application

For more information about Flutter. visit www.fluttertutorial.in