login, sign up, forgot password & otp ui added.

development
Sikander Saleem 5 years ago
parent 408179122e
commit b6cab77867

@ -0,0 +1,7 @@
<svg viewBox="0 0 17.3 17.3" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 1" id="Layer_1-2">
<rect style="fill: #606161" height="17.3" rx="2.52" width="17.3"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 243 B

@ -0,0 +1,10 @@
<svg viewBox="0 0 17.3 17.3" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 1" id="Layer_1-2">
<g>
<rect style="fill: #606161" height="17.3" rx="2.52" width="17.3"/>
<polygon style="fill: #fff" points="7.9 13.3 2.94 8.34 4.47 6.8 7.9 10.23 13.14 5 14.67 6.53 7.9 13.3"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 379 B

@ -0,0 +1,12 @@
<svg viewBox="0 0 22.66 15.58" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 1" id="Layer_1-2">
<g>
<polygon style="fill: #868787" points="15.02 7.91 22.66 12.73 22.66 2.87 15.02 7.91"/>
<polygon style="fill: #868787" points="0 2.87 0 12.73 7.64 7.91 0 2.87"/>
<path style="fill: #868787" d="M21.24,0H1.42A1.41,1.41,0,0,0,0,1.21L11.33,8.64,22.61,1.21A1.39,1.39,0,0,0,21.24,0Z"/>
<path style="fill: #868787" d="M13.72,8.76l-2,1.32a.71.71,0,0,1-.39.12.69.69,0,0,1-.39-.12l-2-1.32L.05,14.38a1.39,1.39,0,0,0,1.37,1.2H21.24a1.4,1.4,0,0,0,1.37-1.2Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 671 B

