Bloc Event Login And List Api Call (RestApi – Offline)

Screenshot : 1

Bloc Event Login And List Api Call (RestApi - Offline)

Screenshot :2

Bloc Event Login And List Api Call (RestApi - Offline)

build.gradle

dependencies {
testImplementation'junit:junit:4.12'
implementation'androidx.annotation:annotation:1.0.1'
implementation <strong>'com.android.support:multidex:1.0.3'
}

gradle.properties

org.gradle.jvmargs=-Xmx1536M
android.enableJetifier=true
android.useAndroidX=true

pubspec.yaml

name: module_block_event
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
rxdart:
flutter_vector_icons:
http:
shared_preferences:
connectivity:
device_id:
intl:
font_awesome_flutter:
flutter_bloc:
provider:

dev_dependencies:
flutter_test:
sdk: flutter

flutter:
uses-material-design: true
Bloc Event Login And List Api Call

Click the Packages get

lib packages

Bloc Event Login And List Api Call

lib packages inside files put

blocs package

  1. reason
    • reason_bloc.dart
    • reason_event.dart
    • reason_state.dart
  2. register
    • register_bloc.dart
    • register_event.dart
    • register_state.dart
  3. user
    • user_bloc.dart
    • user_event.dart
    • user_state.dart
  4. common_state.dart

Reason package inside

 

reason_bloc.dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:module_block_event/blocs/reason/reason_event.dart';
import 'package:module_block_event/blocs/reason/reason_state.dart';
import 'package:module_block_event/viewmodel/api_provider.dart';

class ReasonBlocextends Bloc<ReasonEvent, ReasonState> {
final ApiProviderapiProvider= ApiProvider();

void getSchool() {
    dispatch(GetSchool());
  }

@override
ReasonStateget initialState=>ReasonState.initial();

@override
Stream<ReasonState>mapEventToState(ReasonEvent event) async* {
if (event is GetSchool) {
yield currentState.copyWith(loading: true);

try {
await apiProvider.getPostPonCancelReasonList();

if (apiProvider.apiResult!= null) {
yield currentState.copyWith(
            schools: apiProvider.apiResult.response,
            loaded: true,
            loading: false,
          );
        }
      } catch (e) {
yield currentState.copyWith(
          error: {"error": "Error, Something bad happened."},
          loaded: true,
          loading: false,
        );
      }
    }
  }
}

reason_event.dart

abstract class ReasonEvent {}

class GetSchoolextends ReasonEvent {}

reason_state.dart

import 'package:meta/meta.dart';
import 'package:module_block_event/models/reason.dart';

class ReasonState {
final bool loading;
final bool loaded;
final Map error;
final List<Reason>reasons;

ReasonState({
@required this.loading,
@required this.loaded,
@required this.error,
@required this.reasons,
  });

factory ReasonState.initial() {
return ReasonState(
      loading: false,
      loaded: false,
      error: null,
      reasons: List<Reason>(),
    );
  }

ReasonStatecopyWith({
    bool loading,
    bool loaded,
    Map error,
    List<Reason> schools,
  }) {
return ReasonState(
      loading: loading ?? this.loading,
      loaded: loaded ?? this.loaded,
      error: error ?? this.error,
      reasons: schools ?? this.reasons,
    );
  }
}

register_bloc.dart

import 'package:module_block_event/blocs/register/register_event.dart';
import 'package:module_block_event/blocs/register/register_state.dart';
import 'package:bloc/bloc.dart';
import 'package:module_block_event/helpers/vars.dart';
import 'package:module_block_event/viewmodel/api_provider.dart';

class RegisterBlocextends Bloc<RegisterEvent, RegisterState> {
final ApiProviderapiProvider= ApiProvider();

void onChangeMobile(mobile) {
    dispatch(ChangeMobile(mobile: mobile));
  }

void onChangePassword(password) {
    dispatch(ChangePassword(password: password));
  }

void setUid(uid) {
    dispatch(SetUid(uid: uid));
  }

void registerDevice(callback) {
    dispatch(RegisterDevice(callback: callback));
  }

@override
RegisterStateget initialState=>RegisterState.initial();

@override
Stream<RegisterState>mapEventToState(
RegisterEvent event,
      ) async* {
if (event is ChangeMobile) {
yield currentState.copyWith(mobile: event.mobile, error: {});
    }

if (event is ChangePassword) {
yield currentState.copyWith(password: event.password, error: {});
    }

if (event is SetUid) {
yield currentState.copyWith(uid: event.uid);
    }

if (event is RegisterDevice) {
yield currentState.copyWith(loading: true);
await apiProvider.getLogin(currentState.mobile, currentState.password);
try {
varuser = apiProvider.apiResult.response;
if (apiProvider.apiResult.responseCode== ok200) {
yield currentState.copyWith(
            loaded: true,
            loading: false,
            error: {},
          );
event.callback(user);
        } else {

yield currentState.copyWith(
            loaded: true,
            loading: false,
            error: {"error": apiProvider.apiResult.responseCode== 404 ? 'Record not found': 'Enter mobile or password'},
          );

event.callback(false);
        }
      } catch (e) {
yield currentState.copyWith(
          loaded: true,
          loading: false,
          error: {"error": "Error, Something bad happened."},
        );

event.callback(false);
      }
    }
  }
}

register_event.dart

abstract class RegisterEvent {}

class ChangeMobileextends RegisterEvent {
final String mobile;
ChangeMobile({this.mobile});
}

class ChangePasswordextends RegisterEvent {
final String password;
ChangePassword({this.password});
}

class SetUidextends RegisterEvent {
final String uid;
SetUid({this.uid});
}

class RegisterDeviceextends RegisterEvent {
  Function callback;
RegisterDevice({this.callback});
}

register_state.dart

import'package:meta/meta.dart';
import '../common_state.dart';

