├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example ├── .gitignore ├── .metadata ├── README.md ├── lib │ └── main.dart ├── page_slider_demo.gif ├── pubspec.lock └── pubspec.yaml ├── lib └── page_slider.dart ├── pubspec.lock ├── pubspec.yaml └── test └── page_slider_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | android 2 | ios 3 | 4 | # Miscellaneous 5 | *.class 6 | *.log 7 | *.pyc 8 | *.swp 9 | .DS_Store 10 | .atom/ 11 | .buildlog/ 12 | .history 13 | .svn/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # Visual Studio Code related 22 | .vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Generated.xcconfig 62 | **/ios/Flutter/app.flx 63 | **/ios/Flutter/app.zip 64 | **/ios/Flutter/flutter_assets/ 65 | **/ios/ServiceDefinitions.json 66 | **/ios/Runner/GeneratedPluginRegistrant.* 67 | 68 | # Exceptions to above rules. 69 | !**/ios/**/default.mode1v3 70 | !**/ios/**/default.mode2v3 71 | !**/ios/**/default.pbxuser 72 | !**/ios/**/default.perspectivev3 73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 74 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.2] - 6/6/2019 2 | 3 | * Add example 4 | * Add `onFinished` callback 5 | 6 | ## [0.0.1] - 5/6/2019 7 | 8 | * Initial release 9 | 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 serenader 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_page_slider 2 | 3 | [![Pub](https://img.shields.io/pub/v/page_slider.svg)](https://pub.dev/packages/page_slider) 4 | 5 | A simple Flutter widget that slides through pages horizontally. Use-cases could be wizards or onboarding flows similar to the Material Stepper widget, but without a particular UI - any widget can be a page to slide through. 6 | 7 | Here's a demo of the example app: 8 | 9 | ![PageSlider demo app](https://github.com/julvo/flutter_page_slider/blob/master/example/page_slider_demo.gif) 10 | 11 | 12 | ## How to use 13 | 14 | First, create the `PageSlider` widget with a `GlobalKey` and the child widgets which you want to slide through. Then, control the active page using the global key to address the page slider state like so: 15 | 16 | ```dart 17 | class Demo extends StatefulWidget { 18 | Demo({Key key}) : super(key: key); 19 | _DemoState createState() => _DemoState(); 20 | } 21 | 22 | class _DemoState extends State { 23 | GlobalKey _sliderKey = GlobalKey(); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Column( 28 | children: [ 29 | PageSlider( 30 | key: _sliderKey, 31 | pages: [ 32 | Text('Page 0'), 33 | Text('Page 1'), 34 | Text('Page 2'), 35 | ] 36 | ), 37 | RaisedButton( 38 | onPressed: _sliderKey.currentState.next, 39 | child: Text('Next') 40 | ), 41 | RaisedButton( 42 | onPressed: _sliderKey.currentState.previous, 43 | child: Text('Previous') 44 | ), 45 | ] 46 | ); 47 | } 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | /build/ 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/captures/ 36 | **/android/gradlew 37 | **/android/gradlew.bat 38 | **/android/local.properties 39 | **/android/**/GeneratedPluginRegistrant.java 40 | 41 | # iOS/XCode related 42 | **/ios/**/*.mode1v3 43 | **/ios/**/*.mode2v3 44 | **/ios/**/*.moved-aside 45 | **/ios/**/*.pbxuser 46 | **/ios/**/*.perspectivev3 47 | **/ios/**/*sync/ 48 | **/ios/**/.sconsign.dblite 49 | **/ios/**/.tags* 50 | **/ios/**/.vagrant/ 51 | **/ios/**/DerivedData/ 52 | **/ios/**/Icon? 53 | **/ios/**/Pods/ 54 | **/ios/**/.symlinks/ 55 | **/ios/**/profile 56 | **/ios/**/xcuserdata 57 | **/ios/.generated/ 58 | **/ios/Flutter/App.framework 59 | **/ios/Flutter/Flutter.framework 60 | **/ios/Flutter/Generated.xcconfig 61 | **/ios/Flutter/app.flx 62 | **/ios/Flutter/app.zip 63 | **/ios/Flutter/flutter_assets/ 64 | **/ios/ServiceDefinitions.json 65 | **/ios/Runner/GeneratedPluginRegistrant.* 66 | 67 | # Exceptions to above rules. 68 | !**/ios/**/default.mode1v3 69 | !**/ios/**/default.mode2v3 70 | !**/ios/**/default.pbxuser 71 | !**/ios/**/default.perspectivev3 72 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 73 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: bc7bc940836f1f834699625426795fd6f07c18ec 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:page_slider/page_slider.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Flutter Demo', 11 | theme: ThemeData( 12 | primarySwatch: Colors.blue, 13 | ), 14 | home: MyHomePage(), 15 | ); 16 | } 17 | } 18 | 19 | class MyHomePage extends StatefulWidget { 20 | MyHomePage({Key key}) : super(key: key); 21 | 22 | @override 23 | _MyHomePageState createState() => _MyHomePageState(); 24 | } 25 | 26 | class _MyHomePageState extends State { 27 | GlobalKey _slider = GlobalKey(); 28 | 29 | Widget _card(String text) => 30 | Card( 31 | elevation: 10, 32 | child: Padding( 33 | padding: EdgeInsets.all(100), 34 | child: Text( 35 | text, 36 | style: TextStyle( 37 | fontWeight: FontWeight.bold, 38 | fontSize: 28, 39 | ) 40 | ), 41 | ), 42 | ); 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | return Scaffold( 47 | backgroundColor: Colors.grey.shade100, 48 | appBar: AppBar( 49 | title: Text('Page Slider Demo'), 50 | ), 51 | body: Center( 52 | child: Column( 53 | mainAxisSize: MainAxisSize.max, 54 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 55 | children: [ 56 | PageSlider( 57 | key: _slider, 58 | duration: Duration(milliseconds: 400), 59 | pages: [ 60 | _card('First Page'), 61 | _card('Second Page'), 62 | _card('Third Page'), 63 | _card('Fourth Page'), 64 | ], 65 | ), 66 | Row( 67 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 68 | children: [ 69 | FloatingActionButton( 70 | child: Icon(Icons.arrow_back_ios), 71 | onPressed: () => _slider.currentState.previous(), 72 | ), 73 | FloatingActionButton( 74 | child: Icon(Icons.arrow_forward_ios), 75 | onPressed: () => _slider.currentState.next(), 76 | ), 77 | ], 78 | ), 79 | MaterialButton( 80 | // jump to zero-indexed page number 81 | onPressed: () => _slider.currentState.setPage(3), 82 | child: Text('Go to last page'), 83 | ), 84 | ], 85 | ), 86 | ), 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /example/page_slider_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julvo/flutter_page_slider/fab223914793bd557313b8087b6ddb88bc5da6be/example/page_slider_demo.gif -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.2.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.0.4" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.2" 25 | collection: 26 | dependency: transitive 27 | description: 28 | name: collection 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.14.11" 32 | cupertino_icons: 33 | dependency: "direct main" 34 | description: 35 | name: cupertino_icons 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "0.1.2" 39 | flutter: 40 | dependency: "direct main" 41 | description: flutter 42 | source: sdk 43 | version: "0.0.0" 44 | flutter_test: 45 | dependency: "direct dev" 46 | description: flutter 47 | source: sdk 48 | version: "0.0.0" 49 | matcher: 50 | dependency: transitive 51 | description: 52 | name: matcher 53 | url: "https://pub.dartlang.org" 54 | source: hosted 55 | version: "0.12.5" 56 | meta: 57 | dependency: transitive 58 | description: 59 | name: meta 60 | url: "https://pub.dartlang.org" 61 | source: hosted 62 | version: "1.1.6" 63 | page_slider: 64 | dependency: "direct main" 65 | description: 66 | name: page_slider 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.0.1" 70 | path: 71 | dependency: transitive 72 | description: 73 | name: path 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "1.6.2" 77 | pedantic: 78 | dependency: transitive 79 | description: 80 | name: pedantic 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.5.0" 84 | quiver: 85 | dependency: transitive 86 | description: 87 | name: quiver 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "2.0.3" 91 | sky_engine: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.99" 96 | source_span: 97 | dependency: transitive 98 | description: 99 | name: source_span 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.5.5" 103 | stack_trace: 104 | dependency: transitive 105 | description: 106 | name: stack_trace 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.9.3" 110 | stream_channel: 111 | dependency: transitive 112 | description: 113 | name: stream_channel 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "2.0.0" 117 | string_scanner: 118 | dependency: transitive 119 | description: 120 | name: string_scanner 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.0.4" 124 | term_glyph: 125 | dependency: transitive 126 | description: 127 | name: term_glyph 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.1.0" 131 | test_api: 132 | dependency: transitive 133 | description: 134 | name: test_api 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.2.5" 138 | typed_data: 139 | dependency: transitive 140 | description: 141 | name: typed_data 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.1.6" 145 | vector_math: 146 | dependency: transitive 147 | description: 148 | name: vector_math 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.0.8" 152 | sdks: 153 | dart: ">=2.2.0 <3.0.0" 154 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | page_slider: 0.0.1 23 | 24 | # The following adds the Cupertino Icons font to your application. 25 | # Use with the CupertinoIcons class for iOS style icons. 26 | cupertino_icons: ^0.1.2 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | 32 | 33 | # For information on the generic Dart part of this file, see the 34 | # following page: https://dart.dev/tools/pub/pubspec 35 | 36 | # The following section is specific to Flutter. 37 | flutter: 38 | 39 | # The following line ensures that the Material Icons font is 40 | # included with your application, so that you can use the icons in 41 | # the material Icons class. 42 | uses-material-design: true 43 | 44 | # To add assets to your application, add an assets section, like this: 45 | # assets: 46 | # - images/a_dot_burr.jpeg 47 | # - images/a_dot_ham.jpeg 48 | 49 | # An image asset can refer to one or more resolution-specific "variants", see 50 | # https://flutter.dev/assets-and-images/#resolution-aware. 51 | 52 | # For details regarding adding assets from package dependencies, see 53 | # https://flutter.dev/assets-and-images/#from-packages 54 | 55 | # To add custom fonts to your application, add a fonts section here, 56 | # in this "flutter" section. Each entry in this list should have a 57 | # "family" key with the font family name, and a "fonts" key with a 58 | # list giving the asset and other descriptors for the font. For 59 | # example: 60 | # fonts: 61 | # - family: Schyler 62 | # fonts: 63 | # - asset: fonts/Schyler-Regular.ttf 64 | # - asset: fonts/Schyler-Italic.ttf 65 | # style: italic 66 | # - family: Trajan Pro 67 | # fonts: 68 | # - asset: fonts/TrajanPro.ttf 69 | # - asset: fonts/TrajanPro_Bold.ttf 70 | # weight: 700 71 | # 72 | # For details regarding fonts from package dependencies, 73 | # see https://flutter.dev/custom-fonts/#from-packages 74 | -------------------------------------------------------------------------------- /lib/page_slider.dart: -------------------------------------------------------------------------------- 1 | library page_slider; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class PageSlider extends StatefulWidget { 6 | PageSlider({ 7 | @required this.pages, 8 | this.duration, 9 | this.initialPage, 10 | this.onFinished, 11 | @required Key key 12 | }) : super(key: key); 13 | 14 | final List pages; 15 | final Duration duration; 16 | final int initialPage; 17 | final VoidCallback onFinished; 18 | 19 | PageSliderState createState() => PageSliderState(); 20 | } 21 | 22 | class PageSliderState extends State with TickerProviderStateMixin { 23 | int _currentPage = 0; 24 | int get currentPage => _currentPage; 25 | 26 | List> _positions; 27 | List _controllers; 28 | 29 | @override 30 | void initState() { 31 | super.initState(); 32 | _currentPage = widget.initialPage ?? 0; 33 | 34 | _controllers = List.generate( 35 | widget.pages.length, 36 | (i) => AnimationController( 37 | vsync: this, 38 | duration: widget.duration ?? Duration(milliseconds: 300), 39 | lowerBound: 0, 40 | upperBound: 1, 41 | value: i == _currentPage 42 | ? 0.5 43 | : (i > _currentPage ? 1 : 0), 44 | ) 45 | ); 46 | 47 | _positions = _controllers 48 | .map((controller) => 49 | Tween( 50 | begin: Offset(-1, 0), 51 | end: Offset(1, 0) 52 | ) 53 | //.chain(CurveTween(curve: Curves.easeInCubic)) 54 | .animate(controller) 55 | ).toList(); 56 | } 57 | 58 | bool get hasNext => (_currentPage < widget.pages.length - 1); 59 | bool get hasPrevious => (_currentPage > 0); 60 | 61 | 62 | void setPage(int page) { 63 | assert(page >= 0 || page < widget.pages.length); 64 | while (_currentPage < page) next(); 65 | while (_currentPage > page) previous(); 66 | } 67 | 68 | void next() { 69 | if (!hasNext) { 70 | widget.onFinished(); 71 | return; 72 | } 73 | 74 | _controllers[_currentPage].animateTo(0); 75 | _controllers[_currentPage + 1].animateTo(0.5); 76 | setState(() { 77 | _currentPage += 1; 78 | }); 79 | } 80 | 81 | void previous() { 82 | if (!hasPrevious) return; 83 | 84 | _controllers[_currentPage].animateTo(1); 85 | _controllers[_currentPage - 1].animateTo(0.5); 86 | setState(() { 87 | _currentPage -= 1; 88 | }); 89 | } 90 | 91 | @override 92 | void dispose() { 93 | _controllers.forEach((controller) => controller.dispose()); 94 | super.dispose(); 95 | } 96 | 97 | @override 98 | Widget build(BuildContext context) { 99 | return Stack( 100 | alignment: Alignment.center, 101 | children: widget.pages.asMap().map((i, page) => 102 | MapEntry( 103 | i, 104 | SlideTransition( 105 | position: _positions[i], 106 | child: Center(child: page), 107 | ) 108 | ) 109 | ).values.toList(), 110 | ); 111 | } 112 | } -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.2.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.0.4" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.2" 25 | collection: 26 | dependency: transitive 27 | description: 28 | name: collection 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.14.11" 32 | flutter: 33 | dependency: "direct main" 34 | description: flutter 35 | source: sdk 36 | version: "0.0.0" 37 | flutter_test: 38 | dependency: "direct dev" 39 | description: flutter 40 | source: sdk 41 | version: "0.0.0" 42 | matcher: 43 | dependency: transitive 44 | description: 45 | name: matcher 46 | url: "https://pub.dartlang.org" 47 | source: hosted 48 | version: "0.12.5" 49 | meta: 50 | dependency: transitive 51 | description: 52 | name: meta 53 | url: "https://pub.dartlang.org" 54 | source: hosted 55 | version: "1.1.6" 56 | path: 57 | dependency: transitive 58 | description: 59 | name: path 60 | url: "https://pub.dartlang.org" 61 | source: hosted 62 | version: "1.6.2" 63 | pedantic: 64 | dependency: transitive 65 | description: 66 | name: pedantic 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "1.5.0" 70 | quiver: 71 | dependency: transitive 72 | description: 73 | name: quiver 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "2.0.3" 77 | sky_engine: 78 | dependency: transitive 79 | description: flutter 80 | source: sdk 81 | version: "0.0.99" 82 | source_span: 83 | dependency: transitive 84 | description: 85 | name: source_span 86 | url: "https://pub.dartlang.org" 87 | source: hosted 88 | version: "1.5.5" 89 | stack_trace: 90 | dependency: transitive 91 | description: 92 | name: stack_trace 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "1.9.3" 96 | stream_channel: 97 | dependency: transitive 98 | description: 99 | name: stream_channel 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "2.0.0" 103 | string_scanner: 104 | dependency: transitive 105 | description: 106 | name: string_scanner 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.0.4" 110 | term_glyph: 111 | dependency: transitive 112 | description: 113 | name: term_glyph 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.1.0" 117 | test_api: 118 | dependency: transitive 119 | description: 120 | name: test_api 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "0.2.5" 124 | typed_data: 125 | dependency: transitive 126 | description: 127 | name: typed_data 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.1.6" 131 | vector_math: 132 | dependency: transitive 133 | description: 134 | name: vector_math 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "2.0.8" 138 | sdks: 139 | dart: ">=2.2.0 <3.0.0" 140 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: page_slider 2 | description: A simple Flutter widget that slides through pages horizontally. For wizards or onboarding flows similar to the Material Stepper widget, but without a particular UI - any widget can be a page to slide through. 3 | version: 0.0.2 4 | author: Julian Vossen 5 | homepage: https://github.com/julvo/flutter_page_slider 6 | 7 | environment: 8 | sdk: ">=2.1.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | -------------------------------------------------------------------------------- /test/page_slider_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | import 'package:page_slider/page_slider.dart'; 5 | 6 | void main() { 7 | testWidgets('tests back and forth sliding', (WidgetTester tester) async { 8 | final key = GlobalKey(); 9 | final slider = PageSlider( 10 | key: key, 11 | pages: [ 12 | Text('Page 0', textDirection: TextDirection.ltr), 13 | Text('Page 1', textDirection: TextDirection.ltr), 14 | Text('Page 2', textDirection: TextDirection.ltr), 15 | Text('Page 3', textDirection: TextDirection.ltr), 16 | ], 17 | ); 18 | 19 | await tester.pumpWidget(slider); 20 | 21 | final sliderState = key.currentState; 22 | 23 | expect(sliderState.currentPage, 0); 24 | expect(sliderState.hasPrevious, false); 25 | expect(sliderState.hasNext, true); 26 | 27 | sliderState.next(); 28 | expect(sliderState.currentPage, 1); 29 | expect(sliderState.hasPrevious, true); 30 | expect(sliderState.hasNext, true); 31 | 32 | sliderState.previous(); 33 | expect(sliderState.currentPage, 0); 34 | expect(sliderState.hasPrevious, false); 35 | expect(sliderState.hasNext, true); 36 | 37 | sliderState.setPage(3); 38 | expect(sliderState.currentPage, 3); 39 | expect(sliderState.hasPrevious, true); 40 | expect(sliderState.hasNext, false); 41 | }); 42 | } 43 | --------------------------------------------------------------------------------