@ -0,0 +1,35 @@
<svg viewBox="0 0 135.86 104.03" xmlns="http://www.w3.org/2000/svg">
<g data-name="Layer 2" id="Layer_2">
<g data-name="Layer 1" id="Layer_1-2">
<g>
<g>
<g>
<path style="fill: #1a2e35" d="M106.65,55.74A30.07,30.07,0,1,0,60,48.6l-6.12,5.71,1.47,10.16-9.5-2.66L38.19,69,39.65,79.1l-9.5-2.66-6.58,6.14.89,6.19-5.78-1.62-3.83,3.57-.58,9.41,14,3.53L73.82,61.19A30.08,30.08,0,0,0,106.65,55.74Zm-4.45-37A8.62,8.62,0,1,1,90,18.34,8.63,8.63,0,0,1,102.2,18.76Z"/>
<g>
<path style="fill: none" d="M106.65,55.74A30.07,30.07,0,1,0,60,48.6l-6.12,5.71,1.47,10.16-9.5-2.66L38.19,69,39.65,79.1l-9.5-2.66-6.58,6.14.89,6.19-5.78-1.62-3.83,3.57-.58,9.41,14,3.53L73.82,61.19A30.08,30.08,0,0,0,106.65,55.74Zm-4.45-37A8.62,8.62,0,1,1,90,18.34,8.63,8.63,0,0,1,102.2,18.76Z"/>
<path style="fill: #1a2e35" d="M102.2,18.76c0,.06-.56-.52-1.71-1.23a8.6,8.6,0,0,0-5.43-1.19,8.3,8.3,0,1,0,9.07,9.71,8.53,8.53,0,0,0-.82-5.49c-.62-1.2-1.17-1.75-1.11-1.8s.16.11.42.38a6.88,6.88,0,0,1,.95,1.28,8.57,8.57,0,0,1,1.08,5.72,8.91,8.91,0,0,1-10.42,7.34A8.91,8.91,0,0,1,87,25.7a8.89,8.89,0,0,1,8-9.89,8.62,8.62,0,0,1,5.64,1.47,7.13,7.13,0,0,1,1.21,1C102.1,18.6,102.22,18.75,102.2,18.76Z"/>
<path style="fill: #374061" d="M106.65,55.74s-.14.15-.43.42l-1.33,1.18A31.89,31.89,0,0,1,99.07,61a30.2,30.2,0,0,1-25.34.37l.24,0L28.53,103.9l-.13.13-.18,0-14-3.52-.28-.07v-.29c.18-2.94.37-6.15.57-9.41v-.14l.1-.1,3.83-3.58.15-.14.2.06,5.78,1.62-.46.4c-.28-1.93-.58-4-.89-6.19l0-.19.14-.13,6.58-6.14.15-.14.2,0,9.5,2.66-.47.42c-.47-3.22-1-6.68-1.47-10.16l0-.19.14-.14,2-1.89,5.62-5.25.16-.14.2.06,9.5,2.66-.47.41c-.5-3.42-1-6.81-1.46-10.15l0-.2.14-.13,6.12-5.7-.07.45A30.76,30.76,0,0,1,55.76,35.1a30.76,30.76,0,0,1,2.5-13.5,30.36,30.36,0,0,1,55.05-1.26,30.15,30.15,0,0,1,3,15.78,29.68,29.68,0,0,1-3.37,11.58l-.56,1.07-.62.95c-.41.61-.75,1.21-1.14,1.71-.81,1-1.43,1.86-2,2.47l-1.39,1.39-.48.45s.14-.18.44-.5l1.34-1.43c.59-.62,1.19-1.51,2-2.49.38-.51.71-1.11,1.11-1.72.2-.3.4-.62.6-1s.36-.7.54-1.07a30.12,30.12,0,0,0,.22-27,29.79,29.79,0,0,0-54,1.33A28.31,28.31,0,0,0,57,28.27a28,28,0,0,0-.48,6.79,30.06,30.06,0,0,0,3.83,13.36l.14.26-.21.19-6.11,5.71.11-.32q.72,5,1.46,10.15l.09.57-.56-.15-9.49-2.66.36-.09-5.63,5.25-2,1.89.12-.33c.5,3.49,1,6.94,1.46,10.16l.08.57-.55-.16-9.5-2.66.36-.09-6.59,6.14.12-.32c.3,2.13.61,4.26.89,6.19l.08.55-.55-.15L18.58,87.5l.34-.09L15.09,91l.12-.24c-.21,3.26-.4,6.48-.58,9.41l-.27-.36,14,3.54-.31.08L73.66,61l.11-.11.14.06A30.14,30.14,0,0,0,99,60.81a33.23,33.23,0,0,0,5.84-3.57l1.36-1.13C106.48,55.86,106.65,55.74,106.65,55.74Z"/>
</g>
</g>
<g>
<path style="fill: #e4697b" d="M105.64,52.33A30.07,30.07,0,1,0,59,45.19h0l-6.11,5.7,1.46,10.15-9.5-2.66-7.65,7.15,1.46,10.15L29.15,73l-6.58,6.14.89,6.19-5.79-1.62-3.83,3.57-.57,9.4,14,3.53L72.81,57.78A30.09,30.09,0,0,0,105.64,52.33Zm-4.45-37A8.62,8.62,0,1,1,89,14.93,8.62,8.62,0,0,1,101.19,15.35Z"/>
<g>
<path style="fill: none" d="M105.64,52.33A30.07,30.07,0,1,0,59,45.19h0l-6.11,5.7,1.46,10.15-9.5-2.66-7.65,7.15,1.46,10.15L29.15,73l-6.58,6.14.89,6.19-5.79-1.62-3.83,3.57-.57,9.4,14,3.53L72.81,57.78A30.09,30.09,0,0,0,105.64,52.33Zm-4.45-37A8.62,8.62,0,1,1,89,14.93,8.62,8.62,0,0,1,101.19,15.35Z"/>
<path style="fill: #1a2e35" d="M101.19,15.35c0,.06-.56-.53-1.71-1.23a8.54,8.54,0,0,0-5.43-1.19,8.3,8.3,0,1,0,9.07,9.71,8.65,8.65,0,0,0-.81-5.5c-.63-1.19-1.18-1.74-1.12-1.79s.16.11.42.37a6.37,6.37,0,0,1,1,1.28,8.6,8.6,0,0,1,1.08,5.73A8.94,8.94,0,1,1,94,12.4a8.56,8.56,0,0,1,5.64,1.47,7.13,7.13,0,0,1,1.21,1C101.1,15.18,101.21,15.33,101.19,15.35Z"/>
<path style="fill: #1a2e35" d="M105.64,52.33l-.43.41-1.33,1.18a30.62,30.62,0,0,1-5.82,3.7,30.24,30.24,0,0,1-10.68,2.87A30.72,30.72,0,0,1,72.72,58L73,58c-11.74,11-27.34,25.59-45.44,42.54l-.14.13-.18-.05-14-3.51L12.9,97l0-.29c.17-2.93.37-6.15.56-9.4v-.15l.11-.09,3.82-3.58.15-.14.2.06L23.55,85l-.46.4c-.27-1.93-.58-4-.89-6.19l0-.19.14-.13,6.58-6.14.15-.14.21,0,9.49,2.66-.47.41c-.46-3.21-1-6.67-1.46-10.15l0-.2.14-.13,2-1.89,5.63-5.25.15-.14.2.05,9.5,2.67-.47.41Q53.22,56,52.5,51l0-.19.14-.13,6.12-5.71-.07.45a30.67,30.67,0,0,1-3.9-13.69,29.26,29.26,0,0,1,.49-6.95,29,29,0,0,1,2-6.54,30.29,30.29,0,0,1,58,14.52,29.9,29.9,0,0,1-3.38,11.58l-.56,1.07c-.21.33-.42.64-.61,1-.41.61-.75,1.21-1.15,1.71-.81,1-1.43,1.85-2,2.46l-1.39,1.39-.49.46s.14-.18.44-.51l1.34-1.42c.59-.63,1.2-1.51,2-2.5.38-.5.71-1.1,1.1-1.71.2-.31.4-.62.6-.95l.55-1.07A29.82,29.82,0,1,0,57.89,18.46,29.7,29.7,0,0,0,56,24.85a28.6,28.6,0,0,0-.48,6.8A30.06,30.06,0,0,0,59.3,45l.14.25-.21.2-6.11,5.71.11-.32c.49,3.35,1,6.73,1.47,10.15l.08.57-.55-.16-9.5-2.66.36-.08-5.63,5.25-2,1.89.12-.33c.5,3.48,1,6.94,1.46,10.16l.08.57-.55-.16-9.49-2.66.35-.09-6.58,6.14.11-.32c.31,2.13.61,4.25.89,6.19l.08.55-.54-.15-5.79-1.63.35-.08c-1.33,1.24-2.65,2.46-3.83,3.57l.11-.24c-.2,3.26-.4,6.47-.58,9.41l-.27-.37,14,3.55-.32.08,45.6-42.39.11-.1.13.06A30.14,30.14,0,0,0,98,57.4a32.71,32.71,0,0,0,5.85-3.58l1.36-1.12A4.8,4.8,0,0,1,105.64,52.33Z"/>
</g>
</g>
<path style="fill: #1a2e35" d="M102.88,50a40.43,40.43,0,0,0,4-5.09A25.49,25.49,0,0,0,110,38a26.4,26.4,0,0,0,.86-10A26.15,26.15,0,0,0,96.69,7.38,24.55,24.55,0,0,0,89.58,5a30.38,30.38,0,0,0-3.86-.45,31.08,31.08,0,0,0-4,.2A26,26,0,0,0,59.2,25.78a29.25,29.25,0,0,0-.47,3.93,29.56,29.56,0,0,0,.18,3.89,24.44,24.44,0,0,0,1.9,7.26A26.26,26.26,0,0,0,90.4,56.26a25.3,25.3,0,0,0,7.12-2.6A40.53,40.53,0,0,0,102.88,50a1.79,1.79,0,0,1-.3.31c-.25.21-.56.49-.94.84A12.58,12.58,0,0,1,100,52.4a18.31,18.31,0,0,1-2.36,1.51,25,25,0,0,1-7.17,2.76A26.71,26.71,0,0,1,69,52.19a26.85,26.85,0,0,1-8.79-11.06,25.28,25.28,0,0,1-2-7.45,31.09,31.09,0,0,1-.2-4,29.42,29.42,0,0,1,.48-4.05A26.65,26.65,0,0,1,81.68,4a29.26,29.26,0,0,1,4.07-.19,30.37,30.37,0,0,1,4,.46A25.5,25.5,0,0,1,97,6.76a26.87,26.87,0,0,1,10.42,9.53,26.64,26.64,0,0,1,3,21.79,24.92,24.92,0,0,1-3.25,7,19.08,19.08,0,0,1-1.67,2.25,11.42,11.42,0,0,1-1.38,1.52l-.9.88A1.53,1.53,0,0,1,102.88,50Z"/>
<path style="fill: #1a2e35" d="M101.66,28.64c-.06-.05.63-.64,1.46-2a10,10,0,0,0,1.43-6.38,9.84,9.84,0,0,0-5.35-7.71,9.8,9.8,0,0,0-11.08,1.57,9.85,9.85,0,0,0-2.93,5.31,9.64,9.64,0,0,0,.59,5.63A9.85,9.85,0,0,0,89,29.14a9.7,9.7,0,0,0,4.15,1.8,10,10,0,0,0,6.47-1c1.4-.74,2-1.39,2.09-1.33s-.14.18-.45.48a7.64,7.64,0,0,1-1.5,1.1A10,10,0,0,1,93,31.47,10.39,10.39,0,0,1,84.47,19.3a10.42,10.42,0,0,1,9.06-8.45,10.3,10.3,0,0,1,6,1.09,10.47,10.47,0,0,1,4,3.73,10.22,10.22,0,0,1,1.51,4.54,10.06,10.06,0,0,1-1.7,6.6,7.76,7.76,0,0,1-1.21,1.42C101.85,28.52,101.68,28.66,101.66,28.64Z"/>
<path style="fill: #1a2e35" d="M23.62,98.58c-.14-.15,10.11-9.94,22.89-21.87s23.26-21.47,23.4-21.32S59.81,65.33,47,77.26,23.76,98.73,23.62,98.58Z"/>
</g>
<path style="fill: #ff4f5b" d="M29.27,39l.42-.93.55.85a4.34,4.34,0,0,0,1.83,1.56l.92.41-.85.56a4.28,4.28,0,0,0-1.55,1.82l-.41.93-.56-.85a4.25,4.25,0,0,0-1.83-1.55l-.92-.42.85-.56A4.22,4.22,0,0,0,29.27,39Z"/>
<path style="fill: #ff4f5b" d="M1.4,32l.24-.54L2,32a2.5,2.5,0,0,0,1.06.9l.54.24-.5.32a2.58,2.58,0,0,0-.9,1.06l-.24.54-.32-.49a2.44,2.44,0,0,0-1.06-.9L0,33.42l.49-.33A2.53,2.53,0,0,0,1.4,32Z"/>
<path style="fill: #ff4f5b" d="M89.16,79.54,89.4,79l.33.49a2.44,2.44,0,0,0,1.06.9l.54.24-.5.33a2.45,2.45,0,0,0-.9,1.06l-.24.54-.32-.5a2.5,2.5,0,0,0-1.06-.9l-.54-.24.49-.32A2.44,2.44,0,0,0,89.16,79.54Z"/>
<path style="fill: #ff4f5b" d="M132.14,55.18l.41-.93.56.85a4.22,4.22,0,0,0,1.82,1.55l.93.42-.85.56a4.22,4.22,0,0,0-1.55,1.82l-.42.93-.56-.85A4.22,4.22,0,0,0,130.66,58l-.93-.42.85-.56A4.31,4.31,0,0,0,132.14,55.18Z"/>
<path style="fill: #ff4f5b" d="M126.54,21.06l.7-1.56.93,1.43a7.21,7.21,0,0,0,3.07,2.61l1.56.7-1.43.93a7.14,7.14,0,0,0-2.61,3.07l-.7,1.56-.94-1.43a7.12,7.12,0,0,0-3.06-2.61l-1.56-.7,1.43-.94A7.18,7.18,0,0,0,126.54,21.06Z"/>
<path style="fill: #ff4f5b" d="M20.61,10.54,21.31,9l.93,1.43A7.21,7.21,0,0,0,25.31,13l1.56.69-1.43.94a7.12,7.12,0,0,0-2.61,3.06l-.7,1.56-.94-1.43a7.09,7.09,0,0,0-3.06-2.6l-1.56-.7L18,13.6A7.18,7.18,0,0,0,20.61,10.54Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