class RegisterStateextends CommonState {
final String mobile;
final String password;
final String uid;
  bool loading;
  bool loaded;
  Map error;

RegisterState({
@required this.mobile,
@required this.password,
@required this.uid,
    bool loading,
    bool loaded,
    Map error,
  }) : super(
    loading: loading,
    loaded: loaded,
    error: error,
  );

factory RegisterState.initial() {
return RegisterState(
      mobile: "",
      password: "",
uid: "",
    );
  }

RegisterStatecopyWith(
      {bool loading,
        bool loaded,
        Map error,
        String mobile,
        String uid,
        String password}) {
return RegisterState(
      mobile: mobile ?? this.mobile,
      password: password ??this.password,
uid: uid ??this.uid,
    );
 }
}

user_bloc.dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:module_block_event/blocs/user/user_event.dart';
import 'package:module_block_event/blocs/user/user_state.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/viewmodel/api_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

class UserBlocextends Bloc<UserEvent, UserState> {
final ApiProviderapiProvider= ApiProvider();

void updateState(key, value) {
    dispatch(UpdateState(key: key, value: value));
  }

void getAuthUser() {
    dispatch(GetAuthUser());
  }

void setAuthUser(user) {
    dispatch(SetAuthUser(user: user));
  }

void setAuthToken(token) {
    dispatch(SetAuthToken(token: token));
  }

void removeAuth(token) {
    dispatch(SetAuthToken(token: token));
  }

void updateProfile(callback) {
    dispatch(UpdateProfile(callback: callback));
  }

@override
UserStateget initialState=>UserState.initial();

@override
Stream<UserState>mapEventToState(
UserEvent event,
  ) async* {
if (event is UpdateState) {
      User user = currentState.user.copyWith({event.key: event.value});
yield currentState.copyWith(user: user, error: {});
    }

if (event is GetAuthUser) {
yield currentState.copyWith(loaded: false, loading: true);

/* try {
        final response = await apiProvider.getAuthUser();
        final results = json.decode(response.body);

        if (results['user'] != null) {
          dispatch(SetAuthUser(user: results['user']));
        } else {
          dispatch(RemoveAuth());
        }
      } catch (e) {
        yield currentState.copyWith(
          error: {"errors": "Error, Something bad happened."},
          loaded: true,
          loading: false,
        );
      }*/
}

if (event is SetAuthToken) {
SharedPreferencespref = await SharedPreferences.getInstance();
pref.setString("authToken", event.token);
    }

if (event is SetAuthUser) {
yield currentState.copyWith(
        loaded: true,
        loading: false,
        user: event.user,
      );
    }

if (event is RemoveAuth) {
SharedPreferencespref = await SharedPreferences.getInstance();
pref.remove("authToken");

yield currentState.copyWith(
        loaded: true,
        loading: false,
        user: null,
      );
    }
  }
}

user_event.dart

import 'package:module_block_event/models/user.dart';

abstract class UserEvent {}

class UpdateStateextends UserEvent {
final String key;
final dynamic value;

UpdateState({this.key, this.value});
}

class GetAuthUserextends UserEvent {}

class UpdateProfileextends UserEvent {
final Function callback;
UpdateProfile({this.callback});
}

class SetAuthUserextends UserEvent {
final User user;
SetAuthUser({this.user});
}

class SetAuthTokenextends UserEvent {
final String token;
SetAuthToken({this.token});
}

class RemoveAuthextends UserEvent {}

user_state.dart

import 'package:flutter/material.dart';
import 'package:module_block_event/models/user.dart';
import 'package:meta/meta.dart';

class UserState {
final bool loading;
final bool loaded;
final Map error;
final User user;

UserState({
@required this.loading,
@required this.loaded,
@required this.error,
@required this.user,
  });

factory UserState.initial() {
return UserState(
      loading: false,
      loaded: false,
      error: null,
      user: null,
    );
  }

UserStatecopyWith({
    bool loading,
    bool loaded,
    Map error,
    User user,
  }) {
return UserState(
      loading: loading ?? this.loading,
      loaded: loaded ?? this.loaded,
      error: error ?? this.error,
      user: user ?? this.user,
    );
  }
}

reason.dart

class Reason {
final intid;
final String description;

  Reason({this.id, this.description});

  Reason copyWith(Map<String, String>json) {
return Reason(
      id: json["ID"] ?? this.id,
      description: json["LISTDESC"] ?? this.description,
    );
  }

Reason.fromJson(Map<String, dynamic>json)
      : id = json != null ? json["ID"] : null,
description = json != null ? json["LISTDESC"] : null;
}

user.dart

class User {
final intid;
final String name;
final String mobile;
final String message;

  User({this.id, this.name, this.mobile, this.message});

  User copyWith(Map<String, dynamic>json) {
return User(
        id: json["EMPID"] ?? this.id,
        name: json["EMPNAME"] ?? this.name,
        mobile: json["EMPMBNO"] ?? this.mobile,
        message: json["Message"] ?? this.message);
  }

User.fromJson(Map<String, dynamic>json)
      : id = json["EMPID"],
name = json["EMPNAME"],
mobile = json["EMPMBNO"],
message = json["Message"];
}

common_state.dart

abstract class CommonState {
   bool loading = false;
   bool loaded= false;
   Map error;

CommonState({
this.loading,
this.loaded,
this.error,
  });

  Map<String, dynamic>toMap() => {
'loading': loading,
'loaded': loaded,
'error': error,
  };
}

validation.dart

String getErrorText(state, key) {
return state.error != null &&state.error[key] != null
? state.error[key]
      : null;
}

vars.dart

String appName = "MileStone";
String quickFont = 'Quicksand';
String ralewayFont = 'Raleway';
String quickBoldFont = 'quicksand_bold.otf';
String quickNormalFont = 'quicksand_book.otf';
String quickLightFont = 'quicksand_light.otf';

int ok200 = 200;

