diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 0000000..1b7af81 --- /dev/null +++ b/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\softwares\Flutter\flutter_windows_v1.5.4-hotfix.2-stable\flutter" +export "FLUTTER_APPLICATION_PATH=D:\projects\traintracker" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build\ios" +export "FLUTTER_FRAMEWORK_DIR=D:\softwares\Flutter\flutter_windows_v1.5.4-hotfix.2-stable\flutter\bin\cache\artifacts\engine\ios" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" diff --git a/lib/content_screen/contribution_screen.dart b/lib/content_screen/contribution_screen.dart new file mode 100644 index 0000000..3525ad4 --- /dev/null +++ b/lib/content_screen/contribution_screen.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:trainfinder/widgets/text_form_field.dart'; + +class Contribution extends StatefulWidget { + @override + _ContributionState createState() => _ContributionState(); +} + +class _ContributionState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Contribution(), + floatingActionButton: FloatingActionButton.extended( + icon: Icon(FontAwesomeIcons.ad), + onPressed: () {}, + label: Text("Add"), + ), + ); + } + + Widget Contribution() { + return Container( + child: Column( + children: [ + SizedBox( + height: 40, + ), + Center( + child: Text( + "Contribute", + style: TextStyle( + fontSize: 40, + color: Colors.teal, + fontWeight: FontWeight.bold), + ), + ), + SizedBox( + height: 20, + ), + LabelTextField( + hintText: "Train name", + labelText: "Train name", + ), + SizedBox( + height: 10, + ), + LabelTextField( + hintText: "Train time", + labelText: "Train time", + ) + ], + ), + ); + } +} diff --git a/lib/content_screen/notices_screen.dart b/lib/content_screen/notices_screen.dart new file mode 100644 index 0000000..c051f7f --- /dev/null +++ b/lib/content_screen/notices_screen.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:trainfinder/widgets/text_form_field.dart'; + +class NoticesScreen extends StatefulWidget { + @override + _NoticesScreenState createState() => _NoticesScreenState(); +} + +class _NoticesScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Notices(), + floatingActionButton: FloatingActionButton.extended( + icon: Icon(FontAwesomeIcons.ad), + onPressed: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) => ComposeNotice())); + }, + label: Text("Compose notice"), + ), + ); + } + + Widget Notices() { + return Container( + child: Column( + children: [ + SizedBox( + height: 60, + ), + Row( + children: [ + Text( + "Ruhunu kumari", + style: TextStyle( + fontSize: 20, + color: Colors.teal, + fontWeight: FontWeight.bold), + ) + ], + ), + Card( + child: ListTile( + leading: Icon(FontAwesomeIcons.fileImport), + title: Text("Ruhunu kumari will be delayed 10 minutes today"), + ), + ), + ], + ), + ); + } +} + +class ComposeNotice extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: _composeNotice(), + ); + } + + Widget _composeNotice() { + return Container( + child: Column( + children: [ + SizedBox( + height: 40, + ), + LabelTextField( + hintText: "Train name", + labelText: "Train name", + ), + SizedBox( + height: 20, + ), + LabelTextField( + hintText: "Notice massage", + labelText: "Notice massage", + ), + SizedBox( + height: 20, + ), + LabelTextField( + hintText: "Current Station", + labelText: "Current Station", + ), + SizedBox( + height: 20, + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 100), + ), + ButtonTheme( + minWidth: 200, + child: RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10) + ), + color: Colors.teal, + onPressed: () {}, + child: Text("Submit notice"), + ), + ), + ], + ) + ], + ), + ); + } +} diff --git a/lib/content_screen/search_screen.dart b/lib/content_screen/search_screen.dart new file mode 100644 index 0000000..45d1487 --- /dev/null +++ b/lib/content_screen/search_screen.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:scaffold_tab_bar/scaffold_tab_bar.dart'; +import 'package:trainfinder/widgets/text_form_field.dart'; + +class SearchScreen extends StatefulWidget { + @override + _SearchScreenState createState() => _SearchScreenState(); +} + +class _SearchScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ScaffoldTabBar( + children: [ + ScreenTab( + screen: _search(), + tab: BottomNavigationBarItem( + icon: Icon(FontAwesomeIcons.times), + title: Text('Time table'), + ), + ), + ScreenTab( + screen: _timeTable(), + tab: BottomNavigationBarItem( + icon: Icon(FontAwesomeIcons.search), + title: Text('Search'), + ), + ), + ], + )); + } + + Widget _timeTable() { + return Container( + child: Column( + children: [ + SizedBox( + height: 60, + ), + Center( + child: Text( + "Find Train Schedule", + style: TextStyle( + fontSize: 40, + color: Colors.teal, + fontWeight: FontWeight.bold), + ), + ), + SizedBox( + height: 50, + ), + LabelTextField( + labelText: "From where", + hintText: "From where", + ), + SizedBox( + height: 20, + ), + LabelTextField( + labelText: "To where", + hintText: "To where", + ), + Row( + children: [ + Align( + alignment: Alignment.centerLeft, + child: IconButton( + onPressed: () {}, + icon: Icon( + Icons.swap_vert, + color: Colors.teal, + ), + ), + ), + Text("swap"), + Padding( + padding: EdgeInsets.only(left: 220), + ), + Align( + alignment: Alignment.bottomRight, + child: IconButton( + icon: Icon(FontAwesomeIcons.dropbox), + onPressed: () {}, + ), + ), + Text("more") + ], + ), + SizedBox( + height: 20, + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 40), + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width * 0.8, + child: RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + onPressed: () {}, + child: Text("Submit"), + color: Colors.teal, + ), + ), + ], + ) + ], + ), + ); + } + + Widget _search() { + return Container( + child: Column( + children: [ + SizedBox( + height: 60, + ), + Center( + child: Text( + "Station Time Table", + style: TextStyle( + fontSize: 40, + color: Colors.teal, + fontWeight: FontWeight.bold), + ), + ), + SizedBox( + height: 50, + ), + LabelTextField( + hintText: "Station Name", + labelText: "Station Name", + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 300), + ), + Align( + alignment: Alignment.centerRight, + child: IconButton( + icon: Icon(Icons.more), + onPressed: () {}, + ), + ), + Text("more"), + SizedBox( + height: 10, + ), + ], + ), + ButtonTheme( + minWidth: 300, + child: RaisedButton( + child: Text("Search"), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10) + ), + color: Colors.teal, + onPressed: (){}, + ), + ), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index f4ebf1d..514f2ed 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,111 +1,4 @@ import 'package:flutter/material.dart'; +import 'package:trainfinder/myapp.dart'; void main() => runApp(MyApp()); - -class MyApp extends StatelessWidget { - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); - } -} - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Invoke "debug painting" (press "p" in the console, choose the - // "Toggle Debug Paint" action from the Flutter Inspector in Android - // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) - // to see the wireframe for each widget. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.display1, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -} diff --git a/lib/myapp.dart b/lib/myapp.dart new file mode 100644 index 0000000..3635ab5 --- /dev/null +++ b/lib/myapp.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:trainfinder/screens/home_screen.dart'; + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: "Train tracker", + darkTheme: ThemeData.dark(), + home: Homepage(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart new file mode 100644 index 0000000..2c1ef4f --- /dev/null +++ b/lib/screens/home_screen.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:trainfinder/screens/main_screen.dart'; +import 'package:trainfinder/widgets/common/appbar.dart'; + +class Homepage extends StatefulWidget { + @override + _HomepageState createState() => _HomepageState(); +} + +class _HomepageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: false, + body: NestedScrollView( + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + Header("Train Tracker"), + ]; + }, + body: Container( + child: Center( + child: FlatButton( + color: Colors.amber, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20) + ), + child: Text("Start"), + onPressed: ()=>Navigator.push(context, MaterialPageRoute( + builder: (context)=>Mainscreen() + )) + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart new file mode 100644 index 0000000..253e95d --- /dev/null +++ b/lib/screens/main_screen.dart @@ -0,0 +1,53 @@ +import 'package:circular_bottom_navigation/circular_bottom_navigation.dart'; +import 'package:circular_bottom_navigation/tab_item.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:trainfinder/content_screen/contribution_screen.dart'; +import 'package:trainfinder/content_screen/notices_screen.dart'; +import 'package:trainfinder/content_screen/notification_screen.dart'; +import 'package:trainfinder/content_screen/search_screen.dart'; + +class Mainscreen extends StatefulWidget { + @override + _MainscreenState createState() => _MainscreenState(); +} + +class _MainscreenState extends State { + List tabItems = List.of([ + new TabItem(FontAwesomeIcons.accessibleIcon, "Contribute", Colors.blue, + labelStyle: TextStyle(fontWeight: FontWeight.bold)), + new TabItem(Icons.search, "Search", Colors.orange, + labelStyle: TextStyle(color: Colors.red, fontWeight: FontWeight.bold)), + new TabItem(Icons.layers, "Notices", Colors.red), + new TabItem(Icons.notifications, "Notifications", Colors.cyan), + ]); + + int _selectedIndex = 0; + static const TextStyle optionStyle = + TextStyle(fontSize: 30, fontWeight: FontWeight.bold); + static List _widgetOptions = [ + Contribution(), + SearchScreen(), + NoticesScreen(), + NotificationScreen(), + ]; + + static int selectedPos = 0; + CircularBottomNavigationController _navigationController = + new CircularBottomNavigationController(selectedPos); + @override + Widget build(BuildContext context) { + return Scaffold( + bottomNavigationBar: CircularBottomNavigation( + tabItems, + controller: _navigationController, + selectedCallback: (int selectedPos) { + setState(() { + _selectedIndex = selectedPos; + }); + }, + ), + body: _widgetOptions.elementAt(_selectedIndex), + ); + } +} diff --git a/lib/widgets/common/appbar.dart b/lib/widgets/common/appbar.dart new file mode 100644 index 0000000..9d173e2 --- /dev/null +++ b/lib/widgets/common/appbar.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class Header extends StatelessWidget { + final String title; + + Header(this.title); + + @override + Widget build(BuildContext context) { + return SliverAppBar( + expandedHeight: 240.0, + floating: false, + pinned: false, + flexibleSpace: FlexibleSpaceBar( + title: Padding( + padding: const EdgeInsets.only(bottom: 24.0), + child: Text(title, + style: TextStyle( + color: Colors.white, + fontSize: 36.0, + )), + ), + background: Container( + color: Colors.blue, + )), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/text_form_field.dart b/lib/widgets/text_form_field.dart new file mode 100644 index 0000000..9faa636 --- /dev/null +++ b/lib/widgets/text_form_field.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class LabelTextField extends StatelessWidget { + final String hintText; + final String labelText; + final bool isObscure; + final String controller; + final TextCapitalization textCapitalization; + final TextInputType keyboardType; + final validator; + final onSaved; + final textEditingController; + final Function onTap; + final IconButton iconButton; + final Icon icon; + LabelTextField({ + this.hintText, + this.isObscure = false, + this.textCapitalization = TextCapitalization.none, + this.keyboardType = TextInputType.text, + this.labelText, + this.validator, + this.onSaved, + this.controller, + this.textEditingController, + this.icon, + this.onTap, + this.iconButton, + }); + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(8), + child: TextFormField( + decoration: new InputDecoration( + hintText: hintText, + labelText: labelText, + filled: true, + fillColor: Colors.black12, + border: InputBorder.none, + icon: icon, + + ), + controller: textEditingController, + textCapitalization: textCapitalization, + keyboardType: keyboardType, + obscureText: isObscure, + validator: validator, + onSaved: onSaved, + onTap: onTap, + ), + ); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index f6b0bbd..78fe4bd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,5 +1,5 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: async: dependency: transitive @@ -7,14 +7,21 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.3.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" + bubble_bottom_bar: + dependency: "direct main" + description: + name: bubble_bottom_bar + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" charcode: dependency: transitive description: @@ -22,6 +29,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.2" + circular_bottom_navigation: + dependency: "direct main" + description: + name: circular_bottom_navigation + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" collection: dependency: transitive description: @@ -46,6 +60,13 @@ packages: description: flutter source: sdk version: "0.0.0" + font_awesome_flutter: + dependency: "direct main" + description: + name: font_awesome_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "8.5.0" matcher: dependency: transitive description: @@ -59,33 +80,47 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.1.7" + mobx: + dependency: transitive + description: + name: mobx + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.37" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" + version: "1.6.4" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.5.0" + version: "1.8.0+1" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.5" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + sliver_glue: + dependency: "direct main" + description: + name: sliver_glue + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" source_span: dependency: transitive description: @@ -113,7 +148,7 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" term_glyph: dependency: transitive description: @@ -127,7 +162,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.4" + version: "0.2.5" typed_data: dependency: transitive description: @@ -143,4 +178,4 @@ packages: source: hosted version: "2.0.8" sdks: - dart: ">=2.2.0 <3.0.0" + dart: ">=2.2.2 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 212657e..f27f11a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,11 +19,15 @@ environment: dependencies: flutter: sdk: flutter + sliver_glue: ^1.2.0 + font_awesome_flutter: ^8.5.0 + bubble_bottom_bar: ^1.2.0 + circular_bottom_navigation: ^1.0.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 - + dev_dependencies: flutter_test: sdk: flutter diff --git a/test/widget_test.dart b/test/widget_test.dart index e62c675..d2bc196 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,8 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - -import 'package:trainfinder/main.dart'; +import 'package:trainfinder/myapp.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async {