@ -16,6 +16,7 @@ class Const {
static Color textGrey = Color(0xff787F95);
static Color textGrey1 = Color(0xffA6A8BA);
static Color textGrey2 = Color(0xff868787);
static Color textHintGrey = Color(0xffcccccc);
static Color sliderBackground = Color(0xffdfdfdf);

@ -0,0 +1,9 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
class Utils {
static void showToast(String message) {
Fluttertoast.showToast(
msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 1, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
}
}

@ -0,0 +1,7 @@
extension EmailValidator on String {
bool isValidEmail() {
return RegExp(
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(this);
}
}

@ -3,7 +3,10 @@ import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tangheem/ui/common_appbar.dart';
import 'package:tangheem/ui/screens/forgot_password_screen.dart';
import 'package:tangheem/ui/screens/home_screen.dart';
import 'package:tangheem/ui/screens/login_screen.dart';
import 'package:tangheem/ui/screens/registration_screen.dart';
import 'package:tangheem/ui/screens/surah_screen.dart';
import 'package:tangheem/ui/screens/tangheem_screen.dart';
import 'classes/const.dart';
@ -13,30 +16,39 @@ void main() {
}
class Application extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tangheem',
theme: lightTheme(),
debugShowCheckedModeBanner: false,
initialRoute: HomeScreen.routeName,
onGenerateRoute: (settings) {
var className;
switch (settings.name) {
case HomeScreen.routeName:
className = CommonAppbar(showDrawer: true, child: HomeScreen());
break;
case TangheemScreen.routeName:
className = CommonAppbar(child: TangheemScreen());
break;
case SurahScreen.routeName:
String query = settings.arguments.toString();
className = CommonAppbar(child: SurahScreen(query: query));
break;
}
return goToNavigation(className);
});
title: 'Tangheem',
theme: lightTheme(),
debugShowCheckedModeBanner: false,
initialRoute: LoginScreen.routeName,
onGenerateRoute: (settings) {
var className;
switch (settings.name) {
case LoginScreen.routeName:
className = CommonAppbar(isFirst: true, child: LoginScreen());
break;
case RegistrationScreen.routeName:
className = CommonAppbar(child: RegistrationScreen());
break;
case ForgotPasswordScreen.routeName:
className = CommonAppbar(child: ForgotPasswordScreen());
break;
case HomeScreen.routeName:
className = CommonAppbar(showDrawer: true, child: HomeScreen());
break;
case TangheemScreen.routeName:
className = CommonAppbar(child: TangheemScreen());
break;
case SurahScreen.routeName:
String query = settings.arguments.toString();
className = CommonAppbar(child: SurahScreen(query: query));
break;
}
return goToNavigation(className);
},
);
}
PageRoute goToNavigation(var className) {

@ -5,8 +5,9 @@ import 'package:tangheem/classes/const.dart';
class CommonAppbar extends StatefulWidget {
final bool showDrawer;
final Widget child;
final bool isFirst;
CommonAppbar({Key key, this.showDrawer = false, @required this.child}) : super(key: key);
CommonAppbar({Key key, this.showDrawer = false, @required this.child, this.isFirst = false}) : super(key: key);
@override
_CommonAppbarState createState() {
@ -42,20 +43,21 @@ class _CommonAppbarState extends State<CommonAppbar> {
height: 100,
padding: EdgeInsets.only(top: 8, bottom: 8, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
icon: Icon(widget.showDrawer ? Icons.menu : Icons.arrow_back_ios, color: Const.textGrey),
padding: EdgeInsets.only(left: 16),
onPressed: () {
if (widget.showDrawer) {
_scaffoldKey.currentState.openDrawer();
} else {
Navigator.pop(context);
}
},
),
if (!widget.isFirst)
IconButton(
icon: Icon(widget.showDrawer ? Icons.menu : Icons.arrow_back_ios, color: Const.textGrey),
padding: EdgeInsets.only(left: 16),
onPressed: () {
if (widget.showDrawer) {
_scaffoldKey.currentState.openDrawer();
} else {
Navigator.pop(context);
}
},
),
Expanded(child: SizedBox()),
Hero(
tag: "logo",
child: SvgPicture.asset(
@ -68,7 +70,9 @@ class _CommonAppbarState extends State<CommonAppbar> {
],
),
),
Expanded(child: Directionality(textDirection: TextDirection.rtl, child: widget.child)),
Expanded(
child: Directionality(textDirection: TextDirection.rtl, child: widget.child),
),
],
),
),

@ -0,0 +1,118 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:tangheem/classes/const.dart';
import 'package:tangheem/widgets/otp_widget.dart';
class OTPDialog extends StatefulWidget {
OTPDialog({Key key}) : super(key: key);
@override
_OTPDialogState createState() {
return _OTPDialogState();
}
}
class _OTPDialogState extends State<OTPDialog> {
final TextEditingController _pinPutController = TextEditingController();
final FocusNode _pinPutFocusNode = FocusNode();
bool hasError = false;
String errorMessage;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Dialog(
insetPadding: EdgeInsets.symmetric(horizontal: 60.0, vertical: 24.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Const.primaryBlue,
borderRadius: BorderRadius.circular(16),
),
padding: EdgeInsets.symmetric(vertical: 32, horizontal: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"الرجاء ادخال الرقم المرسل الى جوالك",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
Container(
// width: double.infinity,
margin: EdgeInsets.only(top: 8, bottom: 8),
padding: EdgeInsets.all(6),
decoration: BoxDecoration(
// color: Colors.white,
border: Border.all(width: 1, color: Colors.white),
),
child: OTPWidget(
autofocus: true,
controller: _pinPutController,
defaultBorderColor: Colors.transparent,
maxLength: 4,
hasError: hasError,
onTextChanged: (text) {
setState(() {
hasError = false;
});
},
pinBoxColor: Const.secondaryWhite.withOpacity(0.2),
onDone: (text) {},
textBorderColor: Colors.transparent,
pinBoxWidth: 40,
pinBoxHeight: 40,
pinTextStyle: TextStyle(fontSize: 20.0, color: Colors.white),
pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition,
pinTextAnimatedSwitcherDuration: Duration(milliseconds: 300),
keyboardType: TextInputType.number,
),
),
SizedBox(
width: double.infinity,
height: 40,
child: TextButton(
onPressed: () {
Navigator.pop(context);
},
style: TextButton.styleFrom(
primary: Colors.white,
padding: EdgeInsets.all(2),
backgroundColor: Const.secondaryPink,
textStyle: TextStyle(fontSize: 14, fontFamily: "DroidKufi"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
child: Text("تحقق من الرقم"),
),
),
],
),
),
);
}
BoxDecoration get _pinPutDecoration {
return BoxDecoration(
color: Const.secondaryWhite.withOpacity(0.2),
//border: Border.all(color: Colors.deepPurpleAccent),
//borderRadius: BorderRadius.circular(0.0),
);
}
}