screens package

  1. page
    • initial_screen.dart
    • login.dart
    • reason.dart
  2. widgets
    • animatedbutton.dart
    • common_dialogs.dart
    • editable.dart
    • marquee.dart
    • no_network.dart
  3. app.dart

widgets

initial_screen.dart

import 'package:flutter/material.dart';
import 'package:module_block_event/blocs/user/user_state.dart';
import 'package:module_block_event/screens/page/reason.dart';

import 'login.dart';

 getInitialScreen(bool authenticated, UserState userState) {

if (authenticated == false) {
return LoginPage();
  }

if (userState != null && userState.loaded == true) {
if (userState.user != null) {
return ChooseReason();
    }
  }

return Center(child: ChooseReason());
}

login.dart                       

import 'package:device_id/device_id.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:module_block_event/blocs/register/register_bloc.dart';
import 'package:module_block_event/blocs/register/register_state.dart';
import 'package:module_block_event/blocs/user/user_bloc.dart';
import 'package:module_block_event/helpers/vars.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/screens/widgets/animatedbutton.dart';
import 'package:module_block_event/screens/widgets/editable.dart';

import 'initial_screen.dart';

class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() =>_LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  RegisterBloc registerBloc;
  UserBloc userBloc;
final LoginErrorMessageController loginErrorMessageController =
LoginErrorMessageController();

@override
void initState() {
super.initState();

    setState(() {
registerBloc = BlocProvider.of<RegisterBloc>(context);
userBloc = BlocProvider.of<UserBloc>(context);
    });
  }

  setUid() async {
    String uid = await DeviceId.getID;
registerBloc.setUid(uid);
  }

@override
Widget build(BuildContext context) {
return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          children: [
Expanded(
              child: Container(
                padding: EdgeInsets.all(10.0),
                alignment: Alignment.center,
                width: double.infinity,
                child: Text(
"FlutterTutorial",
                  style: TextStyle(
                    fontFamily: '$ralewayFont',
                    fontWeight: FontWeight.bold,
                    fontSize: 36.0,
                    letterSpacing: 2.0,
                    color: Colors.orange,
                  ),
                ),
              ),
            ),
BlocBuilder(bloc: registerBloc,
              builder: (BuildContext context, RegisterState state) {
return EditableFormField(
                  maxLength: 10,
                  keyboardType: TextInputType.number,
                  controller: null,
                  labelText: "Mobile",
//errorText: getErrorText(state, 'mobile'),
onChanged: registerBloc.onChangeMobile,
                );
              },
            ),
BlocBuilder(bloc: registerBloc,
              builder: (BuildContext context, RegisterState state) {
return EditableFormField(
                  keyboardType: TextInputType.number,
                  controller: null,
                  labelText: "Password",
                  onChanged: registerBloc.onChangePassword,
                );
              },
            ),
BlocBuilder(bloc: registerBloc,
                builder: (BuildContext context, RegisterState state) {
if (state.error != null && state.error.containsKey('error')) {
loginErrorMessageController
.showErrorMessage('Loading'); //state.error['error']
}
return new AnimatedButton(
                    loginErrorMessageController: loginErrorMessageController,
                    loginTip: 'Login',
                    onTap: () async {
                      onRegisterDevice();
loginErrorMessageController.showErrorMessage("Loading");
                    },
                  );
                }),
Container(height: 30.0),
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Center(
                child: Container(
                  child: RaisedButton(
                    elevation: 40.0,
                    color: Colors.white,
                    splashColor: Colors.orangeAccent,
                    onPressed: () {
//do nothing
},
                    shape: CircleBorder(
                      side: BorderSide(style: BorderStyle.none),
                    ),
                    child: Center(
                      child: Padding(
                        padding: const EdgeInsets.all(10),
                        child: Icon(
                          FontAwesomeIcons.google,
                          color: Color(0xffCE107c),
                          size: 30.0,
                        ),
                      ),
                    ),
                  ),
                ),
              ),
Center(
                child: Container(
                  child: RaisedButton(
                    elevation: 40.0,
                    color: Colors.white,
                    splashColor: Colors.orangeAccent,
                    onPressed: () {
//do nothing
},
                    shape: CircleBorder(
                      side: BorderSide(style: BorderStyle.none),
                    ),
                    child: Center(
                      child: Padding(
                        padding: const EdgeInsets.all(10),
                        child: Icon(
                          FontAwesomeIcons.facebookF,
                          color: Color.fromRGBO(59, 89, 152, 1.0),
                          size: 30.0,
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ]),
Container(height: 30.0),
          ],
        ),
      ),
    );
  }

void onRegisterDevice() async {
registerBloc.registerDevice((results) {
if (results != false) {
        User user = results;
userBloc.setAuthToken(user.id.toString());
userBloc.setAuthUser(results);

         Navigator.pushReplacement(
context,
MaterialPageRoute(
            builder: (BuildContext context) {
return getInitialScreen(true, userBloc.currentState);
            },
          ),
        );
      } else {}
    });
  }
}

reason.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:module_block_event/blocs/reason/reason_bloc.dart';
import 'package:module_block_event/blocs/reason/reason_state.dart';
import 'package:module_block_event/helpers/vars.dart';
import 'package:module_block_event/models/reason.dart';

class ChooseReason extends StatefulWidget {
@override
_ChooseReasonState createState() =>_ChooseReasonState();
}

