diff --git a/android/tutorialtest_android.iml b/android/tutorialtest_android.iml
index 1899969..3e44773 100644
--- a/android/tutorialtest_android.iml
+++ b/android/tutorialtest_android.iml
@@ -26,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/lib/core/const/color_constants.dart b/lib/core/const/color_constants.dart
new file mode 100644
index 0000000..1a77da0
--- /dev/null
+++ b/lib/core/const/color_constants.dart
@@ -0,0 +1,19 @@
+import 'dart:ui';
+
+class ColorConstants {
+ static const textColor = Color(0xFF1F2022);
+ static const primaryColor = Color(0xFF6358E1);
+ static const textBlack = Color(0xFF1F2022);
+ static const white = Color(0xFFFFFFFF);
+ static const grey = Color(0xFFB6BDC6);
+ static const loadingBlack = Color(0x80000000);
+
+ static const textFieldBackground = Color(0xFFFBFCFF);
+ static const textFieldBorder = Color (0xFFB9BBC5);
+ static const disabledColor = Color(0xFFE1E1E5);
+ static const errorColor = Color (0xFFF25252);
+ static const homeBackgroundColor = Color.fromRGBO(252, 252, 252, 1);
+ static const textGrey = Color(0xFF8F98A3);
+ static const cardioColor = Color(0xFFFCB74F);
+ static const armsColor = Color(0xFF5C9BA4);
+}
\ No newline at end of file
diff --git a/lib/core/const/data_constants.dart b/lib/core/const/data_constants.dart
new file mode 100644
index 0000000..6f0d42a
--- /dev/null
+++ b/lib/core/const/data_constants.dart
@@ -0,0 +1,25 @@
+import 'package:tutorialtest/core/const/path_constants.dart';
+import 'package:tutorialtest/core/const/text_constants.dart';
+
+import '../../screens/onboarding/widget/onboarding_tile.dart';
+
+class DataConstants {
+ // Onboarding
+ static final onboardingTiles = [
+ OnboardingTile(
+ title: TextConstants.onboarding1Title,
+ mainText: TextConstants.onboardingDescription,
+ imagePath: PathConstants.onboarding1
+ ),
+ OnboardingTile(
+ title: TextConstants.onboardingTitle,
+ mainText: TextConstants.onboardingDescription,
+ imagePath: PathConstants.onboarding2
+ ),
+ OnboardingTile(
+ title: TextConstants.onboarding3Title,
+ mainText: TextConstants.onboarding3Description,
+ imagePath: PathConstants.onboarding3
+ )
+ ];
+}
\ No newline at end of file
diff --git a/lib/core/const/path_constants.dart b/lib/core/const/path_constants.dart
new file mode 100644
index 0000000..6c7ba6a
--- /dev/null
+++ b/lib/core/const/path_constants.dart
@@ -0,0 +1,20 @@
+class PathConstants{
+ // Onboarding
+ static const String onboarding1 = 'assets/images/onboarding/onboarding.png';
+ static const String onboarding2 = 'assets/images/onboarding/onboarding_2.png';
+ static const String onboarding3 = 'assets/images/onboarding/onboarding_3.png';
+ // Auth
+ static const String eye = 'assets/images/auth/eye_icon.png';
+ // Tabbar
+ static const String home = 'assets/icons/home/home_icon.png';
+ static const String workouts = 'assets/icons/home/workouts_icon.png';
+ static const String settings = 'assets/icons/home/settings_icon.png';
+ // Home
+ static const String profile = 'assets/images/home/profile.png';
+ static const String finished = 'assets/images/home/finished.png';
+ static const String inProgress = 'assets/icons/home/inProgress.png';
+ static const String timeSent = 'assets/icons/home/time.png';
+ static const String cardio = 'assets/images/home/cardio.png';
+ static const String arms = 'assets/images/home/arms.png';
+ static const String progress = 'assets/icons/home/progress.png';
+}
\ No newline at end of file
diff --git a/lib/core/const/text_constants.dart b/lib/core/const/text_constants.dart
new file mode 100644
index 0000000..1710975
--- /dev/null
+++ b/lib/core/const/text_constants.dart
@@ -0,0 +1,12 @@
+class TextConstants {
+ // Onboarding
+ static const String onboarding1Title = "Workout anywhere";
+ static const String onboardingTitle = "Learn techniques";
+ static const String onboarding3Title = "Stay strong & healthy";
+ static const String onboardingDescription =
+ "You can do your workout at home without any equipment, outside or at the gym.";
+ static const String onboarding2Description =
+ "Our workout programs are made by professionals.";
+ static const String onboarding3Description =
+ "We want you to fully enjoy the program and stay healthy and positive.";
+}
\ No newline at end of file
diff --git a/lib/core/extensions/exceptions.dart b/lib/core/extensions/exceptions.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/extensions/list_extension.dart b/lib/core/extensions/list_extension.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/auth_service.dart b/lib/core/service/auth_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/date_service.dart b/lib/core/service/date_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/notification_service.dart b/lib/core/service/notification_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/user_service.dart b/lib/core/service/user_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/user_storage_service.dart b/lib/core/service/user_storage_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/core/service/validation_service.dart b/lib/core/service/validation_service.dart
new file mode 100644
index 0000000..e69de29
diff --git a/lib/main.dart b/lib/main.dart
index ac22c56..c6542ec 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,29 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:tutorialtest/screens/onboarding/page/onboarding_page.dart';
+
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
- await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final isLoggedIn = FirebaseAuth.instance.currentUser != null;
-
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Fitness',
theme: ThemeData(
- textTheme:
- TextTheme(bodyText1: TextStyle(color: ColorConstants.textColor)),
fontFamily: 'NotoSansKR',
scaffoldBackgroundColor: Colors.white,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
- home: isLoggedIn ? TabBarPage() : OnboardingPage(),
+ //home: isLoggedIn ? TabBarPage() : OnboardingPage(),
+ home: OnboardingPage(),
);
}
}
\ No newline at end of file
diff --git a/lib/screens/onboarding/bloc/onboarding_bloc.dart b/lib/screens/onboarding/bloc/onboarding_bloc.dart
new file mode 100644
index 0000000..e953583
--- /dev/null
+++ b/lib/screens/onboarding/bloc/onboarding_bloc.dart
@@ -0,0 +1,37 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'onboarding_event.dart';
+import 'onboarding_state.dart';
+
+class OnboardingBloc extends Bloc {
+ OnboardingBloc() : super(OnboardingInitial());
+
+ int pageIndex = 0;
+
+ final pageController = PageController(initialPage: 0);
+
+ @override
+ Stream mapEventToState(
+ OnboardingEvent event,
+ ) async* {
+ if (event is PageChangedEvent) {
+ if (pageIndex == 2) {
+ yield NextScreenState();
+ return;
+ }
+ pageIndex += 1;
+
+ pageController.animateToPage(
+ pageIndex,
+ duration: Duration(milliseconds: 500),
+ curve: Curves.ease,
+ );
+
+ yield PageChangedState(counter: pageIndex);
+ } else if (event is PageSwipedEvent) {
+ pageIndex = event.index;
+ yield PageChangedState(counter: pageIndex);
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/screens/onboarding/bloc/onboarding_event.dart b/lib/screens/onboarding/bloc/onboarding_event.dart
new file mode 100644
index 0000000..9843cbc
--- /dev/null
+++ b/lib/screens/onboarding/bloc/onboarding_event.dart
@@ -0,0 +1,16 @@
+//part of 'onboarding_bloc.dart';
+
+import 'package:flutter/material.dart';
+
+@immutable
+abstract class OnboardingEvent {}
+
+class PageChangedEvent extends OnboardingEvent {
+
+}
+
+class PageSwipedEvent extends OnboardingEvent {
+ final int index;
+
+ PageSwipedEvent({required this.index});
+}
\ No newline at end of file
diff --git a/lib/screens/onboarding/bloc/onboarding_state.dart b/lib/screens/onboarding/bloc/onboarding_state.dart
new file mode 100644
index 0000000..50a16bc
--- /dev/null
+++ b/lib/screens/onboarding/bloc/onboarding_state.dart
@@ -0,0 +1,18 @@
+//part of 'onboarding_bloc.dart';
+
+import 'package:flutter/material.dart';
+
+@immutable
+abstract class OnboardingState {}
+
+class OnboardingInitial extends OnboardingState {}
+
+class PageChangedState extends OnboardingState {
+ final int counter;
+
+ PageChangedState({
+ required this.counter,
+ });
+}
+
+class NextScreenState extends OnboardingState {}
\ No newline at end of file
diff --git a/lib/screens/onboarding/page/onboarding_page.dart b/lib/screens/onboarding/page/onboarding_page.dart
new file mode 100644
index 0000000..003e8f2
--- /dev/null
+++ b/lib/screens/onboarding/page/onboarding_page.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import '../bloc/onboarding_bloc.dart';
+import '../bloc/onboarding_state.dart';
+import '../widget/onboarding_content.dart';
+
+class OnboardingPage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: _buildBody(context),
+ );
+ }
+
+ BlocProvider _buildBody(BuildContext context) {
+ return BlocProvider(
+ create: (BuildContext context) => OnboardingBloc(),
+ child: BlocConsumer(
+ listenWhen: (_, currState) => currState is NextScreenState,
+ listener: (context, state) {
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (_) {
+ //return SignUpPage();
+ return Text('Test');
+ },
+ ),
+ );
+ },
+ buildWhen: (_, currState) => currState is OnboardingInitial,
+ builder: (context, state) {
+ return OnboardingContent();
+ },
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/screens/onboarding/widget/onboarding_content.dart b/lib/screens/onboarding/widget/onboarding_content.dart
new file mode 100644
index 0000000..1fefe46
--- /dev/null
+++ b/lib/screens/onboarding/widget/onboarding_content.dart
@@ -0,0 +1,114 @@
+import 'package:dots_indicator/dots_indicator.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:percent_indicator/circular_percent_indicator.dart';
+
+import '../../../core/const/color_constants.dart';
+import '../../../core/const/data_constants.dart';
+import '../bloc/onboarding_bloc.dart';
+import '../bloc/onboarding_event.dart';
+import '../bloc/onboarding_state.dart';
+
+class OnboardingContent extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ final bloc = BlocProvider.of(context);
+ return SafeArea(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Expanded(
+ flex: 4,
+ child: _createPageView(bloc.pageController, bloc),
+ ),
+ Expanded(
+ flex: 2,
+ child: _createStatic(bloc),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _createPageView(PageController controller, OnboardingBloc bloc) {
+ return PageView(
+ scrollDirection: Axis.horizontal,
+ controller: controller,
+ children: DataConstants.onboardingTiles,
+ onPageChanged: (index) {
+ bloc.add(PageSwipedEvent(index: index));
+ },
+ );
+ }
+
+ Widget _createStatic(OnboardingBloc bloc) {
+ return Column(
+ children: [
+ SizedBox(
+ height: 30,
+ ),
+ BlocBuilder(
+ buildWhen: (_, currState) => currState is PageChangedState,
+ builder: (context, state) {
+ return DotsIndicator(
+ dotsCount: 3,
+ position: bloc.pageIndex.toDouble(),
+ decorator: DotsDecorator(
+ color: Colors.grey,
+ activeColor: ColorConstants.primaryColor,
+ ),
+ );
+ },
+ ),
+ Spacer(),
+ BlocBuilder(
+ buildWhen: (_, currState) => currState is PageChangedState,
+ builder: (context, state) {
+ final percent = _getPercent(bloc.pageIndex);
+ return TweenAnimationBuilder(
+ tween: Tween(begin: 0, end: percent),
+ duration: Duration(seconds: 1),
+ builder: (context, value, _) => CircularPercentIndicator(
+ radius: 110,
+ backgroundColor: ColorConstants.primaryColor,
+ progressColor: Colors.white,
+ percent: 1 - value,
+ center: Material(
+ shape: CircleBorder(),
+ color: ColorConstants.primaryColor,
+ child: RawMaterialButton(
+ shape: CircleBorder(),
+ onPressed: () {
+ bloc.add(PageChangedEvent());
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(24.0),
+ child: Icon(
+ Icons.east_rounded,
+ size: 38.0,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ ));
+ },
+ ),
+ SizedBox(height: 30),
+ ],
+ );
+ }
+
+ double _getPercent(int pageIndex) {
+ switch (pageIndex) {
+ case 0:
+ return 0.25;
+ case 1:
+ return 0.65;
+ case 2:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/screens/onboarding/widget/onboarding_tile.dart b/lib/screens/onboarding/widget/onboarding_tile.dart
new file mode 100644
index 0000000..9beac1a
--- /dev/null
+++ b/lib/screens/onboarding/widget/onboarding_tile.dart
@@ -0,0 +1,46 @@
+import 'package:flutter/material.dart';
+
+class OnboardingTile extends StatelessWidget {
+ final title, imagePath, mainText;
+
+ OnboardingTile({this.imagePath, this.mainText, this.title});
+
+ @override
+ Widget build(BuildContext context) {
+ final screenWidth = MediaQuery.of(context).size.width;
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 24),
+ child: Column(
+ children: [
+ const SizedBox(height: 34),
+ Expanded(
+ child: Image.asset(
+ imagePath,
+ ),
+ ),
+ const SizedBox(height: 65),
+ Text(
+ title,
+ style: TextStyle(
+ fontWeight: FontWeight.w700,
+ fontSize: 24.0,
+ ),
+ ),
+ const SizedBox(height: 15),
+ Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: screenWidth / 100,
+ ),
+ child: Text(
+ mainText,
+ style: TextStyle(
+ fontSize: 16.0,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
index df52a27..6333c38 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -36,6 +36,8 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
+ dots_indicator: ^4.0.1
+ percent_indicator: ^4.2.5
dev_dependencies:
flutter_test:
@@ -53,12 +55,7 @@ dev_dependencies:
# The following section is specific to Flutter packages.
flutter:
- fonts:
- - family: NotoSansKR
- fonts:
- - asset: assets/fonts/NotoSansKR/NotoSansKR-Regular.ttf
- - asset: assets/fonts/NotoSansKR/NotoSansKR-Bold.ttf
- weight: 700
+
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
@@ -66,6 +63,21 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
+ - assets/images/onboarding/
+ - assets/images/auth/
+ - assets/images/home/
+ - assets/images/exercises/
+ - assets/icons/home/
+ - assets/icons/workouts/
+ - assets/icons/social_networks/
+ - assets/videos/workouts/
+
+ fonts:
+ - family: NotoSansKR
+ fonts:
+ - asset: assets/fonts/NotoSansKR/NotoSansKR-Regular.ttf
+ - asset: assets/fonts/NotoSansKR/NotoSansKR-Bold.ttf
+ weight: 700
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
diff --git a/test/widget_test.dart b/test/widget_test.dart
index e0a41ae..748f4cb 100644
--- a/test/widget_test.dart
+++ b/test/widget_test.dart
@@ -13,7 +13,7 @@ import 'package:tutorialtest/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
- await tester.pumpWidget(const MyApp());
+ await tester.pumpWidget(MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);