@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tangheem/classes/const.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/ui/dialogs/opt_dialog.dart';
import 'package:tangheem/widgets/common_textfield_widget.dart';
class ForgotPasswordScreen extends StatefulWidget {
static const String routeName = "/forgot_password";
ForgotPasswordScreen({Key key}) : super(key: key);
@override
_ForgotPasswordScreenState createState() {
return _ForgotPasswordScreenState();
}
}
class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
TextEditingController _usernameController = TextEditingController();
TextEditingController _emailController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Const.secondaryWhite,
body: SingleChildScrollView(
padding: EdgeInsets.all(32.0),
physics: BouncingScrollPhysics(),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8.0), color: Colors.white),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 36, bottom: 24),
child: SvgPicture.asset("assets/icons/key.svg", width: 100, height: 100),
),
Text(
"نسيت كلمة المرور؟",
style: TextStyle(fontSize: 22, color: Const.primaryBlue),
),
Container(
margin: EdgeInsets.only(top: 16),
width: double.infinity,
padding: EdgeInsets.all(32.0),
decoration: BoxDecoration(
color: Const.primaryBlue,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CommonTextFieldWidget(hint: "اسم المستخدم", controller: _usernameController, prefixIcon: "assets/icons/user.svg"),
SizedBox(height: 8),
Text(
"-أو-",
style: TextStyle(color: Colors.white),
),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "الايميل المسجل", controller: _emailController, prefixIcon: "assets/icons/email.svg"),
SizedBox(height: 12),
SizedBox(
width: double.infinity,
height: 50,
child: TextButton(
onPressed: () {
if (_usernameController.text.length < 1) {
Utils.showToast("Username is empty.");
return;
}
if (_emailController.text.length < 1) {
Utils.showToast("Email is empty.");
return;
}
getOTP();
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Const.secondaryPink,
textStyle: TextStyle(fontSize: 16, fontFamily: "DroidKufi"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
child: Text("اعادة تعيين كلمة المرور"),
),
),
],
),
),
],
),
),
),
);
}
getOTP() {
showDialog(
context: context,
barrierColor: Const.secondaryWhite.withOpacity(0.8),
builder: (BuildContext context) => OTPDialog(),
);
}
}