class _ChooseReasonState extends State<ChooseReason> {
  ReasonBloc reasonBloc;
  String keywords;

@override
void initState() {
super.initState();

    setState(() {
reasonBloc = BlocProvider.of<ReasonBloc>(context);
    });

if (reasonBloc.currentState.loaded == false) {
reasonBloc.getSchool();
    }
  }

@override
Widget build(BuildContext context) {
return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: BlocBuilder(
          bloc: reasonBloc,
          builder: (context, ReasonState state) {
if (state.loading) {
return Center(child: CircularProgressIndicator());
            }

var reasonList = state.reasons;
if (keywords != null) {
              reasonList = state.reasons.where((school) {
return school.description
.toLowerCase()
                    .contains(keywords.toLowerCase());
              }).toList();
            }

return Column(
              children: <Widget>[
Container(
                  margin: EdgeInsets.all(20.0),
                  child: TextField(
                    onChanged: (value) {
                      setState(() {
keywords = value;
                      });
                    },
                    style: TextStyle(
                      color: Colors.black,
                      fontSize: 18.0,
                      fontFamily: '$ralewayFont',
                    ),
                    keyboardType: TextInputType.text,
                    decoration: InputDecoration(
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.black,
                        ),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.black,
                        ),
                      ),
                      labelText: "Filter Reason",
                      labelStyle: TextStyle(
                        color: Colors.black87,
                        fontSize: 18.0,
                        fontFamily: '$ralewayFont',
                      ),
                    ),
                  ),
                ),
Expanded(
                  child: Container(
                    margin: EdgeInsets.only(left: 20.0, right: 20),
                    child: ListView.builder(
                      itemCount: reasonList.length,
                      itemBuilder: (BuildContext context, index) {
final Reason reason = reasonList[index];
return InkWell(
                          borderRadius: BorderRadius.circular(50.0),
                          highlightColor: Colors.blueGrey,
                          onTap: () {

                          },
                          child: Container(
                            padding: EdgeInsets.all(10.0),
                            child: Text(
'${reason.description}',
                              style: TextStyle(
                                color: Colors.black,
                                fontSize: 15.0,
                                fontFamily: '$ralewayFont',
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}

animatedbutton.dart

import 'dart:math';

import 'package:flutter/material.dart';

typedef Future OnTap();

class AnimatedButton extends StatefulWidget {
final String loginTip;
final double width, height;
final double indicatorStarRadian;
final double indicatorWidth;
final Color buttonColorNormal;
final Color buttonColorError;
final Color indicatorColor;
final TextStyle textStyleNormal;
final TextStyle textStyleError;
final OnTap onTap;
final LoginErrorMessageController loginErrorMessageController;
final Duration showErrorTime;

  AnimatedButton({
this.height: 40.0,
this.width: 200.0,
this.loginTip: "Button",
this.indicatorStarRadian: 0.0,
this.indicatorWidth: 2.0,
this.buttonColorNormal: Colors.grey,
this.buttonColorError: Colors.grey,
this.indicatorColor: Colors.black26,
this.textStyleNormal: const TextStyle(fontSize: 16.0, color: Colors.orangeAccent),
this.textStyleError: const TextStyle(fontSize: 16.0, color: Colors.black26),
@required this.onTap,
this.loginErrorMessageController,
this.showErrorTime: const Duration(milliseconds: 2000),
  });

@override
State<StatefulWidget> createState() {
return new AnimatedButtonState();
  }
}

class AnimatedButtonState extends State<AnimatedButton>
with TickerProviderStateMixin<AnimatedButton> {
  Animation<double>animationStart;
  AnimationController controllerStart;

  Animation<double>animationEnd;
  AnimationController controllerEnd;

  Animation<double>animationRecover;
  AnimationController controllerRecover;

  AnimationController animationControllerWait;
  double widgetWidth, widgetHeight;
  bool isReset = false;
  bool isNeedRecoverLoginState = false;

  Color _buttonColor;
  String _loginTextTip;
  double _recoverCircleRadius = 0.0;
  TextStyle _textStyle;
  bool _isInAnimation = false;
  bool _assumeLoadFail = false;

@override
void initState() {
super.initState();
if (widget.loginErrorMessageController != null) {
widget.loginErrorMessageController.loginState = this;
    }
widgetWidth = widget.width;
widgetHeight = widget.height;
_buttonColor = widget.buttonColorNormal;
_loginTextTip = widget.loginTip;
_textStyle = widget.textStyleNormal;

animationControllerWait = new AnimationController(
        duration: const Duration(milliseconds: 1000 * 100), vsync: this);

controllerStart = new AnimationController(
        duration: const Duration(milliseconds: 380), vsync: this);
controllerEnd = new AnimationController(
        duration: const Duration(milliseconds: 380), vsync: this);
controllerRecover = new AnimationController(
        duration: const Duration(milliseconds: 300), vsync: this);

    initAnimationStart();
    initAnimationEnd();
    initAnimationRecover();
  }

void changeErrorMsg(String msg) {
if (mounted) {
      setState(() {
_assumeLoadFail = true;
_loginTextTip = msg;
_textStyle = widget.textStyleError;
_buttonColor = widget.buttonColorError;
      });
    }
  }

void initAnimationRecover() {
animationRecover =
new Tween(begin: 0.0, end: widgetWidth).animate(controllerRecover)
          ..addListener(() {
if (mounted) {
              setState(() {
_recoverCircleRadius = animationRecover.value;
              });
            }
          });

animationRecover.addStatusListener((animationStatus) {
if (animationStatus == AnimationStatus.completed) {
isNeedRecoverLoginState = false;
_loginTextTip = widget.loginTip;
_textStyle = widget.textStyleNormal;
_buttonColor = widget.buttonColorNormal;
controllerRecover.reset();
_isInAnimation = false;
      } else if (animationStatus == AnimationStatus.forward) {
isNeedRecoverLoginState = true;
      }
    });
  }

void initAnimationStart() {
animationStart = new Tween(begin: widgetWidth, end: widgetHeight)
        .animate(controllerStart)
          ..addListener(() {
if (isReset) {
return;
            }
if (mounted) {
              setState(() {
widgetWidth = animationStart.value;
              });
            }
          });

animationStart.addStatusListener((animationStatus) {
if (animationStatus == AnimationStatus.completed) {
isReset = true;
controllerStart.reset();
isReset = false;
animationControllerWait.forward();
        handleAnimationEnd();
      } else if (animationStatus == AnimationStatus.forward) {}
    });
  }

void initAnimationEnd() {
animationEnd =
new Tween(begin: widgetHeight, end: widget.width).animate(controllerEnd)
          ..addListener(() {
if (isReset) {
return;
            }
if (mounted) {
              setState(() {
widgetWidth = animationEnd.value;
              });
            }
          });

animationEnd.addStatusListener((animationStatus) async {
if (animationStatus == AnimationStatus.completed) {
isReset = true;
controllerEnd.reset();
isReset = false;
await Future.delayed(widget.showErrorTime);
if (mounted) {
controllerRecover.forward();
        }
      } else if (animationStatus == AnimationStatus.forward) {}
    });
  }

void handleAnimationEnd() async {
_assumeLoadFail = false;
await widget.onTap();
if (mounted &&_assumeLoadFail) {
animationControllerWait.stop();
animationControllerWait.reset();
controllerEnd.forward();
    }
  }

@override
void dispose() {
controllerStart.dispose();
animationControllerWait.dispose();
controllerRecover.dispose();
controllerEnd.dispose();
super.dispose();
  }

@override
Widget build(BuildContext context) {
return new GestureDetector(
      child: new RotationTransition(
        child: new CustomPaint(
          size: new Size(widgetWidth, widgetHeight),
          painter: new LoginPainter(
            width: widgetWidth,
            height: widgetHeight,
            recoverText: widget.loginTip,
            indicatorStarRadian: widget.indicatorStarRadian,
            indicatorWidth: widget.indicatorWidth,
            buttonColorShow: _buttonColor,
            indicatorColor: widget.indicatorColor,
            recoverTextStyle: widget.textStyleNormal,
            recoverButtonColor: widget.buttonColorNormal,
            isNeedRecoverLoginState: isNeedRecoverLoginState,
            recoverCircleRadius: _recoverCircleRadius,
            showText: _loginTextTip,
            showTextStyle: _textStyle,
          ),
        ),
        turns:
new Tween(begin: 0.0, end: 150.0).animate(animationControllerWait)
              ..addStatusListener((animationStatus) {
if (animationStatus == AnimationStatus.completed) {
animationControllerWait.repeat();
                }
              }),
      ),
      onTap: () {
if (!_isInAnimation) {
_isInAnimation = true;
controllerStart.forward();
        }
      },
    );
  }
}

class LoginPainter extends CustomPainter {
final double width, height;
final String recoverText;
final double indicatorRadian = 4.71238898038469;
final double indicatorStarRadian;

final double indicatorWidth;
  double isoscelesTriangle;

final Color indicatorColor;
final TextStyle recoverTextStyle;
final bool isNeedRecoverLoginState;
final Color recoverButtonColor;
final Color buttonColorShow;
final double recoverCircleRadius;
final String showText;
final TextStyle showTextStyle;

  LoginPainter({
this.width,
this.height,
this.recoverText,
this.indicatorStarRadian,
this.indicatorWidth,
this.recoverButtonColor,
this.buttonColorShow,
this.indicatorColor,
this.recoverTextStyle,
this.isNeedRecoverLoginState,
this.recoverCircleRadius,
this.showText,
this.showTextStyle,
  }) {
isoscelesTriangle = indicatorWidth * 1.5;
  }

@override
void paint(Canvas canvas, Size size) {
    Paint paint = new Paint();
    paint.color = buttonColorShow;
    double halfHeight = height / 2;
if (height <width) {
      drawCornerButton(canvas, paint, halfHeight, showText, showTextStyle);
    } else {
      drawCircleButton(canvas, paint, halfHeight);
    }

if (isNeedRecoverLoginState) {
      paint.color = recoverButtonColor;
      Paint layerPaint = Paint();
      canvas.saveLayer(
new Rect.fromLTWH(0.0, 0.0, recoverCircleRadius, size.height),
          layerPaint);
      drawCornerButton(
          canvas, paint, halfHeight, recoverText, recoverTextStyle);

      layerPaint.blendMode = BlendMode.dstIn;

      canvas.saveLayer(
new Rect.fromLTWH(0.0, 0.0, recoverCircleRadius, size.height),
          layerPaint);
      canvas.drawCircle(new Offset(0.0, 0.0), recoverCircleRadius, paint);
      canvas.restore();
      canvas.restore();
    }
  }

void drawCircleButton(Canvas canvas, Paint paint, double halfHeight) {
    canvas.drawCircle(new Offset(halfHeight, halfHeight), halfHeight, paint);
    paint.color = indicatorColor;
    paint.style = PaintingStyle.stroke;
    paint.strokeWidth = indicatorWidth;
    double smallCircleRadius = halfHeight / 2;
    canvas.drawArc(
new Rect.fromLTRB(smallCircleRadius, smallCircleRadius,
height - smallCircleRadius, height - smallCircleRadius),
indicatorStarRadian,
indicatorRadian,
false,
        paint);

    double radian = indicatorStarRadian + indicatorRadian;

    Path path = getPath(smallCircleRadius, radian);

    canvas.save();
    canvas.translate(halfHeight, halfHeight);
    canvas.drawPath(path, paint);

    canvas.restore();
  }

void drawCornerButton(Canvas canvas, Paint paint, double halfHeight,
      String txt, TextStyle txtStyle) {
    canvas.drawCircle(new Offset(halfHeight, halfHeight), halfHeight, paint);

    double rectRight = width - halfHeight;
    canvas.drawRect(
new Rect.fromLTRB(halfHeight, 0.0, rectRight, height), paint);

    canvas.drawCircle(new Offset(rectRight, halfHeight), halfHeight, paint);

    TextPainter textPainter = new TextPainter();
    textPainter.textDirection = TextDirection.ltr;
    textPainter.text = new TextSpan(text: txt, style: txtStyle);
    textPainter.layout();
    double textStarPositionX = (width - textPainter.size.width) / 2;
    double textStarPositionY = (height - textPainter.size.height) / 2;
    textPainter.paint(canvas, new Offset(textStarPositionX, textStarPositionY));
  }

  Path getPath(double radius, double radian) {
    Path path = new Path();

    double yPoint = sin(radian) * radius;
    double xPoint = cos(radian) * radius;

    double halfSide = isoscelesTriangle / 2;
    path.moveTo(xPoint, yPoint + halfSide);

    path.lineTo(xPoint, yPoint - halfSide);

    double xVertex =
        xPoint + sqrt(pow(isoscelesTriangle, 2) - pow(halfSide, 2));
    path.lineTo(xVertex, yPoint);

    path.close();
return path;
  }

@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
  }
}

class LoginErrorMessageController {
  AnimatedButtonState loginState;

void showErrorMessage(String errorMsg) {
if (loginState != null) {
loginState.changeErrorMsg(errorMsg);
    }
  }
}

common_dialogs.dart

import 'package:flutter/material.dart';
import 'package:module_block_event/helpers/vars.dart';

/*toast(String msg) {
  Fluttertoast.showToast(
      msg: msg,
      toastLength: Toast.LENGTH_SHORT,
      gravity: ToastGravity.BOTTOM,
      backgroundColor: Colors.white,
      textColor: Colors.black);
}*/

showSuccess(BuildContext context, String message, IconData icon) {
  showDialog(
      context: context,
      builder: (context) =>Center(
            child: Material(
              borderRadius: BorderRadius.circular(8.0),
              color: Colors.black,
              elevation: 5.0,
              child: Padding(
                padding: const EdgeInsets.all(32.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
Icon(
                      icon,
                      color: Colors.green,
                    ),
SizedBox(
                      height: 10.0,
                    ),
Text(
                      message,
                      style: TextStyle(
                          fontFamily: '$ralewayFont', color: Colors.white),
                    )
                  ],
                ),
              ),
            ),
          ));
}

showProgress(BuildContext context) {
  showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) =>Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.orange,
            ),
          ));
}

hideProgress(BuildContext context) {
  Navigator.pop(context);
}

editable.dart

import 'package:flutter/material.dart';
import 'package:module_block_event/helpers/vars.dart';

class EditableFormField extends StatelessWidget {
final TextEditingController controller;
final String labelText;
final String errorText;
final Function onChanged;
final int maxLength;
final TextInputType keyboardType;

  EditableFormField({
    Key key,
@required this.controller,
@required this.labelText,
@required this.errorText,
@required this.onChanged,
this.maxLength,
this.keyboardType,
  });

@override
Widget build(BuildContext context) {
return Container(
      padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
      child: TextField(
        maxLength: maxLength ?? null,
        controller: controller,
        onChanged: onChanged,
        style: TextStyle(
          color: Colors.black87,
          fontSize: 14.0,
          fontFamily: '$ralewayFont',
        ),
        keyboardType: this.keyboardType ?? TextInputType.text,
        decoration: InputDecoration(
          errorText: errorText,
          contentPadding: EdgeInsets.all(15.0),
          border: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.black87,
            ),
          ),
          disabledBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.black87,
            ),
          ),
          enabledBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.black87,
            ),
          ),
          focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.black87,
            ),
          ),
          errorBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.red,
            ),
          ),
          focusedErrorBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Colors.red,
            ),
          ),
          errorStyle: TextStyle(
            color: Colors.red,
          ),
          labelText: labelText,
          labelStyle: TextStyle(
            color: Colors.black87,
            fontSize: 14.0,
            fontFamily: '$ralewayFont',
          ),
        ),
      ),
    );
  }
}

