diff --git a/lib/Components/custom_clipper.dart b/lib/Components/custom_clipper.dart new file mode 100644 index 0000000..07dac72 --- /dev/null +++ b/lib/Components/custom_clipper.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; + +class WaveClipper extends CustomClipper { + bool minimized; + double height; + double width; + double move = 0; + + WaveClipper({ + this.move, + this.minimized, + this.height, + this.width, + }) : super(); + + @override + Path getClip(Size size) { + + /*print('height from parent = ' + this.height.toString()); + print('width from parent = ' + this.width.toString()); + print('bool from parent = ' + this.minimized.toString());*/ + + var controlPoint1 = Offset(size.width *0.2, size.height*0.75); + var controlPoint2 = Offset(size.width *0.55, size.height*0.76); + var endPoint = Offset(size.width *0.62, size.height*0.79); + + var controlPoint12 = Offset(size.width *0.82, size.height*0.85); + var controlPoint21 = Offset(size.width *0.93, size.height*1.09); + var endPoint1 = Offset(size.width, size.height*0.78); + + /*Path path = Path() + ..lineTo(0, size.width) + ..lineTo(size.width, size.height) + ..lineTo(size.width, 0) + ..close();*/ + Path path = Path() + ..lineTo(0, size.width) + ..lineTo(size.width, size.height) + ..lineTo(size.width*move, 0) + ..close(); + + //print("move is = " + move.toString()); + + /*Path path = Path() + ..moveTo(0, size.height*0.3 *move) + ..cubicTo(0, size.height*0.3, 0, 0, size.width*0.4, 0) + ..lineTo(size.width*0.4, 0) + ..lineTo(size.height, size.width) + /*..cubicTo(controlPoint1.dx, controlPoint1.dy, controlPoint2.dx * move, + controlPoint2.dy, endPoint.dx, endPoint.dy) + ..cubicTo(controlPoint12.dx* move, controlPoint12.dy, controlPoint21.dx, + controlPoint21.dy, endPoint1.dx, endPoint1.dy * move)*/ + //..lineTo(size.width, size.height) + + ..close();*/ + + return path; + + } + + @override + bool shouldReclip(CustomClipper oldClipper) => true; +} \ No newline at end of file diff --git a/lib/constants.dart b/lib/constants.dart index ff0b8e4..8535612 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -2,9 +2,15 @@ import 'package:flutter/material.dart'; // Colors - TO FILL WIT CORRECT COLOR const kBackgroundColor = Color(0xFFFFFFFF); -const kTitleTextColor = Color(0xFF303030); -const kBodyTextColor = Color(0xFF4B4B4B); // TODO -const kTextLightColor = Color(0xFFCED5DF); // #ced5df + +const kMainGrey = Color(0xFF424242); +const kSecondGrey = Color(0xFF555457); +const kTestSecondColor = Color(0xFF2F4858); +const kMainRed = Color(0xFF8b0000); +const kSecondRed = Color(0xFF622727); +const kTextRed = Color(0xFFba0505); +const kBackgroundGrey = Color(0xFFb5b7b9); +const kBackgroundSecondGrey = Color(0xFF5b5b63); /* const kTextStyle = TextStyle( diff --git a/lib/main.dart b/lib/main.dart index 7160f22..286dd8c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,10 @@ -import 'package:flutter/material.dart'; +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +import 'Components/custom_clipper.dart'; import 'constants.dart'; void main() { @@ -17,6 +22,7 @@ void main() { class MyApp extends StatefulWidget { final String initialRoute; + //final Context context; MyApp({this.initialRoute}); @@ -26,21 +32,22 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { + @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Tablet App Demo', initialRoute: widget.initialRoute, - supportedLocales: [ + /*supportedLocales: [ const Locale('en', 'US'), const Locale('fr', 'FR'), - ], + ],*/ theme: ThemeData( primarySwatch: Colors.grey, - scaffoldBackgroundColor: kBackgroundColor, + scaffoldBackgroundColor: kBackgroundGrey, //fontFamily: "Vollkorn", - textTheme: TextTheme(bodyText1: TextStyle(color: kBodyTextColor)), + textTheme: TextTheme(bodyText1: TextStyle(color: kMainRed)), visualDensity: VisualDensity.adaptivePlatformDensity, ), routes: { @@ -59,39 +66,290 @@ class MyHomePage extends StatefulWidget { _MyHomePageState createState() => _MyHomePageState(); } -class _MyHomePageState extends State { +class _MyHomePageState extends State with TickerProviderStateMixin { int _counter = 0; + Size sizeScreen = new Size(1080.0, 1920.0); // Tablet resolution + double elementMinimizedSize = 200.0; + double elementMaximizedSize = 400.0; + bool minimized = false; + + double _leftMain; + double _topMain; + double _rightMain; + double _bottomMain; + + double _leftTitle; + double _topTitle; + double _rightTitle; + double _bottomTitle; + + double _leftElement; + double _topElement; + double _rightElement; + double _bottomElement; + + double _leftMenu; + double _topMenu; + double _rightMenu; + double _bottomMenu; + + AnimationController _controller; + Completer _webViewController = Completer(); + + @override + void initState() { + setState(() { + _leftMain = (sizeScreen.height / 2) - elementMaximizedSize; + _topMain = (sizeScreen.width / 2) - elementMaximizedSize; + _rightMain = (sizeScreen.height / 2) - elementMaximizedSize; + _bottomMain = (sizeScreen.width / 2) - elementMaximizedSize; + + _leftElement = (sizeScreen.height/2)-elementMaximizedSize; + _topElement = (sizeScreen.width/2)-elementMaximizedSize; + _rightElement = (sizeScreen.height/2); + _bottomElement = (sizeScreen.width/2); + + _leftMenu = 0; + _topMenu = sizeScreen.width * 0.15; + _rightMenu = sizeScreen.height; + _bottomMenu = sizeScreen.width * 0.2; + + _leftTitle = 0; + _topTitle = 0; + _rightTitle = sizeScreen.height; + _bottomTitle = sizeScreen.width; + }); + + _controller = AnimationController(value: 12, vsync: this, duration: Duration(seconds: 1)); + _controller.animateBack(0); + + super.initState(); + } void _incrementCounter() { setState(() { _counter++; + + minimized = !minimized; + + if (minimized) { + _controller.animateBack(5.0); + } else { + _controller.animateBack(0.0); + } + + _leftMenu = 0; + _topMenu = sizeScreen.width * 0.18; + _rightMenu = minimized ? sizeScreen.height - elementMinimizedSize : sizeScreen.height; + _bottomMenu = minimized ? sizeScreen.width * 0.2 : sizeScreen.width * 0.2; + + _leftMain = minimized ? 0 : (sizeScreen.height/2)-elementMaximizedSize; + _topMain = minimized ? sizeScreen.width-elementMinimizedSize : (sizeScreen.width/2)-elementMaximizedSize; + _rightMain = minimized ? sizeScreen.height-elementMinimizedSize : (sizeScreen.height/2)-elementMaximizedSize; + _bottomMain = minimized ? 0 : (sizeScreen.width/2)-elementMaximizedSize; + + _leftElement = minimized ? sizeScreen.height * 0.11 : (sizeScreen.height/2)-elementMaximizedSize; + _topElement = minimized ? 0 : (sizeScreen.width/2)-elementMaximizedSize; + _rightElement = minimized ? 0 : (sizeScreen.height/2); + _bottomElement = minimized ? 0 : (sizeScreen.width/2); + + _leftTitle = 0; + _topTitle = 0; + _rightTitle = minimized ? sizeScreen.height - elementMinimizedSize : sizeScreen.height; + _bottomTitle = minimized ? sizeScreen.width * 0.83 : sizeScreen.width; }); } + Future _onWillPop() async { + return false; + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], + SystemChrome.setEnabledSystemUIOverlays([]); + Size size = MediaQuery.of(context).size; + return new WillPopScope( + onWillPop: _onWillPop, + child: Scaffold( + // Tablet size + body: Container( + height: size.height, + width: size.width, + child: Stack( + children: [ + // Main + AnimatedPositioned( + duration: const Duration(milliseconds: 1500), + curve: Curves.easeInOutSine, + left: _leftMain, + top: _topMain, + right: _rightMain, + bottom: _bottomMain, + child: InkWell( + onTap: () { if (minimized) _incrementCounter(); }, + child: Container( + decoration: BoxDecoration( + borderRadius: new BorderRadius.only( + topRight: const Radius.circular(20.0), + ), + color: kSecondRed + ), + child: Center( + child: Text( + 'MAIN MENU', + style: TextStyle(color: kTextRed, fontSize: 25), + ), + ), + ), + ), + ), + // Title opened + AnimatedPositioned( + duration: const Duration(milliseconds: 1500), + curve: Curves.easeInOutSine, + left: _leftTitle, + top: _topTitle, + right: _rightTitle, + bottom: _bottomTitle, + child: InkWell( + onTap: () { if (minimized) _incrementCounter(); }, + child: Container( + decoration: BoxDecoration( + borderRadius: new BorderRadius.only( + bottomRight: const Radius.circular(20.0), + ), + color: kSecondRed + ), + child: Center( + child: Text( + 'Title opened element', + style: TextStyle(color: kTextRed, fontSize: 25), + ), + ), + ), + ), + ), + // Element + AnimatedPositioned( + duration: const Duration(milliseconds: 1000), + curve: Curves.easeInOutSine, + top: _topElement, + left: _leftElement, + right: _rightElement, + bottom: _bottomElement, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, Widget child) { + return ClipPath( + clipper: WaveClipper(move: _controller.value, minimized: minimized, height: _leftMain, width: _topMain), + clipBehavior: Clip.hardEdge, + child: InkWell( + onTap: () => { + if (!minimized) _incrementCounter() + }, + child: AnimatedContainer( + // Define how long the animation should take. + duration: Duration(seconds: 2), + // Provide an optional curve to make the animation feel smoother. + curve: Curves.easeInOutCubic, + height: elementMaximizedSize, + width: elementMaximizedSize, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20.0), + gradient: LinearGradient( + begin: Alignment.centerRight, + end: Alignment.centerLeft, + colors: [ + minimized ? kBackgroundSecondGrey : kSecondGrey, + minimized ? kBackgroundSecondGrey : Colors.transparent + ], + ), + ), + child: Center( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Container( + width: size.width, + height: size.height, + child: WebView( + initialUrl: "https://my.matterport.com/show/?m=k8bvdezfHbT", + javascriptMode: JavascriptMode.unrestricted, + onWebViewCreated: (WebViewController webViewController) { + _webViewController.complete(webViewController); + }, + navigationDelegate: (NavigationRequest request) { + if (request.url != "https://my.matterport.com/show/?m=k8bvdezfHbT") { + print('blocking navigation to $request}'); + return NavigationDecision.prevent; + } + print('allowing navigation to $request'); + return NavigationDecision.navigate; + }, + )), + ), + ), + ), + ), + ); + }, + ), + ), + ), + // MENU + AnimatedPositioned( + duration: const Duration(milliseconds: 2000), + curve: Curves.easeInOutSine, + top: _topMenu, + left: _leftMenu, + right: _rightMenu, + bottom: _bottomMenu, + child: Container( + decoration: BoxDecoration( + borderRadius: new BorderRadius.only( + topRight: const Radius.circular(20.0), + bottomRight: const Radius.circular(20.0), + ), + color: Colors.lightBlue + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text('MENU'), + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text('Sub menu 1'), + Text('Sub menu 2'), + ] + ) + ] + ), + /*Icon( + Icons.autorenew, + color: Colors.pink, + size: 24.0, + semanticLabel: 'Text to announce in accessibility modes', + ),*/ + ), + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: Icon(Icons.add), ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), ), ); } diff --git a/pubspec.lock b/pubspec.lock index 2a705a1..37a4f1d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -149,5 +149,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.4" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.7" sdks: dart: ">=2.11.0-0.0 <2.12.0" + flutter: ">=1.22.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6cbbcf8..c8087f3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,7 +23,7 @@ environment: dependencies: flutter: sdk: flutter - + webview_flutter: ^1.0.7 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.