@ -9,7 +9,7 @@ import 'package:tangheem/ui/screens/tangheem_screen.dart';
import 'package:tangheem/widgets/common_dropdown_button.dart';
class HomeScreen extends StatefulWidget {
static const String routeName = "/";
static const String routeName = "/home";
HomeScreen({Key key}) : super(key: key);

@ -0,0 +1,169 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tangheem/classes/const.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/ui/screens/forgot_password_screen.dart';
import 'package:tangheem/ui/screens/registration_screen.dart';
import 'package:tangheem/widgets/common_textfield_widget.dart';
import 'home_screen.dart';
class LoginScreen extends StatefulWidget {
static const String routeName = "/";
LoginScreen({Key key}) : super(key: key);
@override
_LoginScreenState createState() {
return _LoginScreenState();
}
}
class _LoginScreenState extends State<LoginScreen> {
TextEditingController _usernameController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
bool _isRemember = true;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Const.secondaryWhite,
body: SafeArea(
child: Directionality(
textDirection: TextDirection.rtl,
child: SingleChildScrollView(
padding: EdgeInsets.all(32.0),
physics: BouncingScrollPhysics(),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8.0), color: Colors.white),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 24, bottom: 24),
child: SvgPicture.asset("assets/logos/tangheem_logo.svg", width: 100, height: 100),
),
Text(
"تسجيل الدخول",
style: TextStyle(fontSize: 22, color: Const.primaryBlue),
),
Container(
margin: EdgeInsets.only(top: 16),
width: double.infinity,
padding: EdgeInsets.all(32.0),
color: Const.primaryBlue,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CommonTextFieldWidget(hint: "اسم المستخدم", controller: _usernameController, prefixIcon: "assets/icons/user.svg"),
SizedBox(height: 16),
CommonTextFieldWidget(hint: "كلمة المرور", controller: _passwordController, isPassword: true, prefixIcon: "assets/icons/password.svg"),
SizedBox(height: 16),
SizedBox(
width: double.infinity,
height: 50,
child: TextButton(
onPressed: () {
if (_usernameController.text.length < 1) {
Utils.showToast("Username is empty.");
return;
}
if (_passwordController.text.length < 1) {
Utils.showToast("Password is empty.");
return;
}
Navigator.pushNamed(context, HomeScreen.routeName);
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Const.secondaryPink,
textStyle: TextStyle(fontSize: 16, fontFamily: "DroidKufi"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
child: Text("تسجيل الدخول"),
),
),
SizedBox(height: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"تذكرني",
style: TextStyle(color: Colors.white),
),
SizedBox(width: 8),
InkWell(
onTap: () {
setState(() {
_isRemember = !_isRemember;
});
},
child: SvgPicture.asset(_isRemember ? "assets/icons/checkOn.svg" : "assets/icons/checkOff.svg", width: 16, height: 16))
],
),
InkWell(
onTap: () {
Navigator.pushNamed(context, ForgotPasswordScreen.routeName);
},
child: Text(
"نسيت كلمة المرور؟",
style: TextStyle(color: Colors.white),
),
),
],
),
],
),
),
InkWell(
onTap: () {
Navigator.pushNamed(context, RegistrationScreen.routeName);
},
child: Container(
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Const.tertiaryPurple,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"انشاء حساب جديد",
style: TextStyle(fontSize: 14, color: Colors.white),
),
Icon(Icons.arrow_forward_ios, color: Colors.white, size: 12),
],
),
),
)
],
),
),
),
),
),
);
}
}