marquee.dart

import 'dart:async';

import 'package:flutter/material.dart';

class MarqueeWidget extends StatefulWidget {
final String text;
final TextStyle textStyle;
final Axis scrollAxis;
final double ratioOfBlankToScreen;

  MarqueeWidget({
@required this.text,
this.textStyle,
this.scrollAxis: Axis.horizontal,
this.ratioOfBlankToScreen: 0.25,
  }) : assert(text != null,);

@override
State<StatefulWidget> createState() {
return new MarqueeWidgetState();
  }
}

class MarqueeWidgetState extends State<MarqueeWidget>
with SingleTickerProviderStateMixin {
  ScrollController scroController;
  double screenWidth;
  double screenHeight;
  double position = 0.0;
  Timer timer;
final double _moveDistance = 3.0;
final int _timerRest = 100;
  GlobalKey _key = GlobalKey();

@override
void initState() {
super.initState();
scroController = new ScrollController();
    WidgetsBinding.instance.addPostFrameCallback((callback) {
      startTimer();
    });
  }

void startTimer() {
    double widgetWidth =
_key.currentContext.findRenderObject().paintBounds.size.width;
    double widgetHeight =
_key.currentContext.findRenderObject().paintBounds.size.height;

timer = Timer.periodic(new Duration(milliseconds: _timerRest), (timer) {
      double maxScrollExtent = scroController.position.maxScrollExtent;
      double pixels = scroController.position.pixels;
if (pixels + _moveDistance >= maxScrollExtent) {
if (widget.scrollAxis == Axis.horizontal) {
position = (maxScrollExtent -
screenWidth * widget.ratioOfBlankToScreen +
                      widgetWidth) /
2 -
              widgetWidth +
              pixels -
              maxScrollExtent;
        } else {
position = (maxScrollExtent -
screenHeight * widget.ratioOfBlankToScreen +
                      widgetHeight) /
2 -
              widgetHeight +
              pixels -
              maxScrollExtent;
        }
scroController.jumpTo(position);
      }
position += _moveDistance;
scroController.animateTo(position,
          duration: new Duration(milliseconds: _timerRest),
          curve: Curves.linear);
    });
  }

@override
void didChangeDependencies() {
super.didChangeDependencies();
screenWidth = MediaQuery.of(context).size.width;
screenHeight = MediaQuery.of(context).size.height;
  }

  Widget getBothEndsChild() {
if (widget.scrollAxis == Axis.vertical) {
      String newString = widget.text.split("").join("\n");
return new Center(
        child: new Text(
          newString,
          style: widget.textStyle,
          textAlign: TextAlign.center,
        ),
      );
    }
return new Center(
        child: new Text(
widget.text,
      style: widget.textStyle,
    ));
  }

  Widget getCenterChild() {
if (widget.scrollAxis == Axis.horizontal) {
return new Container(width: screenWidth * widget.ratioOfBlankToScreen);
    } else {
return new Container(height: screenHeight * widget.ratioOfBlankToScreen);
    }
  }

@override
void dispose() {
super.dispose();
timer.cancel();
  }

@override
Widget build(BuildContext context) {
return new ListView(
      key: _key,
      scrollDirection: widget.scrollAxis,
      controller: scroController,
      physics: new NeverScrollableScrollPhysics(),
      children: <Widget>[
        getBothEndsChild(),
        getCenterChild(),
        getBothEndsChild(),
      ],
    );
  }
}

