diff --git a/example/lib/sample2.dart b/example/lib/sample2.dart index ed99c14..3acbd27 100644 --- a/example/lib/sample2.dart +++ b/example/lib/sample2.dart @@ -1,4 +1,5 @@ import 'package:cube_transition/cube_transition.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'data.dart'; @@ -14,14 +15,25 @@ class Sample2 extends StatelessWidget { child: SizedBox( height: height, child: CubePageView( + transformStyle: CubeTransformStyle.inside, + startPage: 1, + scrollDirection: Axis.vertical, children: places .map( (item) => Stack( children: [ - Image.network( - item.url, - height: height, - fit: BoxFit.cover, + GestureDetector( + onLongPress: ()=>print('longtap'), + onTap: ()=>print('longtap'), + child: Container( + height: MediaQuery.of(context).size.height, + color: Colors.red, + child: Image.network( + item.url, + height: height, + fit: BoxFit.cover, + ), + ), ), Positioned( left: 0, diff --git a/example/pubspec.lock b/example/pubspec.lock index 67304a9..9fd4e8e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,69 +1,62 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.2" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.6.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" - charcode: + version: "2.1.0" + characters: dependency: transitive description: - name: charcode + name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" - collection: + version: "1.1.0" + charcode: dependency: transitive description: - name: collection + name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" - convert: + version: "1.2.0" + clock: dependency: transitive description: - name: convert + name: clock url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - crypto: + version: "1.1.0" + collection: dependency: transitive description: - name: crypto + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "1.15.0" cube_transition: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.0.2" + version: "1.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -74,55 +67,27 @@ packages: description: flutter source: sdk version: "0.0.0" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -134,62 +99,55 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.3.0" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.5.0" + version: "2.1.0" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/lib/src/cube_page_view.dart b/lib/src/cube_page_view.dart index fa31ecc..ced66dd 100644 --- a/lib/src/cube_page_view.dart +++ b/lib/src/cube_page_view.dart @@ -1,6 +1,9 @@ import 'dart:math'; import 'dart:ui'; + +import 'package:cube_transition/cube_transition.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; /// Signature for a function that creates a widget for a given index in a [CubePageView] /// @@ -14,6 +17,8 @@ typedef CubeWidgetBuilder = CubeWidget Function( /// 1 - Using the default constructor [CubePageView] passing the items in `children` property. /// 2 - Using the factory constructor [CubePageView.builder] passing a `itemBuilder` and `itemCount` properties. +enum CubeTransformStyle { inside, outside} + class CubePageView extends StatefulWidget { /// Called whenever the page in the center of the viewport changes. final ValueChanged onPageChanged; @@ -25,22 +30,35 @@ class CubePageView extends StatefulWidget { /// Builder to customize your items final CubeWidgetBuilder itemBuilder; + + /// Starting page + final int startPage; + /// The number of items you have, this is only required if you use [CubePageView.builder] final int itemCount; /// Widgets you want to use inside the [CubePageView], this is only required if you use [CubePageView] constructor final List children; + + /// Direction + final Axis scrollDirection; + + /// inside or outside + final CubeTransformStyle transformStyle; /// Creates a scrollable list that works page by page from an explicit [List] /// of widgets. - const CubePageView({ - Key key, - this.onPageChanged, - this.controller, - @required this.children, - }) : itemBuilder = null, + const CubePageView( + {Key key, + this.onPageChanged, + this.controller, + @required this.children, + this.scrollDirection = Axis.horizontal, + this.startPage = 0, this.transformStyle=CubeTransformStyle.outside}) + : itemBuilder = null, itemCount = null, assert(children != null), + assert(children.length>startPage), super(key: key); /// Creates a scrollable list that works page by page using widgets that are @@ -54,14 +72,18 @@ class CubePageView extends StatefulWidget { /// [itemBuilder] will be called only with indices greater than or equal to /// zero and less than [itemCount]. - CubePageView.builder({ - Key key, - @required this.itemCount, - @required this.itemBuilder, - this.onPageChanged, - this.controller, - }) : this.children = null, + CubePageView.builder( + {Key key, + @required this.itemCount, + @required this.itemBuilder, + this.onPageChanged, + this.controller, + this.scrollDirection = Axis.horizontal, + this.transformStyle=CubeTransformStyle.outside, + this.startPage=0}) + : this.children = null, assert(itemCount != null), + assert(itemCount>startPage), assert(itemBuilder != null), super(key: key); @@ -79,11 +101,13 @@ class _CubePageViewState extends State { @override void initState() { + super.initState(); _pageController = widget.controller ?? PageController(); WidgetsBinding.instance.addPostFrameCallback((_) { _pageController.addListener(_listener); + _pageController.jumpToPage(widget.startPage); + }); - super.initState(); } @override @@ -97,11 +121,11 @@ class _CubePageViewState extends State { @override Widget build(BuildContext context) { return Material( - color: Colors.transparent, child: Center( child: ValueListenableBuilder( valueListenable: _pageNotifier, builder: (_, value, child) => PageView.builder( + scrollDirection: widget.scrollDirection, controller: _pageController, onPageChanged: widget.onPageChanged, physics: const ClampingScrollPhysics(), @@ -109,10 +133,13 @@ class _CubePageViewState extends State { itemBuilder: (_, index) { if (widget.itemBuilder != null) return widget.itemBuilder(context, index, value); + return CubeWidget( child: widget.children[index], index: index, pageNotifier: value, + rotationDirection: widget.scrollDirection, + transformStyle: widget.transformStyle, ); }, ), @@ -132,31 +159,58 @@ class CubeWidget extends StatelessWidget { /// Page Notifier value, it comes from the [CubeWidgetBuilder] final double pageNotifier; + /// Rotation direction + final Axis rotationDirection; + + /// sides are center-aligned, it looks not like a cube, but nice + final bool centerAligned; + /// Child you want to use inside the Cube final Widget child; - - const CubeWidget({ - Key key, - @required this.index, - @required this.pageNotifier, - @required this.child, - }) : super(key: key); + + /// + final CubeTransformStyle transformStyle; + @override Widget build(BuildContext context) { final isLeaving = (index - pageNotifier) <= 0; final t = (index - pageNotifier); - final rotationY = lerpDouble(0, 90, t); + final rotation = lerpDouble(0, 90, t); final opacity = lerpDouble(0, 1, t.abs()).clamp(0.0, 1.0); final transform = Matrix4.identity(); - transform.setEntry(3, 2, 0.003); - transform.rotateY(-degToRad(rotationY)); + + rotationDirection == Axis.horizontal + ? transform.setEntry(3, 2, 0.003) : + transform.setEntry(3, 2, 0.001); + + + if (transformStyle==CubeTransformStyle.outside) + rotationDirection == Axis.horizontal + ? transform.rotateY(-degToRad(rotation)) + : transform.rotateX(degToRad(rotation)); + else + rotationDirection == Axis.horizontal + ? transform.rotateY(degToRad(rotation)) + : transform.rotateX(-degToRad(rotation)); + + + var alignment; + if (rotationDirection==Axis.horizontal) { + alignment = isLeaving ? Alignment.centerRight : Alignment.centerLeft; + } else + { + alignment = !isLeaving ? Alignment.topCenter : Alignment.bottomCenter; + } + + + + return Transform( - alignment: isLeaving ? Alignment.centerRight : Alignment.centerLeft, + alignment: alignment, transform: transform, child: Stack( children: [ - child, Positioned.fill( child: Opacity( opacity: opacity, @@ -167,11 +221,24 @@ class CubeWidget extends StatelessWidget { ), ), ), + child, ], ), ); } + + const CubeWidget({ + Key key, + this.rotationDirection = Axis.horizontal, + + @required this.index, + @required this.pageNotifier, + @required this.child, + this.centerAligned=false, this.transformStyle=CubeTransformStyle.outside, + + }) : super(key: key); } num degToRad(num deg) => deg * (pi / 180.0); + num radToDeg(num rad) => rad * (180.0 / pi); diff --git a/pubspec.lock b/pubspec.lock index f85e4f2..5e5273e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,13 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.15.0" flutter: dependency: "direct main" description: flutter @@ -19,7 +26,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0" sky_engine: dependency: transitive description: flutter @@ -31,13 +38,13 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0" sdks: - dart: ">=2.3.0 <3.0.0" + dart: ">=2.12.0-0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index a74616a..7e7745d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: cube_transition description: A nice 3D Cube effect for your PageView and PageRoute transitions. -version: 1.0.2 +version: 1.0.5 homepage: https://aeyrium.com/products/mxtracker/ repository: https://github.com/aeyrium/cube_transition