@ -0,0 +1,183 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tangheem/classes/const.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/widgets/common_textfield_widget.dart';
import 'file:///C:/Users/sikander.saleem/Documents/AndroidStudioProjects/tangheem/lib/extensions/email_validator.dart';
class RegistrationScreen extends StatefulWidget {
static const String routeName = "/registration";
RegistrationScreen({Key key}) : super(key: key);
@override
_RegistrationScreenState createState() {
return _RegistrationScreenState();
}
}
class _RegistrationScreenState extends State<RegistrationScreen> {
TextEditingController _usernameController = TextEditingController();
TextEditingController _fullNameController = TextEditingController();
TextEditingController _emailController = TextEditingController();
TextEditingController _mobileNumberController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
TextEditingController _confirmPasswordController = TextEditingController();
bool _isAccept = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Const.secondaryWhite,
body: SingleChildScrollView(
padding: EdgeInsets.all(32.0),
physics: BouncingScrollPhysics(),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8.0), color: Colors.white),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 24, bottom: 24),
child: SvgPicture.asset("assets/logos/tangheem_logo.svg", width: 100, height: 100),
),
Text(
"انشاء حساب جديد",
style: TextStyle(fontSize: 22, color: Const.primaryBlue),
),
Padding(
padding: EdgeInsets.all(8),
child: Text(
"قم بتعبئة بيانات طلب انشاء الحساب و ستصلك رسالة تأكيد, ومن ثم يمكنك الدخول لحسابك الجديد",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Const.primaryBlue, height: 1),
),
),
Container(
margin: EdgeInsets.only(top: 16),
width: double.infinity,
padding: EdgeInsets.all(32.0),
decoration: BoxDecoration(
color: Const.primaryBlue,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CommonTextFieldWidget(hint: "اسم المستخدم", controller: _usernameController),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "الايميل المسجل", controller: _fullNameController),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "الايميل", controller: _emailController),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "البلد", controller: _mobileNumberController, showSuffix: true),
SizedBox(height: 8),
CommonTextFieldWidget(hint: " رقم الجوال (9xx xxxxxxxxx+)", controller: _mobileNumberController),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "تعيين كلمة المرور", controller: _passwordController),
SizedBox(height: 8),
CommonTextFieldWidget(hint: "تأكيد كلمة المرور", controller: _confirmPasswordController),
SizedBox(height: 8),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: () {
setState(() {
_isAccept = !_isAccept;
});
},
child: SvgPicture.asset(_isAccept ? "assets/icons/checkOn.svg" : "assets/icons/checkOff.svg", width: 16, height: 16),
),
SizedBox(width: 8),
Expanded(
child: Text(
"أقر بأني إطلعت على شروط الاستخدام و سياسية الخصوصية و أوافق عليها",
style: TextStyle(color: Colors.white, fontSize: 13),
),
),
],
),
SizedBox(height: 12),
SizedBox(
width: double.infinity,
height: 50,
child: TextButton(
onPressed: () {
if (_usernameController.text.length < 1) {
Utils.showToast("Username is empty.");
return;
}
if (_fullNameController.text.length < 1) {
Utils.showToast("Name is empty.");
return;
}
if (_emailController.text.length < 1) {
Utils.showToast("Email is empty.");
return;
}
if (_mobileNumberController.text.length < 1) {
Utils.showToast("Phone number is empty.");
return;
}
if (_passwordController.text.length < 1) {
Utils.showToast("Password is empty.");
return;
}
if (_confirmPasswordController.text.length < 1) {
Utils.showToast("Enter same password to confirm");
return;
}
if (!_emailController.text.isValidEmail()) {
Utils.showToast("Invalid email.");
return;
}
if (_passwordController.text != _confirmPasswordController.text) {
Utils.showToast("Your passwords are incorrect.");
return;
}
if (!_isAccept) {
Utils.showToast("You must accept statement to proceed.");
return;
}
Utils.showToast("اعادة تعيين كلمة المرور");
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Const.secondaryPink,
textStyle: TextStyle(fontSize: 16, fontFamily: "DroidKufi"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
child: Text("انشئ حسابك"),
),
),
],
),
),
],
),
),
),
);
}
}

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tangheem/classes/const.dart';
class CommonTextFieldWidget extends StatelessWidget {
final String hint;
final TextEditingController controller;
final bool isPassword;
final String prefixIcon;
final bool showSuffix;
CommonTextFieldWidget({Key key, @required this.hint, @required this.controller, this.isPassword = false, this.prefixIcon, this.showSuffix = false}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: 50,
child: TextField(
textAlignVertical: TextAlignVertical.center,
controller: controller,
obscureText: isPassword,
textInputAction: TextInputAction.next,
style: TextStyle(color: Const.primaryBlack, fontSize: 14),
cursorColor: Const.primaryBlue,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(4, 4, 8, 4),
alignLabelWithHint: true,
fillColor: Colors.white,
filled: true,
hintStyle: TextStyle(color: Const.textGrey2, fontSize: 14),
hintText: hint,
suffixIcon: !showSuffix
? null
: Padding(
padding: EdgeInsets.only(left: 8, right: 0),
child: Icon(Icons.keyboard_arrow_down, size: 18, color: Const.secondaryOrange),
),
suffixIconConstraints: !showSuffix ? null : BoxConstraints(maxHeight: 30),
prefixIconConstraints: prefixIcon == null ? prefixIcon : BoxConstraints(maxHeight: 18),
prefixIcon: prefixIcon == null
? prefixIcon
: Padding(
padding: EdgeInsets.only(left: 4, right: 0),
child: SvgPicture.asset(prefixIcon, color: Const.textGrey2),
),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(6), borderSide: BorderSide.none),
),
),
);
}
}