/*
new Container(
          color: Colors.blueGrey,
          height: 30,
          child: new MarqueeWidget(
            text: "kamlesh´╝îlakhani",
            textStyle: new TextStyle(fontSize: 16.0),
            scrollAxis: Axis.horizontal,
          ),
        )
*/

no_network.dart

import 'package:flutter/material.dart';
import 'package:module_block_event/helpers/vars.dart';

class NoNetwork extends StatefulWidget {
@override
_NoNetwork createState() =>_NoNetwork();
}

class _NoNetwork extends State<NoNetwork>with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
      backgroundColor: Colors.black,
      body: SafeArea(
        child: Center(
          child: Text(
"No Internet",
            style: TextStyle(
              color: Colors.white,
              fontSize: 36.0,
              fontFamily: '$ralewayFont',
            ),
          ),
        ),
      ),
    );
  }
}

app.dart

import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:module_block_event/blocs/user/user_bloc.dart';
import 'package:module_block_event/blocs/user/user_state.dart';
import 'package:module_block_event/screens/page/initial_screen.dart';
import 'package:module_block_event/screens/widgets/no_network.dart';

class MyApp extends StatefulWidget {
final String authToken;

  MyApp({this.authToken});

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

class _MyAppState extends State<MyApp> {
  UserBloc userBloc;
  UserState userState;