@ -0,0 +1,381 @@
import 'dart:async';
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
typedef OnDone = void Function(String text);
class ProvidedPinBoxTextAnimation {
static AnimatedSwitcherTransitionBuilder scalingTransition = (child, animation) {
return ScaleTransition(
child: child,
scale: animation,
);
};
static AnimatedSwitcherTransitionBuilder defaultNoTransition = (Widget child, Animation<double> animation) {
return child;
};
}
class OTPWidget extends StatefulWidget {
final bool isCupertino;
final int maxLength;
final TextEditingController controller;
final Color defaultBorderColor;
final Color pinBoxColor;
final double pinBoxBorderWidth;
final double pinBoxRadius;
final bool hideDefaultKeyboard;
final TextStyle pinTextStyle;
final double pinBoxHeight;
final double pinBoxWidth;
final OnDone onDone;
final bool hasError;
final Color errorBorderColor;
final Color textBorderColor;
final Function(String) onTextChanged;
final bool autofocus;
final FocusNode focusNode;
final AnimatedSwitcherTransitionBuilder pinTextAnimatedSwitcherTransition;
final Duration pinTextAnimatedSwitcherDuration;
final TextDirection textDirection;
final TextInputType keyboardType;
final EdgeInsets pinBoxOuterPadding;
const OTPWidget({
Key key,
this.isCupertino: false,
this.maxLength: 4,
this.controller,
this.pinBoxWidth: 70.0,
this.pinBoxHeight: 70.0,
this.pinTextStyle,
this.onDone,
this.defaultBorderColor: Colors.black,
this.textBorderColor: Colors.black,
this.pinTextAnimatedSwitcherTransition,
this.pinTextAnimatedSwitcherDuration: const Duration(),
this.hasError: false,
this.errorBorderColor: Colors.red,
this.onTextChanged,
this.autofocus: false,
this.focusNode,
this.textDirection: TextDirection.ltr,
this.keyboardType: TextInputType.number,
this.pinBoxOuterPadding = const EdgeInsets.symmetric(horizontal: 4.0),
this.pinBoxColor = Colors.white,
this.pinBoxBorderWidth = 2.0,
this.pinBoxRadius = 0,
this.hideDefaultKeyboard = false,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return OTPWidgetState();
}
}
class OTPWidgetState extends State<OTPWidget> with SingleTickerProviderStateMixin {
AnimationController _highlightAnimationController;
Animation _highlightAnimationColorTween;
FocusNode focusNode;
String text = "";
int currentIndex = 0;
List<String> strList = [];
bool hasFocus = false;
@override
void didUpdateWidget(OTPWidget oldWidget) {
super.didUpdateWidget(oldWidget);
focusNode = widget.focusNode ?? focusNode;
if (oldWidget.maxLength < widget.maxLength) {
setState(() {
currentIndex = text.length;
});
widget.controller?.text = text;
widget.controller?.selection = TextSelection.collapsed(offset: text.length);
} else if (oldWidget.maxLength > widget.maxLength && widget.maxLength > 0 && text.length > 0 && text.length > widget.maxLength) {
setState(() {
text = text.substring(0, widget.maxLength);
currentIndex = text.length;
});
widget.controller?.text = text;
widget.controller?.selection = TextSelection.collapsed(offset: text.length);
}
}
_calculateStrList() async {
if (strList.length > widget.maxLength) {
strList.length = widget.maxLength;
}
while (strList.length < widget.maxLength) {
strList.add("");
}
}
@override
void initState() {
super.initState();
focusNode = widget.focusNode ?? FocusNode();
_initTextController();
_calculateStrList();
widget.controller?.addListener(_controllerListener);
focusNode?.addListener(_focusListener);
}
void _controllerListener() {
if (mounted == true) {
setState(() {
_initTextController();
});
var onTextChanged = widget.onTextChanged;
if (onTextChanged != null) {
onTextChanged(widget.controller?.text ?? "");
}
}
}
void _focusListener() {
if (mounted == true) {
setState(() {
hasFocus = focusNode?.hasFocus ?? false;
});
}
}
void _initTextController() {
if (widget.controller == null) {
return;
}
strList.clear();
var text = widget.controller?.text ?? "";
if (text.isNotEmpty) {
if (text.length > widget.maxLength) {
throw Exception("TextEditingController length exceeded maxLength!");
}
}
for (var i = 0; i < text.length; i++) {
strList.add(text[i]);
}
}
double get _width {
var width = 0.0;
for (var i = 0; i < widget.maxLength; i++) {
width += widget.pinBoxWidth;
if (i == 0) {
width += widget.pinBoxOuterPadding.left;
} else if (i + 1 == widget.maxLength) {
width += widget.pinBoxOuterPadding.right;
} else {
width += widget.pinBoxOuterPadding.left;
}
}
return width;
}
@override
void dispose() {
if (widget.focusNode == null) {
focusNode?.dispose();
} else {
focusNode?.removeListener(_focusListener);
}
_highlightAnimationController?.dispose();
widget.controller?.removeListener(_controllerListener);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
_otpTextInput(),
_touchPinBoxRow(),
],
);
}
Widget _touchPinBoxRow() {
return widget.hideDefaultKeyboard
? _pinBoxRow(context)
: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
if (hasFocus) {
FocusScope.of(context).requestFocus(FocusNode());
Future.delayed(Duration(milliseconds: 100), () {
FocusScope.of(context).requestFocus(focusNode);
});
} else {
FocusScope.of(context).requestFocus(focusNode);
}
},
child: _pinBoxRow(context),
);
}
Widget _otpTextInput() {
var transparentBorder = OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
width: 0.0,
),
);
return Container(
width: _width,
height: widget.pinBoxHeight,
child: TextField(
autofocus: !kIsWeb ? widget.autofocus : false,
enableInteractiveSelection: false,
focusNode: focusNode,
controller: widget.controller,
keyboardType: widget.keyboardType,
inputFormatters: widget.keyboardType == TextInputType.number ? <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly] : null,
style: TextStyle(
height: 0.1, color: Colors.transparent,
// color: Colors.transparent,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0),
focusedErrorBorder: transparentBorder,
errorBorder: transparentBorder,
disabledBorder: transparentBorder,
enabledBorder: transparentBorder,
focusedBorder: transparentBorder,
counterText: null,
counterStyle: null,
helperStyle: TextStyle(
height: 0.0,
color: Colors.transparent,
),
labelStyle: TextStyle(height: 0.1),
fillColor: Colors.transparent,
border: InputBorder.none,
),
cursorColor: Colors.transparent,
showCursor: false,
maxLength: widget.maxLength,
onChanged: _onTextChanged,
),
);
}
void _onTextChanged(text) {
var onTextChanged = widget.onTextChanged;
if (onTextChanged != null) {
onTextChanged(text);
}
setState(() {
this.text = text;
if (text.length >= currentIndex) {
for (int i = currentIndex; i < text.length; i++) {
strList[i] = text[i];
}
}
currentIndex = text.length;
});
if (text.length == widget.maxLength) {
FocusScope.of(context).requestFocus(FocusNode());
var onDone = widget.onDone;
if (onDone != null) {
onDone(text);
}
}
}
Widget _pinBoxRow(BuildContext context) {
_calculateStrList();
List<Widget> pinCodes = List.generate(widget.maxLength, (int i) {
return _buildPinCode(i, context);
});
return Row(children: pinCodes, mainAxisSize: MainAxisSize.min);
}
Widget _buildPinCode(int i, BuildContext context) {
Color borderColor;
Color pinBoxColor = widget.pinBoxColor;
if (widget.hasError) {
borderColor = widget.errorBorderColor;
} else if (i < text.length) {
borderColor = widget.textBorderColor;
} else {
borderColor = widget.defaultBorderColor;
pinBoxColor = widget.pinBoxColor;
}
EdgeInsets insets;
if (i == 0) {
insets = EdgeInsets.only(
left: 0,
top: widget.pinBoxOuterPadding.top,
right: widget.pinBoxOuterPadding.right,
bottom: widget.pinBoxOuterPadding.bottom,
);
} else if (i == strList.length - 1) {
insets = EdgeInsets.only(
left: widget.pinBoxOuterPadding.left,
top: widget.pinBoxOuterPadding.top,
right: 0,
bottom: widget.pinBoxOuterPadding.bottom,
);
} else {
insets = widget.pinBoxOuterPadding;
}
return Padding(
padding: insets,
child: Container(
key: ValueKey<String>("container$i"),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 1.0),
child: Center(
child: _animatedTextBox(strList[i], i),
),
),
decoration: BoxDecoration(
border: Border.all(
color: borderColor,
width: widget.pinBoxBorderWidth,
),
color: pinBoxColor,
borderRadius: BorderRadius.circular(widget.pinBoxRadius),
),
width: widget.pinBoxWidth,
height: widget.pinBoxHeight,
),
);
}
Widget _animatedTextBox(String text, int i) {
if (widget.pinTextAnimatedSwitcherTransition != null) {
return AnimatedSwitcher(
duration: widget.pinTextAnimatedSwitcherDuration,
transitionBuilder: widget.pinTextAnimatedSwitcherTransition ??
(Widget child, Animation<double> animation) {
return child;
},
child: Text(
text,
key: ValueKey<String>("$text$i"),
style: widget.pinTextStyle,
),
);
} else {
return Text(
text,
key: ValueKey<String>("${strList[i]}$i"),
style: widget.pinTextStyle,
);
}
}
}

@ -28,6 +28,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_svg: ^0.19.3
fluttertoast: ^7.1.8
dev_dependencies:
flutter_test:

Loading…
Cancel
Save