  ConnectivityResult connectivityResult;
var subscription;

@override
void initState() {
super.initState();

    checkConnection();

    setState(() {
userBloc = BlocProvider.of<UserBloc>(context);
    });

//userBloc.getAuthUser();

userBloc.state.listen((state) {
if (userState == null && state.user != null) {
        setState(() {
userState = state;
        });
      }
    });
  }

void checkConnection() {
subscription = Connectivity().onConnectivityChanged.listen(
      (ConnectivityResult result) {
        setState(() =>connectivityResult = result);
      },
    );
  }

@override
void dispose() {
subscription.cancel();
super.dispose();
  }

@override
Widget build(BuildContext context) {
return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(platform: TargetPlatform.iOS),
      home: connectivityResult == ConnectivityResult.none
? NoNetwork()
          : getInitialScreen(widget.authToken != null, userState),
    );
  }
}

service package

  1. abstract
    • -api_service.dart
  2. di
    • dependency_injection.dart
  3. mock
    • mock_service.dart
  4. network
    • network_service.dart
  5. network_service_response.dart
  6. network_type.dart
  7. restclient.dart

api_service.dart

import 'dart:async';

import 'package:module_block_event/models/reason.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/service/network_service_response.dart';

abstract class APIService {
  Future<NetworkServiceResponse<User>> login(String phoneNumber, String password);
  Future<NetworkServiceResponse<List<Reason>>>postPonCancelReasonList();
}

dependency_injection.dart

dependency_injection.dart
import 'package:module_block_event/service/abstract/api_service.dart';
import 'package:module_block_event/service/mock/mock_service.dart';
import 'package:module_block_event/service/network/network_service.dart';
import 'package:module_block_event/service/restclient.dart';

enum Flavor {Testing, Network}

//Simple DI
class Injector {
static final Injector _singleton = new Injector._internal();
static Flavor _flavor;

static void configure(Flavor flavor) async {
_flavor = flavor;
  }

factory Injector() =>_singleton;

  Injector._internal();

  APIService get flavor {
switch (_flavor) {
case Flavor.Testing:
return MockService();
default:
return NetworkService(new RestClient());
    }
  }
}

mock_service.dart

import 'dart:async';

import 'package:module_block_event/helpers/vars.dart';
import 'package:module_block_event/models/reason.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/service/abstract/api_service.dart';
import 'package:module_block_event/viewmodel/reason_postpone_cancel_view_model.dart';
import 'package:module_block_event/service/network_service_response.dart';

class MockService implements APIService {
@override
Future<NetworkServiceResponse<User>> login(
      String phoneNumber, String password) async {
await Future.delayed(Duration(seconds: 2));
return Future.value(NetworkServiceResponse(
        responseCode: ok200,
        response: User(
          id: 000,
          name: 'Lakhani kamlesh',
          mobile: '9586331823',
          message: '',
        )));
  }

@override
Future<NetworkServiceResponse<List<Reason>>> postPonCancelReasonList() {
final _reasonPostPoneCancelVM = ReasonPostPoneCancelViewModel();
return Future.value(NetworkServiceResponse(
        responseCode: ok200,
        response: _reasonPostPoneCancelVM.getReasonPostPoneCancel()));
  }
}

network_service.dart

import 'dart:async';
import 'dart:convert';

import 'package:module_block_event/models/reason.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/service/abstract/api_service.dart';
import 'package:module_block_event/service/network_service_response.dart';
import 'package:module_block_event/service/network_type.dart';
import 'package:module_block_event/service/restclient.dart';

class NetworkService extends NetworkType implements APIService {
static final _baseUrl = '';
final _loginUrl = _baseUrl + '';

//PICKUP - DISPATCH UNDELIVERED REASON LIST
final _postPoneCancelReasonListUrl = _baseUrl + '';

  Map<String, String>headers = {
"Content-Type": 'application/json',
  };

  NetworkService(RestClient rest) : super(rest);

@override
Future<NetworkServiceResponse<User>> login(
      String phoneNumber, String password) async {
var result = await rest.get<User>(
'$_loginUrl?MobileNo=$phoneNumber&Password=$password&DeviceId=""',
headers);
if (result.mappedResult != null) {
var res = User.fromJson(json.decode(result.mappedResult));
return new NetworkServiceResponse(
          response: res,
          responseCode: result.networkServiceResponse.responseCode);
    }
return new NetworkServiceResponse(
        responseCode: result.networkServiceResponse.responseCode);
  }

@override
Future<NetworkServiceResponse<List<Reason>>> postPonCancelReasonList() async {
var result =
await rest.get<Reason>('$_postPoneCancelReasonListUrl', headers);
if (result.networkServiceResponse.responseCode == 200) {
      List<Reason> list = (json.decode(result.mappedResult) as List)
          .map((data) =>new Reason.fromJson(data))
          .toList();
return new NetworkServiceResponse(
          response: list,
          responseCode: result.networkServiceResponse.responseCode);
    }
return new NetworkServiceResponse(
        responseCode: result.networkServiceResponse.responseCode);
  }
}

network_service_response.dart

class NetworkServiceResponse<T> {
  T response;
  int responseCode;

  NetworkServiceResponse({this.response, this.responseCode});
}

class MappedNetworkServiceResponse<T> {
dynamic mappedResult;
  NetworkServiceResponse<T>networkServiceResponse;
  MappedNetworkServiceResponse(
      {this.mappedResult, this.networkServiceResponse});
}

network_type.dart

import'package:module_block_event/service/restclient.dart';

abstract class NetworkType {
  RestClient rest;
  NetworkType(this.rest);
}

restclient.dart

import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:module_block_event/helpers/vars.dart';
import 'package:module_block_event/service/network_service_response.dart';

class RestClient {
  Future<MappedNetworkServiceResponse<T>> get<T>(String url, Map headers) async{
try {
var response = await http.get(url, headers: headers);
return processResponse<T>(response);

    }
catch(e) {
return new MappedNetworkServiceResponse<T>(
          networkServiceResponse: new NetworkServiceResponse<T>(
              responseCode: 0));
    }
  }

  Future<MappedNetworkServiceResponse<T>> post<T>(String url, {Map headers, body, encoding}) async{
try {
var response = await http.post(url, headers: headers, body: body, encoding: encoding);
return processResponse<T>(response);
    }
catch(e) {
return new MappedNetworkServiceResponse<T>(
          networkServiceResponse: new NetworkServiceResponse<T>(
              responseCode: 0));
    }
  }

  MappedNetworkServiceResponse<T> processResponse<T>(http.Response response) {
if ((response.statusCode > ok200)) {
return new MappedNetworkServiceResponse<T>(
          networkServiceResponse: new NetworkServiceResponse<T>(
              responseCode: response.statusCode));
    } else {
return new MappedNetworkServiceResponse<T>(
          mappedResult: response.body,
          networkServiceResponse:
new NetworkServiceResponse<T>(responseCode: response.statusCode));
    }
  }
}

viewmodel package

api_provider.dart

import 'dart:async';
import 'package:module_block_event/models/reason.dart';
import 'package:module_block_event/models/user.dart';
import 'package:module_block_event/service/abstract/api_service.dart';
import 'package:module_block_event/service/di/dependency_injection.dart';
import 'package:module_block_event/service/network_service_response.dart';

class ApiProvider {
  NetworkServiceResponse apiResult;
  APIService apiService = new Injector().flavor;

  Future<Null> getLogin(String phoneNumber, String password) async {
    NetworkServiceResponse<User> result =
await apiService.login(phoneNumber, password);
this.apiResult = result;
  }

  Future<Null> getPostPonCancelReasonList() async {
    NetworkServiceResponse<List<Reason>> result =
await apiService.postPonCancelReasonList();
this.apiResult = result;
  }
}

reason_postpone_cancel_view_model.dart

import 'package:module_block_event/models/reason.dart';

class ReasonPostPoneCancelViewModel {
  List<Reason>reasonUndeliveredItems;

  ReasonPostPoneCancelViewModel({this.reasonUndeliveredItems});

  getReasonPostPoneCancel() =>
<Reason>[
Reason(
          id: 1,
          description: 'ADDRESS CHANGED',
        ),
Reason(
          id: 2,
          description: 'BACKUP PENDING',
        )
      ];
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:module_block_event/blocs/reason/reason_bloc.dart';
import 'package:module_block_event/blocs/user/user_bloc.dart';
import 'package:module_block_event/screens/app.dart';
import 'package:module_block_event/service/di/dependency_injection.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'blocs/register/register_bloc.dart';

void main() async {
  Injector.configure(Flavor.Testing);

  SharedPreferences prefs = await SharedPreferences.getInstance();
  String authToken = prefs.getString("authToken");

  runApp(MaterialApp(
    home: BlocProvider(
      builder: (context) =>UserBloc(),
      child: BlocProvider(
        builder: (context) =>RegisterBloc(),
        child: BlocProvider(
            builder: (context) =>ReasonBloc(),
          child: MyApp(authToken: authToken),
      ),
    )
  )));
}

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