├── .gitignore ├── LICENSE ├── README.md └── peek_and_pop ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example ├── .flutter-plugins-dependencies ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets │ ├── 0.jpeg │ ├── 1.jpeg │ ├── 10.jpeg │ ├── 11.jpeg │ ├── 12.jpeg │ ├── 13.jpeg │ ├── 14.jpeg │ ├── 15.jpeg │ ├── 16.jpeg │ ├── 17.jpeg │ ├── 18.jpeg │ ├── 19.jpeg │ ├── 2.jpeg │ ├── 20.jpeg │ ├── 21.jpeg │ ├── 22.jpeg │ ├── 23.jpeg │ ├── 24.jpeg │ ├── 25.jpeg │ ├── 26.jpeg │ ├── 27.jpeg │ ├── 28.jpeg │ ├── 29.jpeg │ ├── 3.jpeg │ ├── 4.jpeg │ ├── 5.jpeg │ ├── 6.jpeg │ ├── 7.jpeg │ ├── 8.jpeg │ ├── 9.jpeg │ ├── Hero.png │ └── Scenery.jpeg ├── lib │ ├── main.dart │ └── nav_bar.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── example_test.dart ├── lib ├── Export.dart ├── animated_cross_fade.dart ├── gesture_detector.dart ├── misc.dart ├── peek_and_pop.dart ├── peek_and_pop_child.dart ├── peek_and_pop_controller.dart └── peek_and_pop_detector.dart ├── pretty_example ├── .flutter-plugins-dependencies ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets │ ├── 0.jpeg │ ├── 1.jpeg │ ├── 10.jpeg │ ├── 11.jpeg │ ├── 12.jpeg │ ├── 13.jpeg │ ├── 14.jpeg │ ├── 15.jpeg │ ├── 16.jpeg │ ├── 17.jpeg │ ├── 18.jpeg │ ├── 19.jpeg │ ├── 2.jpeg │ ├── 20.jpeg │ ├── 21.jpeg │ ├── 22.jpeg │ ├── 23.jpeg │ ├── 24.jpeg │ ├── 25.jpeg │ ├── 26.jpeg │ ├── 27.jpeg │ ├── 28.jpeg │ ├── 29.jpeg │ ├── 3.jpeg │ ├── 4.jpeg │ ├── 5.jpeg │ ├── 6.jpeg │ ├── 7.jpeg │ ├── 8.jpeg │ ├── 9.jpeg │ ├── Hero.png │ └── Scenery.jpeg ├── lib │ ├── main.dart │ └── nav_bar.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── pretty_example_test.dart ├── pubspec.lock ├── pubspec.yaml └── test └── peek_and_pop_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # peek_and_pop 2 | 3 | [comment]: <> (Badges) 4 | 5 | Cosmos Software 6 | 7 | 8 | Cosmos Software 9 | 10 |
11 | 12 | 13 | Awesome Flutter 14 | 15 |
16 | 17 | [![Pub](https://img.shields.io/pub/v/peek_and_pop?color=g)](https://pub.dev/packages/peek_and_pop) 18 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-peek-and-pop?color=blue)](https://github.com/aliyigitbireroglu/flutter-peek-and-pop/blob/master/LICENSE) 19 | 20 | [comment]: <> (Introduction) 21 | 22 |

23 | Peek & Pop implementation for Flutter based on the iOS functionality of the same name. 24 | 25 | **Finally, the v1.0.0 release! More fluent, more optimised and more beautiful than ever. Very customisable and very easy to use.** 26 | 27 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range of 28 | capabilities.** 29 | 30 | [comment]: <> (ToC) 31 | [Media](#media) | [Description](#description) | [Installation](#installation) | [How-to-Use](#howtouse) 32 | 33 | [comment]: <> (Notice) 34 | ## Notice 35 | * **v0.1.9 and higher no longer requires any modifications to Flutter's normal "binding.dart"! You can leave your Flutter source code alone and happy.** 36 | 37 | * **If you are updating from an earlier version, you can revert your "binding.dart" to its original format.** 38 | * * * 39 | [comment]: <> (Recent) 40 | ## Recent 41 | * **The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 42 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 43 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See [Media](#media) for examples.** 44 | 45 | * **The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 46 | to the actual iOS version. See [Media](#media) for examples.** 47 | 48 | * **The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 49 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box.See [Media](#media) for examples.** 50 | 51 | * **Improved enumeration for the stage of the Peek & Pop process.** 52 | 53 | * **The "Indicator" feature is now added. See [Media](#media) for examples.** 54 | 55 | * **Animations are now up to 4x faster with the new optimised blur effect algorithm during the Peek & Pop process.** 56 | * * * 57 | [comment]: <> (Warning) 58 | ## Warning 59 | * **"isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 60 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 61 | while "willBeDone" or "isDone" is true.** 62 | 63 | * **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 64 | the relevant installation instructions.** 65 | * * * 66 | 67 | 68 | [comment]: <> (Media) 69 | 70 | ## Media 71 | 72 | Watch on **Youtube**: 73 | 74 | [**v1.0.0 Showcase Demo**](https://youtu.be/IQq_ty5mRYU) | [**v1.0.0 Technical Preview**](https://youtu.be/hIjoWfP0krA) 75 |

76 | [v0.1.7](https://youtu.be/wOWCV7HJzwc) 77 | 78 | [v0.1.0 Mixed](https://youtu.be/G5QLwGtcb1I) 79 | 80 | [v0.0.1 Normal](https://youtu.be/PaEpU31z_7Q) | [v0.0.1 Moveable](https://youtu.be/3TjCFwHoOiE) | [v0.0.1 Platform View](https://youtu.be/489YB-QuJ3k) | [v0.0.1 Hero](https://youtu.be/36DAwnFKSKI) 81 |

82 | 83 | 84 |

85 | 86 | 87 | [comment]: <> (Description) 88 | 89 | ## Description 90 | As a fan of the iOS Peek & Pop functionality, I decided to implement it for Flutter as well. 91 | 92 | The package has been tested on iOS but not yet on Android as I don't have access to an Android device with Force Press capabilities. Help about 93 | this would be appreciated. 94 | 95 | ~~For devices that don't support Force Press, the package comes with an adaptation to Long Press *however* the Long Press version of this package is 96 | still under development and is not yet fully tested so consider it as a developers preview.~~ 97 | 98 | (The Long Press version is temporarily removed. It will be added back soon.) 99 | 100 | ## 101 | The power move of this package is what I like to call "Gesture Recognition Rerouting". Normally, when a new widget with GestureDetector or similar 102 | is pushed over an initial widget used for detecting Force Press or when Navigator is used to pop a new page, the user has to restart the gesture 103 | for Flutter to resume updating it. This package fixes that problem as explained in the documentation: 104 | 105 | ``` 106 | //This function is called by the instantiated [PeekAndPopChild] once it is ready to be included in the Peek & Pop process. Perhaps the most 107 | //essential functionality of this package also takes places in this function: The gesture recognition is rerouted from the [PeekAndPopDetector] 108 | //to the instantiated [PeekAndPopChild]. This is important for avoiding the necessity of having the user stop and restart their Force Press. 109 | //Instead, the [PeekAndPopController] does this automatically so that the existing Force Press can continue to update even when if 110 | //[PeekAndPopDetector] is blocked by the view which is often the case especially when using PlatformViews. 111 | ``` 112 | 113 | 114 | [comment]: <> (Installation) 115 | 116 | ## Installation 117 | *It is easy. Don't worry.* 118 | 119 | **If you do not wish to use PlatformViews you can skip the installation instructions.** 120 | 121 | **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 122 | the relevant installation instructions.** 123 | 124 | For properly displaying PlatformViews, this package requires the latest Flutter [master](https://github.com/flutter/flutter) 125 | branch. *Maybe* it will work with some other version too but tests made with the [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) 126 | seem to only properly display with the latest Flutter [master](https://github.com/flutter/flutter) branch which has improved the PlatformViews that 127 | allow better functionalities such as proper scaling and proper clipping. 128 | 129 | If you do not wish to use PlatformViews, you can skip this step. 130 | 131 | To use latest Flutter [master](https://github.com/flutter/flutter) branch, run the following command. 132 | 133 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 134 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 135 | 136 | ``` 137 | $ git clone -b master https://github.com/flutter/flutter.git 138 | $ flutter channel master 139 | $ flutter upgrade 140 | $ flutter doctor 141 | $ ./flutter/bin/flutter --version 142 | ``` 143 | 144 | 145 | [comment]: <> (How-to-Use) 146 | 147 | ## How-to-Use 148 | *Also easy.* 149 | 150 | First of all, as explained in the documentation: 151 | 152 | ``` 153 | //I noticed that a fullscreen blur effect via the [BackdropFilter] widget is not good to use while running the animations required for the Peek & 154 | //Pop process as it causes a noticeable drop in the framerate- especially for devices with high resolutions. During a mostly static view, the 155 | //drop is acceptable. However, once the animations start running, this drop causes a visual disturbance. To prevent this, a new optimised blur 156 | //effect algorithm is implemented. Now, the [BackdropFilter] widget is only used until the animations are about to start. At that moment, it is 157 | //replaced by a static image. Therefore, to capture this image, your root CupertinoApp/MaterialApp MUST be wrapped in a [RepaintBoundary] widget 158 | //which uses the [background] key. As a result, the Peek & Pop process is now up to 4x more fluent. 159 | ``` 160 | 161 | TL;DR: Wrap your root CupertinoApp/MaterialApp in a RepaintBoundary widget and use the background GlobalKey from "misc.dart". 162 | 163 | This is required for the new optimised blur effect algorithm: 164 | 165 | ``` 166 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 167 | 168 | class MyApp extends StatelessWidget { 169 | @override 170 | Widget build(BuildContext context) { 171 | return RepaintBoundary( 172 | key: PeekAndPopMisc.background, 173 | child: MaterialApp( 174 | title: 'Peek & Pop Demo', 175 | home: MyHomePage(title: 'Peek & Pop Demo') 176 | ) 177 | ); 178 | } 179 | } 180 | ``` 181 | 182 | If you wish to use the "ScaleUp" or the "Scale Down" features, wrap the widgets you wish to scale down or scale up during the Peek & Pop process with 183 | the scaleUpWrapper and scaleDownWrapper functions from "misc.dart": 184 | 185 | ``` 186 | @override 187 | Widget build(BuildContext context) { 188 | return Scaffold( 189 | appBar: AppBar(title: Text(widget.title)), 190 | body: PeekAndPopMisc.scaleDownWrapper( 191 | ..., 192 | 0.04, 193 | ), 194 | ); 195 | } 196 | ``` 197 | 198 | Then, create a PeekAndPopController such as: 199 | 200 | ``` 201 | PeekAndPopController( 202 | uiChild(), //Widget uiChild 203 | false, //bool uiChildUseCache 204 | {Key key, 205 | peekAndPopBuilder, 206 | peekAndPopBuilderUseCache, 207 | peekAndPopBuilderAtPeek : peekAndPopBuilderAtPeek, 208 | peekAndPopBuilderAtPop : peekAndPopBuilderAtPop, 209 | quickActionsBuilder : quickActionsBuilder, 210 | sigma : 10, 211 | backdropColor : Colors.black, 212 | alpha : 126, 213 | overlayBuilder : overlayBuilder, 214 | useOverlap : true, 215 | customOverlapRect, 216 | useAlignment, : false, 217 | useIndicator : true, 218 | indicatorScaleUpCoefficient : 0.01, 219 | willPeekAndPopComplete : _willPeekAndPopComplete, 220 | willPushPeekAndPop : _willPushPeekAndPop, 221 | willUpdatePeekAndPop : _willUpdatePeekAndPop, 222 | willCancelPeekAndPop : _willCancelPeekAndPop, 223 | willFinishPeekAndPop : _willFinishPeekAndPop, 224 | willClosePeekAndPop : _willClosePeekAndPop, 225 | onPeekAndPopComplete : _onPeekAndPopComplete, 226 | onPushPeekAndPop : _onPushPeekAndPop, 227 | onUpdatePeekAndPop : _onUpdatePeekAndPop, 228 | onCancelPeekAndPop : _onCancelPeekAndPop, 229 | onFinishPeekAndPop : _onFinishPeekAndPop, 230 | onClosePeekAndPop : _onFinishPeekAndPop, 231 | onPressStart : _onPressStart, 232 | onPressUpdate : _onPressUpdate, 233 | onPressEnd : _onPressEnd, 234 | treshold : 0.5, 235 | startPressure : 0.125, 236 | peakPressure : 1.0, 237 | peekScale : 0.5, 238 | peekCoefficient : 0.05, 239 | popTransition, 240 | useHaptics : true}) 241 | 242 | Widget uiChild() {} 243 | 244 | Widget peekAndPopBuilderAtPeek(BuildContext context, PeekAndPopControllerState _peekAndPopController); 245 | Widget peekAndPopBuilderAtPop(BuildContext context, PeekAndPopControllerState _peekAndPopController); 246 | 247 | QuickActionsData quickActionsBuilder(PeekAndPopControllerState _peekAndPopController); 248 | 249 | WidgetBuilder overlayBuiler(BuildContext context); 250 | 251 | bool _willPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 252 | bool _willPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 253 | bool _willUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 254 | bool _willCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 255 | bool _willFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 256 | bool _willClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 257 | 258 | void _onPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 259 | void _onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 260 | void _onUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 261 | void _onCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 262 | void _onFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 263 | void _onClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 264 | 265 | void _onPressStart(dynamic dragDetails); 266 | void _onPressUpdate(dynamic dragDetails); 267 | void _onPressEnd(dynamic dragDetails); 268 | 269 | ``` 270 | 271 | **Further Explanations:** 272 | 273 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/peek_and_pop/latest/).* 274 | 275 | * Set [uiChildUseCache] to true if your [uiChild] doesn't change during the Peek & Pop process. 276 | * Set [peekAndPopBuilderUseCache] to true if your [peekAndPopBuilder] doesn't change during the Peek & Pop process. 277 | * If [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] are set, [peekAndPopBuilder] and [peekAndPopBuilderUseCache] are ignored. 278 | * If one of [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] is set, the other one must be set too. 279 | * If [quickActionsBuilder] is set, it is recommended that [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPop] are set too. 280 | * [overlayBuilder] is an optional second view to be displayed during the Peek & Pop process. This entire widget is built after everything else. 281 | * For all [PeekAndPopProcessNotifier] callbacks such as [willPeekAndPopComplete], you can return false to prevent the default action. 282 | * All [PeekAndPopProcessNotifier] and [PeekAndPopProcessCallback] callbacks will return a reference to the created [PeekAndPopController] state. 283 | You can save this instance for further actions. 284 | * [pageTransition] is the transition to be used when the view is opened directly or when the view is closed. A default [SlideTransition] is provided. 285 | * Use [PeekAndPopControllerState]'s [void closePeekAndPop()] method to close the Peek & Pop process. Do not call [Navigator.of(context).pop()] 286 | directly. 287 | * Use [PeekAndPopControllerState]'s [stage] variable to get enumeration for the stage of the Peek & Pop process. If you want to only know when the 288 | Peek & Pop process will be or is completed, you can also use [willBeDone] or [isDone] variables. 289 | 290 | 291 | [comment]: <> (Notes) 292 | ## Notes 293 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 294 | different, that could be much better, etc. Please let me know! Nicely! 295 | 296 | Any help, suggestion or criticism is appreciated! 297 | 298 | Cheers. 299 | 300 | [comment]: <> (CosmosSoftware) 301 |

302 | 303 |

-------------------------------------------------------------------------------- /peek_and_pop/.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /peek_and_pop/.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: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /peek_and_pop/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.3] - 21.11.2019 2 | 3 | * Minor changes. 4 | 5 | ## [1.0.2] - 07.09.2019 6 | 7 | * Two new PeekAndPopBuilders are added to [PeekAndPopController]. Use [PeekAndPopController.peekAndPopBuilderAtPeek] and 8 | [PeekAndPopController.peekAndPopBuilderAtPop] for both convenience and improved performance. 9 | 10 | * Improved performance. 11 | 12 | * [1.0.2+1] Support for latest dependencies. 13 | 14 | ## [1.0.1] - 03.09.2019 15 | 16 | * Minor changes. 17 | 18 | ## [1.0.0] - 30.08.2019 19 | 20 | * The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 21 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 22 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 23 | 24 | * The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 25 | to the actual iOS version. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 26 | 27 | * The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 28 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 29 | 30 | * "isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 31 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 32 | while "willBeDone" or "isDone" is true. 33 | 34 | * A workaround is implemented to avoid a Flutter Engine bug that was causing trouble with the optimised blur effect algorithm. 35 | 36 | * Improved enumeration for the stage of the Peek & Pop process. 37 | 38 | * Improved performance. 39 | 40 | * Fine tuning. 41 | 42 | * Improved code style. 43 | 44 | * Improved example project. 45 | 46 | * Updated README. 47 | 48 | * Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 49 | the relevant installation instructions. 50 | 51 | ## [0.2.0] - 23.08.2019 52 | 53 | * Improved performance. 54 | 55 | * Minor changes. 56 | 57 | * Improved code style with trailing commas. 58 | 59 | * [0.2.0+1] Minor changes. 60 | 61 | ## [0.1.9] - 20.08.2019 62 | 63 | * Modifications to Flutter's normal "binding.dart" are no longer required! 64 | 65 | * The Long Press version is temporarily removed. It will be added back soon. 66 | 67 | * Code excerpt added to the README. 68 | 69 | * Updated README. 70 | 71 | * [0.1.9+1] Updated README. 72 | 73 | ## [0.1.8] - 18.08.2019 74 | 75 | * Example project adapted to the updated [snap](https://pub.dev/packages/snap). 76 | 77 | * Minor changes. 78 | 79 | * [0.1.8+1] Updated README. 80 | 81 | ## [0.1.7] - 14.08.2019 82 | 83 | * The "Indicator" feature added. See this [video](https://youtu.be/wOWCV7HJzwc) for examples. 84 | 85 | * Improved performance. 86 | 87 | * Fine tuning. 88 | 89 | ## [0.1.6] - 12.08.2019 90 | 91 | * Improved Long Press version (still under development). 92 | 93 | * Fine tuning. 94 | 95 | * Improved documentation. 96 | 97 | * Updated README. 98 | 99 | ## [0.1.5] - 11.08.2019 100 | 101 | * Improved performance. 102 | 103 | * Improved code style. 104 | 105 | ## [0.1.4] - 11.08.2019 106 | 107 | * A minor bug is fixed. 108 | 109 | ## [0.1.3] - 07.08.2019 110 | 111 | * A minor bug in the example project is fixed. 112 | 113 | * Updated README: 114 | 115 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 116 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 117 | 118 | ## [0.1.2] - 07.08.2019 119 | 120 | * [snap](https://pub.dev/packages/snap) is now implemented directly to the example. 121 | 122 | * More callbacks added for better control. 123 | 124 | * Simple enumeration for the stage of the Peek & Pop process added. 125 | 126 | * Improved animations. 127 | 128 | * Improved documentation. 129 | 130 | ## [0.1.1] - 06.08.2019 131 | 132 | * Improved code style. 133 | 134 | ## [0.1.0] - 06.08.2019 135 | 136 | * Improved Long Press version (still under development). 137 | 138 | * Improved documentation. 139 | 140 | ## [0.0.1] - 05.08.2019 141 | 142 | * Initial release. 143 | -------------------------------------------------------------------------------- /peek_and_pop/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 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. 22 | -------------------------------------------------------------------------------- /peek_and_pop/README.md: -------------------------------------------------------------------------------- 1 | # peek_and_pop 2 | 3 | [comment]: <> (Badges) 4 | 5 | Cosmos Software 6 | 7 | 8 | Cosmos Software 9 | 10 |
11 | 12 | 13 | Awesome Flutter 14 | 15 |
16 | 17 | [![Pub](https://img.shields.io/pub/v/peek_and_pop?color=g)](https://pub.dev/packages/peek_and_pop) 18 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-peek-and-pop?color=blue)](https://github.com/aliyigitbireroglu/flutter-peek-and-pop/blob/master/LICENSE) 19 | 20 | [comment]: <> (Introduction) 21 | 22 |

23 | Peek & Pop implementation for Flutter based on the iOS functionality of the same name. 24 | 25 | **Finally, the v1.0.0 release! More fluent, more optimised and more beautiful than ever. Very customisable and very easy to use.** 26 | 27 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range of 28 | capabilities.** 29 | 30 | [comment]: <> (ToC) 31 | [Media](#media) | [Description](#description) | [Installation](#installation) | [How-to-Use](#howtouse) 32 | 33 | [comment]: <> (Notice) 34 | ## Notice 35 | * **v0.1.9 and higher no longer requires any modifications to Flutter's normal "binding.dart"! You can leave your Flutter source code alone and happy.** 36 | 37 | * **If you are updating from an earlier version, you can revert your "binding.dart" to its original format.** 38 | * * * 39 | [comment]: <> (Recent) 40 | ## Recent 41 | * **The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 42 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 43 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See [Media](#media) for examples.** 44 | 45 | * **The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 46 | to the actual iOS version. See [Media](#media) for examples.** 47 | 48 | * **The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 49 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box.See [Media](#media) for examples.** 50 | 51 | * **Improved enumeration for the stage of the Peek & Pop process.** 52 | 53 | * **The "Indicator" feature is now added. See [Media](#media) for examples.** 54 | 55 | * **Animations are now up to 4x faster with the new optimised blur effect algorithm during the Peek & Pop process.** 56 | * * * 57 | [comment]: <> (Warning) 58 | ## Warning 59 | * **"isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 60 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 61 | while "willBeDone" or "isDone" is true.** 62 | 63 | * **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 64 | the relevant installation instructions.** 65 | * * * 66 | 67 | 68 | [comment]: <> (Media) 69 | 70 | ## Media 71 | 72 | Watch on **Youtube**: 73 | 74 | [**v1.0.0 Showcase Demo**](https://youtu.be/IQq_ty5mRYU) | [**v1.0.0 Technical Preview**](https://youtu.be/hIjoWfP0krA) 75 |

76 | [v0.1.7](https://youtu.be/wOWCV7HJzwc) 77 | 78 | [v0.1.0 Mixed](https://youtu.be/G5QLwGtcb1I) 79 | 80 | [v0.0.1 Normal](https://youtu.be/PaEpU31z_7Q) | [v0.0.1 Moveable](https://youtu.be/3TjCFwHoOiE) | [v0.0.1 Platform View](https://youtu.be/489YB-QuJ3k) | [v0.0.1 Hero](https://youtu.be/36DAwnFKSKI) 81 |

82 | 83 | 84 |

85 | 86 | 87 | [comment]: <> (Description) 88 | 89 | ## Description 90 | As a fan of the iOS Peek & Pop functionality, I decided to implement it for Flutter as well. 91 | 92 | The package has been tested on iOS but not yet on Android as I don't have access to an Android device with Force Press capabilities. Help about 93 | this would be appreciated. 94 | 95 | ~~For devices that don't support Force Press, the package comes with an adaptation to Long Press *however* the Long Press version of this package is 96 | still under development and is not yet fully tested so consider it as a developers preview.~~ 97 | 98 | (The Long Press version is temporarily removed. It will be added back soon.) 99 | 100 | ## 101 | The power move of this package is what I like to call "Gesture Recognition Rerouting". Normally, when a new widget with GestureDetector or similar 102 | is pushed over an initial widget used for detecting Force Press or when Navigator is used to pop a new page, the user has to restart the gesture 103 | for Flutter to resume updating it. This package fixes that problem as explained in the documentation: 104 | 105 | ``` 106 | //This function is called by the instantiated [PeekAndPopChild] once it is ready to be included in the Peek & Pop process. Perhaps the most 107 | //essential functionality of this package also takes places in this function: The gesture recognition is rerouted from the [PeekAndPopDetector] 108 | //to the instantiated [PeekAndPopChild]. This is important for avoiding the necessity of having the user stop and restart their Force Press. 109 | //Instead, the [PeekAndPopController] does this automatically so that the existing Force Press can continue to update even when if 110 | //[PeekAndPopDetector] is blocked by the view which is often the case especially when using PlatformViews. 111 | ``` 112 | 113 | 114 | [comment]: <> (Installation) 115 | 116 | ## Installation 117 | *It is easy. Don't worry.* 118 | 119 | **If you do not wish to use PlatformViews you can skip the installation instructions.** 120 | 121 | **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 122 | the relevant installation instructions.** 123 | 124 | For properly displaying PlatformViews, this package requires the latest Flutter [master](https://github.com/flutter/flutter) 125 | branch. *Maybe* it will work with some other version too but tests made with the [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) 126 | seem to only properly display with the latest Flutter [master](https://github.com/flutter/flutter) branch which has improved the PlatformViews that 127 | allow better functionalities such as proper scaling and proper clipping. 128 | 129 | If you do not wish to use PlatformViews, you can skip this step. 130 | 131 | To use latest Flutter [master](https://github.com/flutter/flutter) branch, run the following command. 132 | 133 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 134 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 135 | 136 | ``` 137 | $ git clone -b master https://github.com/flutter/flutter.git 138 | $ flutter channel master 139 | $ flutter upgrade 140 | $ flutter doctor 141 | $ ./flutter/bin/flutter --version 142 | ``` 143 | 144 | 145 | [comment]: <> (How-to-Use) 146 | 147 | ## How-to-Use 148 | *Also easy.* 149 | 150 | First of all, as explained in the documentation: 151 | 152 | ``` 153 | //I noticed that a fullscreen blur effect via the [BackdropFilter] widget is not good to use while running the animations required for the Peek & 154 | //Pop process as it causes a noticeable drop in the framerate- especially for devices with high resolutions. During a mostly static view, the 155 | //drop is acceptable. However, once the animations start running, this drop causes a visual disturbance. To prevent this, a new optimised blur 156 | //effect algorithm is implemented. Now, the [BackdropFilter] widget is only used until the animations are about to start. At that moment, it is 157 | //replaced by a static image. Therefore, to capture this image, your root CupertinoApp/MaterialApp MUST be wrapped in a [RepaintBoundary] widget 158 | //which uses the [background] key. As a result, the Peek & Pop process is now up to 4x more fluent. 159 | ``` 160 | 161 | TL;DR: Wrap your root CupertinoApp/MaterialApp in a RepaintBoundary widget and use the background GlobalKey from "misc.dart". 162 | 163 | This is required for the new optimised blur effect algorithm: 164 | 165 | ``` 166 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 167 | 168 | class MyApp extends StatelessWidget { 169 | @override 170 | Widget build(BuildContext context) { 171 | return RepaintBoundary( 172 | key: PeekAndPopMisc.background, 173 | child: MaterialApp( 174 | title: 'Peek & Pop Demo', 175 | home: MyHomePage(title: 'Peek & Pop Demo') 176 | ) 177 | ); 178 | } 179 | } 180 | ``` 181 | 182 | If you wish to use the "ScaleUp" or the "Scale Down" features, wrap the widgets you wish to scale down or scale up during the Peek & Pop process with 183 | the scaleUpWrapper and scaleDownWrapper functions from "misc.dart": 184 | 185 | ``` 186 | @override 187 | Widget build(BuildContext context) { 188 | return Scaffold( 189 | appBar: AppBar(title: Text(widget.title)), 190 | body: PeekAndPopMisc.scaleDownWrapper( 191 | ..., 192 | 0.04, 193 | ), 194 | ); 195 | } 196 | ``` 197 | 198 | Then, create a PeekAndPopController such as: 199 | 200 | ``` 201 | PeekAndPopController( 202 | uiChild(), //Widget uiChild 203 | false, //bool uiChildUseCache 204 | {Key key, 205 | peekAndPopBuilder, 206 | peekAndPopBuilderUseCache, 207 | peekAndPopBuilderAtPeek : peekAndPopBuilderAtPeek, 208 | peekAndPopBuilderAtPop : peekAndPopBuilderAtPop, 209 | quickActionsBuilder : quickActionsBuilder, 210 | sigma : 10, 211 | backdropColor : Colors.black, 212 | alpha : 126, 213 | overlayBuilder : overlayBuilder, 214 | useOverlap : true, 215 | customOverlapRect, 216 | useAlignment, : false, 217 | useIndicator : true, 218 | indicatorScaleUpCoefficient : 0.01, 219 | willPeekAndPopComplete : _willPeekAndPopComplete, 220 | willPushPeekAndPop : _willPushPeekAndPop, 221 | willUpdatePeekAndPop : _willUpdatePeekAndPop, 222 | willCancelPeekAndPop : _willCancelPeekAndPop, 223 | willFinishPeekAndPop : _willFinishPeekAndPop, 224 | willClosePeekAndPop : _willClosePeekAndPop, 225 | onPeekAndPopComplete : _onPeekAndPopComplete, 226 | onPushPeekAndPop : _onPushPeekAndPop, 227 | onUpdatePeekAndPop : _onUpdatePeekAndPop, 228 | onCancelPeekAndPop : _onCancelPeekAndPop, 229 | onFinishPeekAndPop : _onFinishPeekAndPop, 230 | onClosePeekAndPop : _onFinishPeekAndPop, 231 | onPressStart : _onPressStart, 232 | onPressUpdate : _onPressUpdate, 233 | onPressEnd : _onPressEnd, 234 | treshold : 0.5, 235 | startPressure : 0.125, 236 | peakPressure : 1.0, 237 | peekScale : 0.5, 238 | peekCoefficient : 0.05, 239 | popTransition, 240 | useHaptics : true}) 241 | 242 | Widget uiChild() {} 243 | 244 | Widget peekAndPopBuilderAtPeek(BuildContext context, PeekAndPopControllerState _peekAndPopController); 245 | Widget peekAndPopBuilderAtPop(BuildContext context, PeekAndPopControllerState _peekAndPopController); 246 | 247 | QuickActionsData quickActionsBuilder(PeekAndPopControllerState _peekAndPopController); 248 | 249 | WidgetBuilder overlayBuiler(BuildContext context); 250 | 251 | bool _willPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 252 | bool _willPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 253 | bool _willUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 254 | bool _willCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 255 | bool _willFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 256 | bool _willClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 257 | 258 | void _onPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 259 | void _onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 260 | void _onUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 261 | void _onCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 262 | void _onFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 263 | void _onClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 264 | 265 | void _onPressStart(dynamic dragDetails); 266 | void _onPressUpdate(dynamic dragDetails); 267 | void _onPressEnd(dynamic dragDetails); 268 | 269 | ``` 270 | 271 | **Further Explanations:** 272 | 273 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/peek_and_pop/latest/).* 274 | 275 | * Set [uiChildUseCache] to true if your [uiChild] doesn't change during the Peek & Pop process. 276 | * Set [peekAndPopBuilderUseCache] to true if your [peekAndPopBuilder] doesn't change during the Peek & Pop process. 277 | * If [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] are set, [peekAndPopBuilder] and [peekAndPopBuilderUseCache] are ignored. 278 | * If one of [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] is set, the other one must be set too. 279 | * If [quickActionsBuilder] is set, it is recommended that [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPop] are set too. 280 | * [overlayBuilder] is an optional second view to be displayed during the Peek & Pop process. This entire widget is built after everything else. 281 | * For all [PeekAndPopProcessNotifier] callbacks such as [willPeekAndPopComplete], you can return false to prevent the default action. 282 | * All [PeekAndPopProcessNotifier] and [PeekAndPopProcessCallback] callbacks will return a reference to the created [PeekAndPopController] state. 283 | You can save this instance for further actions. 284 | * [pageTransition] is the transition to be used when the view is opened directly or when the view is closed. A default [SlideTransition] is provided. 285 | * Use [PeekAndPopControllerState]'s [void closePeekAndPop()] method to close the Peek & Pop process. Do not call [Navigator.of(context).pop()] 286 | directly. 287 | * Use [PeekAndPopControllerState]'s [stage] variable to get enumeration for the stage of the Peek & Pop process. If you want to only know when the 288 | Peek & Pop process will be or is completed, you can also use [willBeDone] or [isDone] variables. 289 | 290 | 291 | [comment]: <> (Notes) 292 | ## Notes 293 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 294 | different, that could be much better, etc. Please let me know! Nicely! 295 | 296 | Any help, suggestion or criticism is appreciated! 297 | 298 | Cheers. 299 | 300 | [comment]: <> (CosmosSoftware) 301 |

302 | 303 |

-------------------------------------------------------------------------------- /peek_and_pop/example/.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"webview_flutter","path":"/Users/fabriziotognetto/Library/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter-0.3.13/","dependencies":[]}],"android":[{"name":"webview_flutter","path":"/Users/fabriziotognetto/Library/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter-0.3.13/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"webview_flutter","dependencies":[]}],"date_created":"2020-09-23 23:12:06.440462","version":"1.22.0-12.1.pre"} -------------------------------------------------------------------------------- /peek_and_pop/example/.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /peek_and_pop/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: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /peek_and_pop/example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.3] - 21.11.2019 2 | 3 | * Minor changes. 4 | 5 | ## [1.0.2] - 07.09.2019 6 | 7 | * Two new PeekAndPopBuilders are added to [PeekAndPopController]. Use [PeekAndPopController.peekAndPopBuilderAtPeek] and 8 | [PeekAndPopController.peekAndPopBuilderAtPop] for both convenience and improved performance. 9 | 10 | * Improved performance. 11 | 12 | * [1.0.2+1] Support for latest dependencies. 13 | 14 | ## [1.0.1] - 03.09.2019 15 | 16 | * Minor changes. 17 | 18 | ## [1.0.0] - 30.08.2019 19 | 20 | * The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 21 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 22 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 23 | 24 | * The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 25 | to the actual iOS version. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 26 | 27 | * The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 28 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 29 | 30 | * "isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 31 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 32 | while "willBeDone" or "isDone" is true. 33 | 34 | * A workaround is implemented to avoid a Flutter Engine bug that was causing trouble with the optimised blur effect algorithm. 35 | 36 | * Improved enumeration for the stage of the Peek & Pop process. 37 | 38 | * Improved performance. 39 | 40 | * Fine tuning. 41 | 42 | * Improved code style. 43 | 44 | * Improved example project. 45 | 46 | * Updated README. 47 | 48 | * Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 49 | the relevant installation instructions. 50 | 51 | ## [0.2.0] - 23.08.2019 52 | 53 | * Improved performance. 54 | 55 | * Minor changes. 56 | 57 | * Improved code style with trailing commas. 58 | 59 | * [0.2.0+1] Minor changes. 60 | 61 | ## [0.1.9] - 20.08.2019 62 | 63 | * Modifications to Flutter's normal "binding.dart" are no longer required! 64 | 65 | * The Long Press version is temporarily removed. It will be added back soon. 66 | 67 | * Code excerpt added to the README. 68 | 69 | * Updated README. 70 | 71 | * [0.1.9+1] Updated README. 72 | 73 | ## [0.1.8] - 18.08.2019 74 | 75 | * Example project adapted to the updated [snap](https://pub.dev/packages/snap). 76 | 77 | * Minor changes. 78 | 79 | * [0.1.8+1] Updated README. 80 | 81 | ## [0.1.7] - 14.08.2019 82 | 83 | * The "Indicator" feature added. See this [video](https://youtu.be/wOWCV7HJzwc) for examples. 84 | 85 | * Improved performance. 86 | 87 | * Fine tuning. 88 | 89 | ## [0.1.6] - 12.08.2019 90 | 91 | * Improved Long Press version (still under development). 92 | 93 | * Fine tuning. 94 | 95 | * Improved documentation. 96 | 97 | * Updated README. 98 | 99 | ## [0.1.5] - 11.08.2019 100 | 101 | * Improved performance. 102 | 103 | * Improved code style. 104 | 105 | ## [0.1.4] - 11.08.2019 106 | 107 | * A minor bug is fixed. 108 | 109 | ## [0.1.3] - 07.08.2019 110 | 111 | * A minor bug in the example project is fixed. 112 | 113 | * Updated README: 114 | 115 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 116 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 117 | 118 | ## [0.1.2] - 07.08.2019 119 | 120 | * [snap](https://pub.dev/packages/snap) is now implemented directly to the example. 121 | 122 | * More callbacks added for better control. 123 | 124 | * Simple enumeration for the stage of the Peek & Pop process added. 125 | 126 | * Improved animations. 127 | 128 | * Improved documentation. 129 | 130 | ## [0.1.1] - 06.08.2019 131 | 132 | * Improved code style. 133 | 134 | ## [0.1.0] - 06.08.2019 135 | 136 | * Improved Long Press version (still under development). 137 | 138 | * Improved documentation. 139 | 140 | ## [0.0.1] - 05.08.2019 141 | 142 | * Initial release. 143 | -------------------------------------------------------------------------------- /peek_and_pop/example/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 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. 22 | -------------------------------------------------------------------------------- /peek_and_pop/example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Example Project for peek_and_pop. 4 | 5 | Note: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 6 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 7 | 8 | 9 | # peek_and_pop 10 | 11 | [comment]: <> (Badges) 12 | 13 | Cosmos Software 14 | 15 | 16 | Cosmos Software 17 | 18 |
19 | 20 | 21 | Awesome Flutter 22 | 23 |
24 | 25 | [![Pub](https://img.shields.io/pub/v/peek_and_pop?color=g)](https://pub.dev/packages/peek_and_pop) 26 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-peek-and-pop?color=blue)](https://github.com/aliyigitbireroglu/flutter-peek-and-pop/blob/master/LICENSE) 27 | 28 | [comment]: <> (Introduction) 29 | 30 |

31 | Peek & Pop implementation for Flutter based on the iOS functionality of the same name. 32 | 33 | **Finally, the v1.0.0 release! More fluent, more optimised and more beautiful than ever. Very customisable and very easy to use.** 34 | 35 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range of 36 | capabilities.** 37 | 38 | [comment]: <> (ToC) 39 | [Media](#media) | [Description](#description) | [Installation](#installation) | [How-to-Use](#howtouse) 40 | 41 | [comment]: <> (Notice) 42 | ## Notice 43 | * **v0.1.9 and higher no longer requires any modifications to Flutter's normal "binding.dart"! You can leave your Flutter source code alone and happy.** 44 | 45 | * **If you are updating from an earlier version, you can revert your "binding.dart" to its original format.** 46 | * * * 47 | [comment]: <> (Recent) 48 | ## Recent 49 | * **The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 50 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 51 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See [Media](#media) for examples.** 52 | 53 | * **The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 54 | to the actual iOS version. See [Media](#media) for examples.** 55 | 56 | * **The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 57 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box.See [Media](#media) for examples.** 58 | 59 | * **Improved enumeration for the stage of the Peek & Pop process.** 60 | 61 | * **The "Indicator" feature is now added. See [Media](#media) for examples.** 62 | 63 | * **Animations are now up to 4x faster with the new optimised blur effect algorithm during the Peek & Pop process.** 64 | * * * 65 | [comment]: <> (Warning) 66 | ## Warning 67 | * **"isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 68 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 69 | while "willBeDone" or "isDone" is true.** 70 | 71 | * **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 72 | the relevant installation instructions.** 73 | * * * 74 | 75 | 76 | [comment]: <> (Media) 77 | 78 | ## Media 79 | 80 | Watch on **Youtube**: 81 | 82 | [**v1.0.0 Showcase Demo**](https://youtu.be/IQq_ty5mRYU) | [**v1.0.0 Technical Preview**](https://youtu.be/hIjoWfP0krA) 83 |

84 | [v0.1.7](https://youtu.be/wOWCV7HJzwc) 85 | 86 | [v0.1.0 Mixed](https://youtu.be/G5QLwGtcb1I) 87 | 88 | [v0.0.1 Normal](https://youtu.be/PaEpU31z_7Q) | [v0.0.1 Moveable](https://youtu.be/3TjCFwHoOiE) | [v0.0.1 Platform View](https://youtu.be/489YB-QuJ3k) | [v0.0.1 Hero](https://youtu.be/36DAwnFKSKI) 89 |

90 | 91 | 92 |

93 | 94 | 95 | [comment]: <> (Description) 96 | 97 | ## Description 98 | As a fan of the iOS Peek & Pop functionality, I decided to implement it for Flutter as well. 99 | 100 | The package has been tested on iOS but not yet on Android as I don't have access to an Android device with Force Press capabilities. Help about 101 | this would be appreciated. 102 | 103 | ~~For devices that don't support Force Press, the package comes with an adaptation to Long Press *however* the Long Press version of this package is 104 | still under development and is not yet fully tested so consider it as a developers preview.~~ 105 | 106 | (The Long Press version is temporarily removed. It will be added back soon.) 107 | 108 | ## 109 | The power move of this package is what I like to call "Gesture Recognition Rerouting". Normally, when a new widget with GestureDetector or similar 110 | is pushed over an initial widget used for detecting Force Press or when Navigator is used to pop a new page, the user has to restart the gesture 111 | for Flutter to resume updating it. This package fixes that problem as explained in the documentation: 112 | 113 | ``` 114 | //This function is called by the instantiated [PeekAndPopChild] once it is ready to be included in the Peek & Pop process. Perhaps the most 115 | //essential functionality of this package also takes places in this function: The gesture recognition is rerouted from the [PeekAndPopDetector] 116 | //to the instantiated [PeekAndPopChild]. This is important for avoiding the necessity of having the user stop and restart their Force Press. 117 | //Instead, the [PeekAndPopController] does this automatically so that the existing Force Press can continue to update even when if 118 | //[PeekAndPopDetector] is blocked by the view which is often the case especially when using PlatformViews. 119 | ``` 120 | 121 | 122 | [comment]: <> (Installation) 123 | 124 | ## Installation 125 | *It is easy. Don't worry.* 126 | 127 | **If you do not wish to use PlatformViews you can skip the installation instructions.** 128 | 129 | **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 130 | the relevant installation instructions.** 131 | 132 | For properly displaying PlatformViews, this package requires the latest Flutter [master](https://github.com/flutter/flutter) 133 | branch. *Maybe* it will work with some other version too but tests made with the [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) 134 | seem to only properly display with the latest Flutter [master](https://github.com/flutter/flutter) branch which has improved the PlatformViews that 135 | allow better functionalities such as proper scaling and proper clipping. 136 | 137 | If you do not wish to use PlatformViews, you can skip this step. 138 | 139 | To use latest Flutter [master](https://github.com/flutter/flutter) branch, run the following command. 140 | 141 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 142 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 143 | 144 | ``` 145 | $ git clone -b master https://github.com/flutter/flutter.git 146 | $ flutter channel master 147 | $ flutter upgrade 148 | $ flutter doctor 149 | $ ./flutter/bin/flutter --version 150 | ``` 151 | 152 | 153 | [comment]: <> (How-to-Use) 154 | 155 | ## How-to-Use 156 | *Also easy.* 157 | 158 | First of all, as explained in the documentation: 159 | 160 | ``` 161 | //I noticed that a fullscreen blur effect via the [BackdropFilter] widget is not good to use while running the animations required for the Peek & 162 | //Pop process as it causes a noticeable drop in the framerate- especially for devices with high resolutions. During a mostly static view, the 163 | //drop is acceptable. However, once the animations start running, this drop causes a visual disturbance. To prevent this, a new optimised blur 164 | //effect algorithm is implemented. Now, the [BackdropFilter] widget is only used until the animations are about to start. At that moment, it is 165 | //replaced by a static image. Therefore, to capture this image, your root CupertinoApp/MaterialApp MUST be wrapped in a [RepaintBoundary] widget 166 | //which uses the [background] key. As a result, the Peek & Pop process is now up to 4x more fluent. 167 | ``` 168 | 169 | TL;DR: Wrap your root CupertinoApp/MaterialApp in a RepaintBoundary widget and use the background GlobalKey from "misc.dart". 170 | 171 | This is required for the new optimised blur effect algorithm: 172 | 173 | ``` 174 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 175 | 176 | class MyApp extends StatelessWidget { 177 | @override 178 | Widget build(BuildContext context) { 179 | return RepaintBoundary( 180 | key: PeekAndPopMisc.background, 181 | child: MaterialApp( 182 | title: 'Peek & Pop Demo', 183 | home: MyHomePage(title: 'Peek & Pop Demo') 184 | ) 185 | ); 186 | } 187 | } 188 | ``` 189 | 190 | If you wish to use the "ScaleUp" or the "Scale Down" features, wrap the widgets you wish to scale down or scale up during the Peek & Pop process with 191 | the scaleUpWrapper and scaleDownWrapper functions from "misc.dart": 192 | 193 | ``` 194 | @override 195 | Widget build(BuildContext context) { 196 | return Scaffold( 197 | appBar: AppBar(title: Text(widget.title)), 198 | body: PeekAndPopMisc.scaleDownWrapper( 199 | ..., 200 | 0.04, 201 | ), 202 | ); 203 | } 204 | ``` 205 | 206 | Then, create a PeekAndPopController such as: 207 | 208 | ``` 209 | PeekAndPopController( 210 | uiChild(), //Widget uiChild 211 | false, //bool uiChildUseCache 212 | {Key key, 213 | peekAndPopBuilder, 214 | peekAndPopBuilderUseCache, 215 | peekAndPopBuilderAtPeek : peekAndPopBuilderAtPeek, 216 | peekAndPopBuilderAtPop : peekAndPopBuilderAtPop, 217 | quickActionsBuilder : quickActionsBuilder, 218 | sigma : 10, 219 | backdropColor : Colors.black, 220 | alpha : 126, 221 | overlayBuilder : overlayBuilder, 222 | useOverlap : true, 223 | customOverlapRect, 224 | useAlignment, : false, 225 | useIndicator : true, 226 | indicatorScaleUpCoefficient : 0.01, 227 | willPeekAndPopComplete : _willPeekAndPopComplete, 228 | willPushPeekAndPop : _willPushPeekAndPop, 229 | willUpdatePeekAndPop : _willUpdatePeekAndPop, 230 | willCancelPeekAndPop : _willCancelPeekAndPop, 231 | willFinishPeekAndPop : _willFinishPeekAndPop, 232 | willClosePeekAndPop : _willClosePeekAndPop, 233 | onPeekAndPopComplete : _onPeekAndPopComplete, 234 | onPushPeekAndPop : _onPushPeekAndPop, 235 | onUpdatePeekAndPop : _onUpdatePeekAndPop, 236 | onCancelPeekAndPop : _onCancelPeekAndPop, 237 | onFinishPeekAndPop : _onFinishPeekAndPop, 238 | onClosePeekAndPop : _onFinishPeekAndPop, 239 | onPressStart : _onPressStart, 240 | onPressUpdate : _onPressUpdate, 241 | onPressEnd : _onPressEnd, 242 | treshold : 0.5, 243 | startPressure : 0.125, 244 | peakPressure : 1.0, 245 | peekScale : 0.5, 246 | peekCoefficient : 0.05, 247 | popTransition, 248 | useHaptics : true}) 249 | 250 | Widget uiChild() {} 251 | 252 | Widget peekAndPopBuilderAtPeek(BuildContext context, PeekAndPopControllerState _peekAndPopController); 253 | Widget peekAndPopBuilderAtPop(BuildContext context, PeekAndPopControllerState _peekAndPopController); 254 | 255 | QuickActionsData quickActionsBuilder(PeekAndPopControllerState _peekAndPopController); 256 | 257 | WidgetBuilder overlayBuiler(BuildContext context); 258 | 259 | bool _willPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 260 | bool _willPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 261 | bool _willUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 262 | bool _willCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 263 | bool _willFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 264 | bool _willClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 265 | 266 | void _onPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 267 | void _onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 268 | void _onUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 269 | void _onCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 270 | void _onFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 271 | void _onClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 272 | 273 | void _onPressStart(dynamic dragDetails); 274 | void _onPressUpdate(dynamic dragDetails); 275 | void _onPressEnd(dynamic dragDetails); 276 | 277 | ``` 278 | 279 | **Further Explanations:** 280 | 281 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/peek_and_pop/latest/).* 282 | 283 | * Set [uiChildUseCache] to true if your [uiChild] doesn't change during the Peek & Pop process. 284 | * Set [peekAndPopBuilderUseCache] to true if your [peekAndPopBuilder] doesn't change during the Peek & Pop process. 285 | * If [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] are set, [peekAndPopBuilder] and [peekAndPopBuilderUseCache] are ignored. 286 | * If one of [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] is set, the other one must be set too. 287 | * If [quickActionsBuilder] is set, it is recommended that [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPop] are set too. 288 | * [overlayBuilder] is an optional second view to be displayed during the Peek & Pop process. This entire widget is built after everything else. 289 | * For all [PeekAndPopProcessNotifier] callbacks such as [willPeekAndPopComplete], you can return false to prevent the default action. 290 | * All [PeekAndPopProcessNotifier] and [PeekAndPopProcessCallback] callbacks will return a reference to the created [PeekAndPopController] state. 291 | You can save this instance for further actions. 292 | * [pageTransition] is the transition to be used when the view is opened directly or when the view is closed. A default [SlideTransition] is provided. 293 | * Use [PeekAndPopControllerState]'s [void closePeekAndPop()] method to close the Peek & Pop process. Do not call [Navigator.of(context).pop()] 294 | directly. 295 | * Use [PeekAndPopControllerState]'s [stage] variable to get enumeration for the stage of the Peek & Pop process. If you want to only know when the 296 | Peek & Pop process will be or is completed, you can also use [willBeDone] or [isDone] variables. 297 | 298 | 299 | [comment]: <> (Notes) 300 | ## Notes 301 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 302 | different, that could be much better, etc. Please let me know! Nicely! 303 | 304 | Any help, suggestion or criticism is appreciated! 305 | 306 | Cheers. 307 | 308 | [comment]: <> (CosmosSoftware) 309 |

310 | 311 |

-------------------------------------------------------------------------------- /peek_and_pop/example/assets/0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/0.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/1.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/10.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/10.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/11.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/11.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/12.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/12.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/13.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/13.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/14.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/14.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/15.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/15.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/16.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/16.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/17.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/17.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/18.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/18.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/19.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/19.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/2.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/20.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/20.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/21.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/21.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/22.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/22.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/23.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/23.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/24.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/24.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/25.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/25.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/26.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/26.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/27.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/27.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/28.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/28.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/29.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/29.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/3.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/4.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/5.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/6.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/7.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/7.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/8.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/9.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/assets/Hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/Hero.png -------------------------------------------------------------------------------- /peek_and_pop/example/assets/Scenery.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/assets/Scenery.jpeg -------------------------------------------------------------------------------- /peek_and_pop/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | //Note: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 2 | //[webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 3 | 4 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 | // © Cosmos Software | Ali Yigit Bireroglu / 6 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 7 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 8 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 9 | // text at all times. / 10 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | //@formatter:off 12 | 13 | import 'package:flutter/foundation.dart'; 14 | import 'package:flutter/cupertino.dart'; 15 | import 'package:flutter/material.dart'; 16 | import 'package:flutter/services.dart'; 17 | 18 | import 'package:webview_flutter/webview_flutter.dart'; 19 | import 'nav_bar.dart' as MyNavBar; 20 | 21 | import 'package:peek_and_pop/peek_and_pop.dart'; 22 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 23 | 24 | PeekAndPopControllerState peekAndPopController; 25 | 26 | final GlobalKey scaffold = GlobalKey(); 27 | final GlobalKey header = GlobalKey(); 28 | 29 | void main() => runApp(MyApp()); 30 | 31 | class MyApp extends StatelessWidget { 32 | @override 33 | Widget build(BuildContext context) { 34 | return RepaintBoundary( 35 | key: PeekAndPopMisc.background, 36 | child: MaterialApp( 37 | title: 'Peek & Pop Demo', 38 | theme: ThemeData(primarySwatch: Colors.blue), 39 | home: MyHomePage(title: 'Peek & Pop Demo'), 40 | ), 41 | ); 42 | } 43 | } 44 | 45 | class MyHomePage extends StatefulWidget { 46 | MyHomePage({Key key, this.title}) : super(key: key); 47 | 48 | final String title; 49 | 50 | @override 51 | _MyHomePageState createState() => _MyHomePageState(); 52 | } 53 | 54 | class _MyHomePageState extends State { 55 | void onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController) { 56 | peekAndPopController = _peekAndPopController; 57 | } 58 | 59 | void showSnackbar() { 60 | scaffold.currentState.showSnackBar(SnackBar(content: const Text("Everything works as usual."))); 61 | } 62 | 63 | Widget paddingWrapper(Widget child) { 64 | return Container( 65 | color: Colors.transparent, 66 | child: Padding( 67 | padding: EdgeInsets.all(25), 68 | child: child, 69 | ), 70 | ); 71 | } 72 | 73 | Widget atPeekWrapper(Widget child, PeekAndPopControllerState _peekAndPopController) { 74 | return Container( 75 | decoration: BoxDecoration( 76 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 77 | boxShadow: [ 78 | const BoxShadow( 79 | color: Colors.black, 80 | offset: const Offset(0, 15), 81 | spreadRadius: -5, 82 | blurRadius: 20, 83 | ), 84 | ], 85 | ), 86 | child: ClipRRect( 87 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 88 | child: child, 89 | ), 90 | ); 91 | } 92 | 93 | MyNavBar.CupertinoNavigationBar appBar(PeekAndPopControllerState _peekAndPopController) { 94 | return MyNavBar.CupertinoNavigationBar( 95 | key: header, 96 | backgroundColor: const Color(0xff1B1B1B), 97 | border: const Border( 98 | bottom: const BorderSide( 99 | color: Colors.black, 100 | width: 0.0, 101 | style: BorderStyle.solid, 102 | ), 103 | ), 104 | middle: const Text( 105 | "Peek & Pop", 106 | style: const TextStyle(color: const Color(0xffFF9500)), 107 | ), 108 | leading: CupertinoButton( 109 | padding: EdgeInsets.only(bottom: 2), 110 | onPressed: () { 111 | HapticFeedback.mediumImpact(); 112 | _peekAndPopController.closePeekAndPop(); 113 | }, 114 | child: const Icon( 115 | CupertinoIcons.left_chevron, 116 | size: 25, 117 | color: const Color(0xffFF9500), 118 | ), 119 | ), 120 | trailing: CupertinoButton( 121 | padding: EdgeInsets.only(bottom: 2), 122 | onPressed: () { 123 | HapticFeedback.mediumImpact(); 124 | showSnackbar(); 125 | }, 126 | child: const Icon( 127 | CupertinoIcons.heart_solid, 128 | size: 25, 129 | color: const Color(0xffFF9500), 130 | ), 131 | ), 132 | transitionBetweenRoutes: false, 133 | ); 134 | } 135 | 136 | Widget atPopWrapper(Widget child, PeekAndPopControllerState _peekAndPopController) { 137 | return Scaffold( 138 | key: scaffold, 139 | appBar: appBar(_peekAndPopController), 140 | body: SizedBox.expand(child: child), 141 | ); 142 | } 143 | 144 | Widget normalRow(String text, Color color) { 145 | return Container( 146 | constraints: BoxConstraints.expand(), 147 | decoration: BoxDecoration( 148 | color: color, 149 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 150 | ), 151 | child: Center( 152 | child: Text( 153 | text, 154 | style: const TextStyle( 155 | color: Colors.white, 156 | fontWeight: FontWeight.bold, 157 | fontSize: 25, 158 | ), 159 | textAlign: TextAlign.center, 160 | ), 161 | ), 162 | ); 163 | } 164 | 165 | Widget specialRow(String text, Color color) { 166 | return Container( 167 | constraints: BoxConstraints.expand(), 168 | decoration: BoxDecoration( 169 | color: color, 170 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 171 | ), 172 | child: Center( 173 | child: Padding( 174 | padding: EdgeInsets.all(25), 175 | child: Hero( 176 | tag: "Hero", 177 | child: Image.asset( 178 | "assets/Hero.png", 179 | fit: BoxFit.contain, 180 | key: Key("Image"), 181 | ), 182 | ), 183 | ), 184 | ), 185 | ); 186 | } 187 | 188 | Widget normalPeekAndPopBuilderAtPeek(BuildContext context, PeekAndPopControllerState _peekAndPopController) { 189 | return atPeekWrapper( 190 | Image.asset( 191 | "assets/Scenery.jpeg", 192 | fit: BoxFit.contain, 193 | key: Key("Image"), 194 | ), 195 | _peekAndPopController, 196 | ); 197 | } 198 | 199 | Widget normalPeekAndPopBuilderAtPop(BuildContext context, PeekAndPopControllerState _peekAndPopController) { 200 | return atPopWrapper( 201 | Transform.translate( 202 | offset: Offset(0, -50), 203 | child: Image.asset( 204 | "assets/Scenery.jpeg", 205 | fit: BoxFit.contain, 206 | key: Key("Image"), 207 | ), 208 | ), 209 | _peekAndPopController, 210 | ); 211 | } 212 | 213 | Widget platformViewPeekAndPopBuilder(BuildContext context, PeekAndPopControllerState _peekAndPopController) { 214 | return Container( 215 | decoration: BoxDecoration( 216 | borderRadius: (_peekAndPopController.willBeDone || _peekAndPopController.isDone) ? null : const BorderRadius.all(const Radius.circular(10.0)), 217 | boxShadow: (_peekAndPopController.willBeDone || _peekAndPopController.isDone) 218 | ? null 219 | : [ 220 | const BoxShadow( 221 | color: Colors.black, 222 | offset: const Offset(0, 15), 223 | spreadRadius: -5, 224 | blurRadius: 20, 225 | ), 226 | ], 227 | ), 228 | child: ClipRRect( 229 | borderRadius: BorderRadius.all((_peekAndPopController.willBeDone || _peekAndPopController.isDone) ? const Radius.circular(0.0) : const Radius.circular(10.0)), 230 | child: Scaffold( 231 | key: scaffold, 232 | appBar: (_peekAndPopController.willBeDone || _peekAndPopController.isDone) ? appBar(_peekAndPopController) : null, 233 | body: SizedBox.expand( 234 | child: (peekAndPopController.stage == Stage.IsPeeking || _peekAndPopController.willBeDone || peekAndPopController.isDone) && DateTime.now().difference(_peekAndPopController.pushTime).inSeconds > 1 ? InAppBrowser("https://flutter.dev") : peekAndPopController.stage == Stage.WillCancel || peekAndPopController.stage == Stage.IsCancelled ? Container() : const Center(child: const CupertinoActivityIndicator()), 235 | ), 236 | ), 237 | ), 238 | ); 239 | } 240 | 241 | Widget specialPeekAndPopBuilder(BuildContext context, PeekAndPopControllerState _peekAndPopController) { 242 | if (_peekAndPopController.willBeDone || _peekAndPopController.isDone) 243 | return atPopWrapper( 244 | Transform.translate( 245 | offset: Offset(0, -50), 246 | child: Hero( 247 | tag: "Hero", 248 | child: Image.asset( 249 | "assets/Hero.png", 250 | fit: BoxFit.contain, 251 | key: Key("Image"), 252 | ), 253 | ), 254 | ), 255 | _peekAndPopController, 256 | ); 257 | else 258 | return Image.asset( 259 | "assets/Hero.png", 260 | fit: BoxFit.contain, 261 | key: Key("Image"), 262 | ); 263 | } 264 | 265 | Widget gridPeekAndPopBuilderAtPeek(int index, BuildContext context, PeekAndPopControllerState _peekAndPopController) { 266 | return atPeekWrapper( 267 | Image.asset( 268 | "assets/" + index.toString() + ".jpeg", 269 | fit: BoxFit.contain, 270 | key: Key("Image"), 271 | ), 272 | _peekAndPopController, 273 | ); 274 | } 275 | 276 | Widget gridPeekAndPopBuilderAtPop(int index, BuildContext context, PeekAndPopControllerState _peekAndPopController) { 277 | return atPopWrapper( 278 | Transform.translate( 279 | offset: Offset(0, -50), 280 | child: Image.asset( 281 | "assets/" + index.toString() + ".jpeg", 282 | fit: BoxFit.contain, 283 | key: Key("Image"), 284 | ), 285 | ), 286 | _peekAndPopController, 287 | ); 288 | } 289 | 290 | QuickActionsData moveableQuickActionsBuilder(PeekAndPopControllerState _peekAndPopController) { 291 | return QuickActionsData( 292 | const EdgeInsets.only(left: 12.5, top: 25, right: 12.5, bottom: 25), 293 | const BorderRadius.all(const Radius.circular(10.0)), 294 | [ 295 | QuickAction( 296 | 60, 297 | () { 298 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 299 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 300 | _peekAndPopController.finishPeekAndPop(null); 301 | }); 302 | }, 303 | const BoxDecoration( 304 | color: CupertinoColors.white, 305 | border: const Border( 306 | bottom: const BorderSide( 307 | color: CupertinoColors.inactiveGray, 308 | width: 0.0, 309 | style: BorderStyle.solid, 310 | ), 311 | ), 312 | ), 313 | const Center( 314 | child: const Text( 315 | "Pop", 316 | style: const TextStyle( 317 | color: CupertinoColors.activeBlue, 318 | fontWeight: FontWeight.normal, 319 | fontSize: 20, 320 | ), 321 | textAlign: TextAlign.center, 322 | ), 323 | ), 324 | ), 325 | QuickAction( 326 | 60, 327 | () {}, 328 | const BoxDecoration( 329 | color: CupertinoColors.white, 330 | border: const Border( 331 | bottom: const BorderSide( 332 | color: CupertinoColors.inactiveGray, 333 | width: 0.0, 334 | style: BorderStyle.solid, 335 | ), 336 | ), 337 | ), 338 | const Center( 339 | child: const Text( 340 | "Do Nothing", 341 | style: const TextStyle( 342 | color: CupertinoColors.activeBlue, 343 | fontWeight: FontWeight.normal, 344 | fontSize: 20, 345 | ), 346 | textAlign: TextAlign.center, 347 | ), 348 | ), 349 | ), 350 | QuickAction( 351 | 60, 352 | () { 353 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 354 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 355 | _peekAndPopController.cancelPeekAndPop(null); 356 | }); 357 | }, 358 | const BoxDecoration( 359 | color: CupertinoColors.white, 360 | border: const Border( 361 | top: const BorderSide( 362 | color: CupertinoColors.inactiveGray, 363 | width: 0.0, 364 | style: BorderStyle.solid, 365 | ), 366 | ), 367 | ), 368 | const Center( 369 | child: const Text( 370 | "Dismiss", 371 | style: const TextStyle( 372 | color: CupertinoColors.destructiveRed, 373 | fontWeight: FontWeight.normal, 374 | fontSize: 20, 375 | ), 376 | textAlign: TextAlign.center, 377 | ), 378 | ), 379 | ), 380 | ], 381 | ); 382 | } 383 | 384 | QuickActionsData gridQuickActionsBuilder(PeekAndPopControllerState _peekAndPopController) { 385 | return QuickActionsData( 386 | const EdgeInsets.only(left: 12.5, top: 25, right: 12.5, bottom: 25), 387 | const BorderRadius.all(const Radius.circular(10.0)), 388 | [ 389 | QuickAction( 390 | 60, 391 | () { 392 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 393 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 394 | _peekAndPopController.finishPeekAndPop(null); 395 | }); 396 | }, 397 | const BoxDecoration( 398 | color: CupertinoColors.white, 399 | border: const Border( 400 | bottom: const BorderSide( 401 | color: CupertinoColors.inactiveGray, 402 | width: 0.0, 403 | style: BorderStyle.solid, 404 | ), 405 | ), 406 | ), 407 | const Center( 408 | child: const Text( 409 | "Pop", 410 | style: const TextStyle( 411 | color: CupertinoColors.activeBlue, 412 | fontWeight: FontWeight.normal, 413 | fontSize: 20, 414 | ), 415 | textAlign: TextAlign.center, 416 | ), 417 | ), 418 | ), 419 | QuickAction( 420 | 60, 421 | () {}, 422 | const BoxDecoration( 423 | color: CupertinoColors.white, 424 | border: const Border( 425 | bottom: const BorderSide( 426 | color: CupertinoColors.inactiveGray, 427 | width: 0.0, 428 | style: BorderStyle.solid, 429 | ), 430 | ), 431 | ), 432 | const Center( 433 | child: const Text( 434 | "Save", 435 | style: const TextStyle( 436 | color: CupertinoColors.activeBlue, 437 | fontWeight: FontWeight.normal, 438 | fontSize: 20, 439 | ), 440 | textAlign: TextAlign.center, 441 | ), 442 | ), 443 | ), 444 | QuickAction( 445 | 60, 446 | () {}, 447 | const BoxDecoration( 448 | color: CupertinoColors.white, 449 | border: const Border( 450 | bottom: const BorderSide( 451 | color: CupertinoColors.inactiveGray, 452 | width: 0.0, 453 | style: BorderStyle.solid, 454 | ), 455 | ), 456 | ), 457 | const Center( 458 | child: const Text( 459 | "Share", 460 | style: const TextStyle( 461 | color: CupertinoColors.activeBlue, 462 | fontWeight: FontWeight.normal, 463 | fontSize: 20, 464 | ), 465 | textAlign: TextAlign.center, 466 | ), 467 | ), 468 | ), 469 | QuickAction( 470 | 60, 471 | () { 472 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 473 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 474 | _peekAndPopController.cancelPeekAndPop(null); 475 | }); 476 | }, 477 | const BoxDecoration( 478 | color: CupertinoColors.white, 479 | border: const Border( 480 | top: const BorderSide( 481 | color: CupertinoColors.inactiveGray, 482 | width: 0.0, 483 | style: BorderStyle.solid, 484 | ), 485 | ), 486 | ), 487 | const Center( 488 | child: const Text( 489 | "Dismiss", 490 | style: const TextStyle( 491 | color: CupertinoColors.destructiveRed, 492 | fontWeight: FontWeight.normal, 493 | fontSize: 20, 494 | ), 495 | textAlign: TextAlign.center, 496 | ), 497 | ), 498 | ), 499 | ], 500 | ); 501 | } 502 | 503 | @override 504 | Widget build(BuildContext context) { 505 | return Scaffold( 506 | appBar: AppBar(title: Text(widget.title)), 507 | body: PeekAndPopMisc.scaleDownWrapper( 508 | PageView( 509 | children: [ 510 | Column( 511 | mainAxisAlignment: MainAxisAlignment.center, 512 | children: [ 513 | Expanded( 514 | child: paddingWrapper( 515 | PeekAndPopController( 516 | normalRow( 517 | "Normal with Overlap & without Alignment", 518 | Colors.redAccent, 519 | ), 520 | true, 521 | peekAndPopBuilderAtPeek: normalPeekAndPopBuilderAtPeek, 522 | peekAndPopBuilderAtPop: normalPeekAndPopBuilderAtPop, 523 | sigma: 10, 524 | backdropColor: Colors.white, 525 | useOverlap: true, 526 | useAlignment: false, 527 | indicatorScaleUpCoefficient: 0.01, 528 | onPushPeekAndPop: onPushPeekAndPop, 529 | peekScale: 0.95, 530 | peekCoefficient: 0.025, 531 | ), 532 | ), 533 | ), 534 | Expanded( 535 | child: paddingWrapper( 536 | PeekAndPopController( 537 | normalRow( 538 | "Moveable with Alignment & without Overlap", 539 | Colors.deepPurpleAccent, 540 | ), 541 | true, 542 | peekAndPopBuilderAtPeek: normalPeekAndPopBuilderAtPeek, 543 | peekAndPopBuilderAtPop: normalPeekAndPopBuilderAtPop, 544 | quickActionsBuilder: moveableQuickActionsBuilder, 545 | sigma: 10, 546 | backdropColor: Colors.white, 547 | useOverlap: false, 548 | useAlignment: true, 549 | indicatorScaleUpCoefficient: 0.01, 550 | onPushPeekAndPop: onPushPeekAndPop, 551 | peekScale: 0.95, 552 | peekCoefficient: 0.025, 553 | ), 554 | ), 555 | ), 556 | Expanded( 557 | child: paddingWrapper( 558 | PeekAndPopController( 559 | normalRow( 560 | "Platform View with Custom Overlap Rect", 561 | Colors.cyan, 562 | ), 563 | true, 564 | peekAndPopBuilder: platformViewPeekAndPopBuilder, 565 | peekAndPopBuilderUseCache: false, 566 | sigma: 10, 567 | backdropColor: Colors.white, 568 | useOverlap: true, 569 | customOverlapRect: Rect.fromLTRB( 570 | MediaQuery.of(context).size.width * 0.25, 571 | MediaQuery.of(context).size.height * 0.25, 572 | MediaQuery.of(context).size.width * 0.25, 573 | MediaQuery.of(context).size.height * 0.25, 574 | ), 575 | useAlignment: true, 576 | indicatorScaleUpCoefficient: 0.01, 577 | onPushPeekAndPop: onPushPeekAndPop, 578 | peekScale: 0.75, 579 | peekCoefficient: 0.025, 580 | ), 581 | ), 582 | ), 583 | Expanded( 584 | child: paddingWrapper( 585 | PeekAndPopController( 586 | specialRow( 587 | "Hero with Overlap & without Alignment", 588 | Colors.greenAccent, 589 | ), 590 | true, 591 | peekAndPopBuilder: specialPeekAndPopBuilder, 592 | peekAndPopBuilderUseCache: false, 593 | sigma: 10, 594 | backdropColor: Colors.white, 595 | useOverlap: true, 596 | useAlignment: false, 597 | indicatorScaleUpCoefficient: 0.01, 598 | onPushPeekAndPop: onPushPeekAndPop, 599 | peekScale: 0.95, 600 | peekCoefficient: 0.025, 601 | ), 602 | ), 603 | ), 604 | ], 605 | ), 606 | GridView.count( 607 | padding: EdgeInsets.all(25), 608 | mainAxisSpacing: 10.0, 609 | crossAxisSpacing: 10.0, 610 | crossAxisCount: 3, 611 | children: List.generate(30, (int index) { 612 | return PeekAndPopController( 613 | Container( 614 | decoration: BoxDecoration( 615 | image: DecorationImage( 616 | image: AssetImage( 617 | "assets/" + index.toString() + ".jpeg", 618 | ), 619 | fit: BoxFit.cover, 620 | ), 621 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 622 | ), 623 | ), 624 | true, 625 | peekAndPopBuilderAtPeek: (BuildContext context, PeekAndPopControllerState _peekAndPopController) => gridPeekAndPopBuilderAtPeek(index, context, _peekAndPopController), 626 | peekAndPopBuilderAtPop: (BuildContext context, PeekAndPopControllerState _peekAndPopController) => gridPeekAndPopBuilderAtPop(index, context, _peekAndPopController), 627 | quickActionsBuilder: gridQuickActionsBuilder, 628 | sigma: 10, 629 | backdropColor: Colors.white, 630 | useOverlap: true, 631 | useAlignment: false, 632 | indicatorScaleUpCoefficient: 0.01, 633 | onPushPeekAndPop: onPushPeekAndPop, 634 | peekScale: 0.95, 635 | peekCoefficient: 0.025, 636 | ); 637 | }), 638 | ), 639 | ], 640 | ), 641 | 0.04, 642 | ), 643 | ); 644 | } 645 | } 646 | 647 | class InAppBrowser extends StatefulWidget { 648 | final String url; 649 | 650 | const InAppBrowser( 651 | this.url, 652 | ); 653 | 654 | @override 655 | InAppBrowserState createState() { 656 | return InAppBrowserState(url); 657 | } 658 | } 659 | 660 | class InAppBrowserState extends State { 661 | final String url; 662 | 663 | InAppBrowserState( 664 | this.url, 665 | ); 666 | 667 | @override 668 | Widget build(BuildContext context) { 669 | return WebView( 670 | initialUrl: url, 671 | javascriptMode: JavascriptMode.unrestricted, 672 | navigationDelegate: (NavigationRequest request) => NavigationDecision.navigate, 673 | onPageFinished: (String url) {}, 674 | ); 675 | } 676 | } 677 | -------------------------------------------------------------------------------- /peek_and_pop/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/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.5.0-nullsafety" 11 | bloc: 12 | dependency: transitive 13 | description: 14 | name: bloc 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "6.0.3" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0-nullsafety" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.1.0-nullsafety.2" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.2.0-nullsafety" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0-nullsafety" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.15.0-nullsafety.2" 53 | cupertino_icons: 54 | dependency: "direct main" 55 | description: 56 | name: cupertino_icons 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "0.1.2" 60 | fake_async: 61 | dependency: transitive 62 | description: 63 | name: fake_async 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.1.0-nullsafety" 67 | flick: 68 | dependency: transitive 69 | description: 70 | name: flick 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.0.3" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_test: 80 | dependency: "direct dev" 81 | description: flutter 82 | source: sdk 83 | version: "0.0.0" 84 | matcher: 85 | dependency: transitive 86 | description: 87 | name: matcher 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "0.12.10-nullsafety" 91 | meta: 92 | dependency: transitive 93 | description: 94 | name: meta 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.3.0-nullsafety.2" 98 | path: 99 | dependency: transitive 100 | description: 101 | name: path 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.8.0-nullsafety" 105 | peek_and_pop: 106 | dependency: "direct main" 107 | description: 108 | path: ".." 109 | relative: true 110 | source: path 111 | version: "1.0.3" 112 | sky_engine: 113 | dependency: transitive 114 | description: flutter 115 | source: sdk 116 | version: "0.0.99" 117 | snap: 118 | dependency: transitive 119 | description: 120 | name: snap 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.0.5" 124 | source_span: 125 | dependency: transitive 126 | description: 127 | name: source_span 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.8.0-nullsafety" 131 | stack_trace: 132 | dependency: transitive 133 | description: 134 | name: stack_trace 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.10.0-nullsafety" 138 | stream_channel: 139 | dependency: transitive 140 | description: 141 | name: stream_channel 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.1.0-nullsafety" 145 | string_scanner: 146 | dependency: transitive 147 | description: 148 | name: string_scanner 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.1.0-nullsafety" 152 | term_glyph: 153 | dependency: transitive 154 | description: 155 | name: term_glyph 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.2.0-nullsafety" 159 | test_api: 160 | dependency: transitive 161 | description: 162 | name: test_api 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "0.2.19-nullsafety" 166 | transparent_image: 167 | dependency: transitive 168 | description: 169 | name: transparent_image 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.0.0" 173 | typed_data: 174 | dependency: transitive 175 | description: 176 | name: typed_data 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.3.0-nullsafety.2" 180 | vector_math: 181 | dependency: transitive 182 | description: 183 | name: vector_math 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.1.0-nullsafety.2" 187 | webview_flutter: 188 | dependency: "direct main" 189 | description: 190 | name: webview_flutter 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "0.3.13" 194 | sdks: 195 | dart: ">=2.10.0-0.0.dev <2.10.0" 196 | flutter: ">=1.5.0 <2.0.0" 197 | -------------------------------------------------------------------------------- /peek_and_pop/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name : example 2 | description : Example Project for peek_and_pop. 3 | version : 1.0.3 4 | author : Ali Yigit Bireroglu 5 | repository : https://github.com/aliyigitbireroglu/flutter-peek-and-pop 6 | homepage : https://www.cosmossoftware.coffee 7 | 8 | environment : 9 | sdk: ">=2.1.0 <3.0.0" 10 | 11 | dependencies : 12 | flutter : 13 | sdk: flutter 14 | peek_and_pop : 15 | path: ../ 16 | cupertino_icons: ^0.1.2 17 | webview_flutter: ^0.3.13 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter : 24 | uses-material-design: true 25 | 26 | assets : 27 | - assets/ 28 | -------------------------------------------------------------------------------- /peek_and_pop/example/test/example_test.dart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/example/test/example_test.dart -------------------------------------------------------------------------------- /peek_and_pop/lib/Export.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | export 'peek_and_pop_controller.dart'; 11 | export 'peek_and_pop_detector.dart'; 12 | export 'peek_and_pop_child.dart'; 13 | export 'misc.dart'; 14 | -------------------------------------------------------------------------------- /peek_and_pop/lib/animated_cross_fade.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'package:flutter/rendering.dart'; 6 | 7 | import 'package:flutter/widgets.dart'; 8 | 9 | // Examples can assume: 10 | // bool _first; 11 | 12 | /// Specifies which of two children to show. See [AnimatedCrossFade]. 13 | /// 14 | /// The child that is shown will fade in, while the other will fade out. 15 | enum CrossFadeState { 16 | /// Show the first child ([AnimatedCrossFade.firstChild]) and hide the second 17 | /// ([AnimatedCrossFade.secondChild]]). 18 | showFirst, 19 | 20 | /// Show the second child ([AnimatedCrossFade.secondChild]) and hide the first 21 | /// ([AnimatedCrossFade.firstChild]). 22 | showSecond, 23 | } 24 | 25 | /// Signature for the [AnimatedCrossFade.layoutBuilder] callback. 26 | /// 27 | /// The `topChild` is the child fading in, which is normally drawn on top. The 28 | /// `bottomChild` is the child fading out, normally drawn on the bottom. 29 | /// 30 | /// For good performance, the returned widget tree should contain both the 31 | /// `topChild` and the `bottomChild`; the depth of the tree, and the types of 32 | /// the widgets in the tree, from the returned widget to each of the children 33 | /// should be the same; and where there is a widget with multiple children, the 34 | /// top child and the bottom child should be keyed using the provided 35 | /// `topChildKey` and `bottomChildKey` keys respectively. 36 | /// 37 | /// {@tool sample} 38 | /// 39 | /// ```dart 40 | /// Widget defaultLayoutBuilder(Widget topChild, Key topChildKey, Widget bottomChild, Key bottomChildKey) { 41 | /// return Stack( 42 | /// fit: StackFit.loose, 43 | /// children: [ 44 | /// Positioned( 45 | /// key: bottomChildKey, 46 | /// left: 0.0, 47 | /// top: 0.0, 48 | /// right: 0.0, 49 | /// child: bottomChild, 50 | /// ), 51 | /// Positioned( 52 | /// key: topChildKey, 53 | /// child: topChild, 54 | /// ) 55 | /// ], 56 | /// ); 57 | /// } 58 | /// ``` 59 | /// {@end-tool} 60 | typedef AnimatedCrossFadeBuilder = Widget Function(Widget topChild, Key topChildKey, Widget bottomChild, Key bottomChildKey); 61 | 62 | /// A widget that cross-fades between two given children and animates itself 63 | /// between their sizes. 64 | /// 65 | /// The animation is controlled through the [crossFadeState] parameter. 66 | /// [firstCurve] and [secondCurve] represent the opacity curves of the two 67 | /// children. The [firstCurve] is inverted, i.e. it fades out when providing a 68 | /// growing curve like [Curves.linear]. The [sizeCurve] is the curve used to 69 | /// animate between the size of the fading-out child and the size of the 70 | /// fading-in child. 71 | /// 72 | /// This widget is intended to be used to fade a pair of widgets with the same 73 | /// width. In the case where the two children have different heights, the 74 | /// animation crops overflowing children during the animation by aligning their 75 | /// top edge, which means that the bottom will be clipped. 76 | /// 77 | /// The animation is automatically triggered when an existing 78 | /// [AnimatedCrossFade] is rebuilt with a different value for the 79 | /// [crossFadeState] property. 80 | /// 81 | /// {@tool sample} 82 | /// 83 | /// This code fades between two representations of the Flutter logo. It depends 84 | /// on a boolean field `_first`; when `_first` is true, the first logo is shown, 85 | /// otherwise the second logo is shown. When the field changes state, the 86 | /// [AnimatedCrossFade] widget cross-fades between the two forms of the logo 87 | /// over three seconds. 88 | /// 89 | /// ```dart 90 | /// AnimatedCrossFade( 91 | /// duration: const Duration(seconds: 3), 92 | /// firstChild: const FlutterLogo(style: FlutterLogoStyle.horizontal, size: 100.0), 93 | /// secondChild: const FlutterLogo(style: FlutterLogoStyle.stacked, size: 100.0), 94 | /// crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond, 95 | /// ) 96 | /// ``` 97 | /// {@end-tool} 98 | /// 99 | /// See also: 100 | /// 101 | /// * [AnimatedSize], the lower-level widget which [AnimatedCrossFade] uses to 102 | /// automatically change size. 103 | /// * [AnimatedSwitcher], which switches out a child for a new one with a 104 | /// customizable transition. 105 | class AnimatedCrossFade extends StatefulWidget { 106 | /// Creates a cross-fade animation widget. 107 | /// 108 | /// The [duration] of the animation is the same for all components (fade in, 109 | /// fade out, and size), and you can pass [Interval]s instead of [Curve]s in 110 | /// order to have finer control, e.g., creating an overlap between the fades. 111 | /// 112 | /// All the arguments other than [key] must be non-null. 113 | const AnimatedCrossFade({ 114 | Key key, 115 | @required this.firstChild, 116 | @required this.secondChild, 117 | this.firstCurve = Curves.linear, 118 | this.secondCurve = Curves.linear, 119 | this.sizeCurve = Curves.linear, 120 | this.alignment = Alignment.topCenter, 121 | @required this.crossFadeState, 122 | @required this.duration, 123 | this.reverseDuration, 124 | this.layoutBuilder = defaultLayoutBuilder, 125 | }) : assert(firstChild != null), 126 | assert(secondChild != null), 127 | assert(firstCurve != null), 128 | assert(secondCurve != null), 129 | assert(sizeCurve != null), 130 | assert(alignment != null), 131 | assert(crossFadeState != null), 132 | assert(duration != null), 133 | assert(layoutBuilder != null), 134 | super(key: key); 135 | 136 | /// The child that is visible when [crossFadeState] is 137 | /// [CrossFadeState.showFirst]. It fades out when transitioning 138 | /// [crossFadeState] from [CrossFadeState.showFirst] to 139 | /// [CrossFadeState.showSecond] and vice versa. 140 | final Widget firstChild; 141 | 142 | /// The child that is visible when [crossFadeState] is 143 | /// [CrossFadeState.showSecond]. It fades in when transitioning 144 | /// [crossFadeState] from [CrossFadeState.showFirst] to 145 | /// [CrossFadeState.showSecond] and vice versa. 146 | final Widget secondChild; 147 | 148 | /// The child that will be shown when the animation has completed. 149 | final CrossFadeState crossFadeState; 150 | 151 | /// The duration of the whole orchestrated animation. 152 | final Duration duration; 153 | 154 | /// The duration of the whole orchestrated animation when running in reverse. 155 | /// 156 | /// If not supplied, this defaults to [duration]. 157 | final Duration reverseDuration; 158 | 159 | /// The fade curve of the first child. 160 | /// 161 | /// Defaults to [Curves.linear]. 162 | final Curve firstCurve; 163 | 164 | /// The fade curve of the second child. 165 | /// 166 | /// Defaults to [Curves.linear]. 167 | final Curve secondCurve; 168 | 169 | /// The curve of the animation between the two children's sizes. 170 | /// 171 | /// Defaults to [Curves.linear]. 172 | final Curve sizeCurve; 173 | 174 | /// How the children should be aligned while the size is animating. 175 | /// 176 | /// Defaults to [Alignment.topCenter]. 177 | /// 178 | /// See also: 179 | /// 180 | /// * [Alignment], a class with convenient constants typically used to 181 | /// specify an [AlignmentGeometry]. 182 | /// * [AlignmentDirectional], like [Alignment] for specifying alignments 183 | /// relative to text direction. 184 | final AlignmentGeometry alignment; 185 | 186 | /// A builder that positions the [firstChild] and [secondChild] widgets. 187 | /// 188 | /// The widget returned by this method is wrapped in an [AnimatedSize]. 189 | /// 190 | /// By default, this uses [AnimatedCrossFade.defaultLayoutBuilder], which uses 191 | /// a [Stack] and aligns the `bottomChild` to the top of the stack while 192 | /// providing the `topChild` as the non-positioned child to fill the provided 193 | /// constraints. This works well when the [AnimatedCrossFade] is in a position 194 | /// to change size and when the children are not flexible. However, if the 195 | /// children are less fussy about their sizes (for example a 196 | /// [CircularProgressIndicator] inside a [Center]), or if the 197 | /// [AnimatedCrossFade] is being forced to a particular size, then it can 198 | /// result in the widgets jumping about when the cross-fade state is changed. 199 | final AnimatedCrossFadeBuilder layoutBuilder; 200 | 201 | /// The default layout algorithm used by [AnimatedCrossFade]. 202 | /// 203 | /// The top child is placed in a stack that sizes itself to match the top 204 | /// child. The bottom child is positioned at the top of the same stack, sized 205 | /// to fit its width but without forcing the height. The stack is then 206 | /// clipped. 207 | /// 208 | /// This is the default value for [layoutBuilder]. It implements 209 | /// [AnimatedCrossFadeBuilder]. 210 | static Widget defaultLayoutBuilder(Widget topChild, Key topChildKey, Widget bottomChild, Key bottomChildKey) { 211 | return Stack( 212 | overflow: Overflow.visible, 213 | children: [ 214 | Positioned( 215 | key: bottomChildKey, 216 | left: 0.0, 217 | top: 0.0, 218 | right: 0.0, 219 | child: bottomChild, 220 | ), 221 | Positioned( 222 | key: topChildKey, 223 | child: topChild, 224 | ), 225 | ], 226 | ); 227 | } 228 | 229 | @override 230 | _AnimatedCrossFadeState createState() => _AnimatedCrossFadeState(); 231 | 232 | @override 233 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { 234 | super.debugFillProperties(properties); 235 | properties.add(EnumProperty('crossFadeState', crossFadeState)); 236 | properties.add(DiagnosticsProperty('alignment', alignment, defaultValue: Alignment.topCenter)); 237 | properties.add(IntProperty('duration', duration.inMilliseconds, unit: 'ms')); 238 | properties.add(IntProperty('reverseDuration', reverseDuration?.inMilliseconds, unit: 'ms', defaultValue: null)); 239 | } 240 | } 241 | 242 | class _AnimatedCrossFadeState extends State with TickerProviderStateMixin { 243 | AnimationController _controller; 244 | Animation _firstAnimation; 245 | Animation _secondAnimation; 246 | 247 | @override 248 | void initState() { 249 | super.initState(); 250 | _controller = AnimationController( 251 | duration: widget.duration, 252 | reverseDuration: widget.reverseDuration, 253 | vsync: this, 254 | ); 255 | if (widget.crossFadeState == CrossFadeState.showSecond) _controller.value = 1.0; 256 | _firstAnimation = _initAnimation(widget.firstCurve, true); 257 | _secondAnimation = _initAnimation(widget.secondCurve, false); 258 | _controller.addStatusListener((AnimationStatus status) { 259 | setState(() { 260 | // Trigger a rebuild because it depends on _isTransitioning, which 261 | // changes its value together with animation status. 262 | }); 263 | }); 264 | } 265 | 266 | Animation _initAnimation(Curve curve, bool inverted) { 267 | Animation result = _controller.drive(CurveTween(curve: curve)); 268 | if (inverted) result = result.drive(Tween(begin: 1.0, end: 0.0)); 269 | return result; 270 | } 271 | 272 | @override 273 | void dispose() { 274 | _controller.dispose(); 275 | super.dispose(); 276 | } 277 | 278 | @override 279 | void didUpdateWidget(AnimatedCrossFade oldWidget) { 280 | super.didUpdateWidget(oldWidget); 281 | if (widget.duration != oldWidget.duration) _controller.duration = widget.duration; 282 | if (widget.reverseDuration != oldWidget.reverseDuration) _controller.reverseDuration = widget.reverseDuration; 283 | if (widget.firstCurve != oldWidget.firstCurve) _firstAnimation = _initAnimation(widget.firstCurve, true); 284 | if (widget.secondCurve != oldWidget.secondCurve) _secondAnimation = _initAnimation(widget.secondCurve, false); 285 | if (widget.crossFadeState != oldWidget.crossFadeState) { 286 | switch (widget.crossFadeState) { 287 | case CrossFadeState.showFirst: 288 | _controller.reverse(); 289 | break; 290 | case CrossFadeState.showSecond: 291 | _controller.forward(); 292 | break; 293 | } 294 | } 295 | } 296 | 297 | /// Whether we're in the middle of cross-fading this frame. 298 | bool get _isTransitioning => _controller.status == AnimationStatus.forward || _controller.status == AnimationStatus.reverse; 299 | 300 | @override 301 | Widget build(BuildContext context) { 302 | const Key kFirstChildKey = ValueKey(CrossFadeState.showFirst); 303 | const Key kSecondChildKey = ValueKey(CrossFadeState.showSecond); 304 | final bool transitioningForwards = _controller.status == AnimationStatus.completed || _controller.status == AnimationStatus.forward; 305 | Key topKey; 306 | Widget topChild; 307 | Animation topAnimation; 308 | Key bottomKey; 309 | Widget bottomChild; 310 | Animation bottomAnimation; 311 | if (transitioningForwards) { 312 | topKey = kSecondChildKey; 313 | topChild = widget.secondChild; 314 | topAnimation = _secondAnimation; 315 | bottomKey = kFirstChildKey; 316 | bottomChild = widget.firstChild; 317 | bottomAnimation = _firstAnimation; 318 | } else { 319 | topKey = kFirstChildKey; 320 | topChild = widget.firstChild; 321 | topAnimation = _firstAnimation; 322 | bottomKey = kSecondChildKey; 323 | bottomChild = widget.secondChild; 324 | bottomAnimation = _secondAnimation; 325 | } 326 | 327 | bottomChild = TickerMode( 328 | key: bottomKey, 329 | enabled: _isTransitioning, 330 | child: ExcludeSemantics( 331 | excluding: true, // Always exclude the semantics of the widget that's fading out. 332 | child: FadeTransition( 333 | opacity: bottomAnimation, 334 | child: bottomChild, 335 | ), 336 | ), 337 | ); 338 | topChild = TickerMode( 339 | key: topKey, enabled: true, // Top widget always has its animations enabled. 340 | child: ExcludeSemantics( 341 | excluding: false, // Always publish semantics for the widget that's fading in. 342 | child: FadeTransition( 343 | opacity: topAnimation, 344 | child: topChild, 345 | ), 346 | ), 347 | ); 348 | return AnimatedSize( 349 | alignment: widget.alignment, 350 | duration: widget.duration, 351 | reverseDuration: widget.reverseDuration, 352 | curve: widget.sizeCurve, 353 | vsync: this, 354 | child: widget.layoutBuilder(topChild, topKey, bottomChild, bottomKey), 355 | ); 356 | } 357 | 358 | @override 359 | void debugFillProperties(DiagnosticPropertiesBuilder description) { 360 | super.debugFillProperties(description); 361 | description.add(EnumProperty('crossFadeState', widget.crossFadeState)); 362 | description.add(DiagnosticsProperty('controller', _controller, showName: false)); 363 | description.add(DiagnosticsProperty('alignment', widget.alignment, defaultValue: Alignment.topCenter)); 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /peek_and_pop/lib/misc.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | import 'package:flutter/widgets.dart'; 11 | 12 | import 'package:bloc/bloc.dart'; 13 | 14 | import 'Export.dart'; 15 | 16 | typedef PeekAndPopBuilder = Widget Function(BuildContext context, PeekAndPopControllerState _peekAndPopController); 17 | typedef PeekAndPopProcessNotifier = bool Function(PeekAndPopControllerState _peekAndPopController); 18 | typedef PeekAndPopProcessCallback = void Function(PeekAndPopControllerState _peekAndPopController); 19 | typedef PeekAndPopGestureCallback = void Function(dynamic pressDetails); 20 | typedef QuickActionsBuilder = QuickActionsData Function(PeekAndPopControllerState _peekAndPopController); 21 | 22 | ///See [PeekAndPopControllerState.stage]. 23 | enum Stage { 24 | None, 25 | WillPush, 26 | IsPushed, 27 | WillPeek, 28 | IsPeeking, 29 | WillCancel, 30 | IsCancelled, 31 | WillFinish, 32 | IsFinished, 33 | WillComplete, 34 | IsComplete, 35 | WillClose, 36 | IsClosed, 37 | } 38 | 39 | ///The new optimised blur effect algorithm during the Peek & Pop process requires your root CupertinoApp/MaterialApp to be wrapped in a 40 | ///[RepaintBoundary] widget which uses this key. See README, [PeekAndPopChildState.blurSnapshot] or [PeekAndPopChildState.blurTrackerNotifier] for more 41 | ///info. 42 | final GlobalKey background = GlobalKey(); 43 | 44 | ///See [TransformBloc], [scaleUpWrapper] and [scaleDownWrapper]. 45 | TransformBloc transformBloc = TransformBloc(); 46 | 47 | ///Use this function to scale down a widget as the Peek & Pop process proceeds. 48 | Widget scaleDownWrapper(Widget child, double scaleDownCoefficient) { 49 | return StreamBuilder( 50 | stream: transformBloc, 51 | builder: (BuildContext context, AsyncSnapshot snapshot) { 52 | return Transform.scale( 53 | scale: snapshot.hasData ? (1.0 - (snapshot.data * scaleDownCoefficient)) : 1.0, 54 | child: child, 55 | ); 56 | }, 57 | ); 58 | } 59 | 60 | ///Use this function to scale up a widget as the Peek & Pop process proceeds. 61 | Widget scaleUpWrapper(Widget child, double scaleUpCoefficient) { 62 | return StreamBuilder( 63 | stream: transformBloc, 64 | builder: (BuildContext context, AsyncSnapshot snapshot) { 65 | return Transform.scale( 66 | scale: snapshot.hasData ? (1.0 + (snapshot.data * scaleUpCoefficient)) : 1.0, 67 | child: child, 68 | ); 69 | }, 70 | ); 71 | } 72 | 73 | ///A Bloc class for controlling the [scaleDownWrapper] and [scaleUpWrapper]. 74 | class TransformBloc extends Bloc { 75 | 76 | TransformBloc(): super(0.0); 77 | 78 | @override 79 | Stream mapEventToState(double newState) async* { 80 | yield newState; 81 | } 82 | } 83 | 84 | ///A simple class for organising general Quick Actions information. 85 | class QuickActionsData { 86 | final EdgeInsets padding; 87 | final BorderRadius borderRadius; 88 | final List quickActions; 89 | 90 | const QuickActionsData( 91 | this.padding, 92 | this.borderRadius, 93 | this.quickActions, 94 | ); 95 | } 96 | 97 | ///A simple class for organising an individual Quick Action information. 98 | class QuickAction { 99 | final double height; 100 | final Function onTap; 101 | final BoxDecoration boxDecoration; 102 | final Widget child; 103 | 104 | const QuickAction( 105 | this.height, 106 | this.onTap, 107 | this.boxDecoration, 108 | this.child, 109 | ); 110 | } 111 | 112 | class PeekAndPopRoute extends PageRoute { 113 | final PeekAndPopControllerState _peekAndPopController; 114 | 115 | final WidgetBuilder builder; 116 | 117 | final Function pageTransition; 118 | 119 | PeekAndPopRoute( 120 | this._peekAndPopController, 121 | this.builder, 122 | this.pageTransition, 123 | ); 124 | 125 | @override 126 | bool get opaque => false; 127 | 128 | @override 129 | bool get barrierDismissible => true; 130 | 131 | @override 132 | Color get barrierColor => Color.fromARGB(1, 0, 0, 0); 133 | 134 | @override 135 | String get barrierLabel => ""; 136 | 137 | @override 138 | bool get maintainState => true; 139 | 140 | @override 141 | Duration get transitionDuration => const Duration(milliseconds: 333); 142 | 143 | @override 144 | Widget buildTransitions(BuildContext context, Animation animation, Animation secondaryAnimation, Widget child) { 145 | if (!_peekAndPopController.isDirect && !_peekAndPopController.ignoreAnimation && _peekAndPopController.stage != Stage.IsComplete) return child; 146 | if (pageTransition == null) 147 | return SlideTransition( 148 | position: Tween( 149 | begin: const Offset(0.0, 1.0), 150 | end: Offset.zero, 151 | ).animate(animation), 152 | child: child, 153 | ); 154 | return pageTransition( 155 | context, 156 | animation, 157 | secondaryAnimation, 158 | child, 159 | ); 160 | } 161 | 162 | @override 163 | Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { 164 | return builder(context); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /peek_and_pop/lib/peek_and_pop.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | export 'Export.dart'; 11 | -------------------------------------------------------------------------------- /peek_and_pop/lib/peek_and_pop_detector.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | import 'package:flutter/material.dart'; 11 | import 'package:flutter/services.dart'; 12 | 13 | import 'gesture_detector.dart' as MyGestureDetector; 14 | import 'Export.dart'; 15 | 16 | ///The widget that is responsible of detecting Peek & Pop related gestures until the gesture recognition is rerouted to the instantiated 17 | ///[PeekAndPopChild]. It is automatically created by the [PeekAndPopController]. It uses [MyGestureDetector.GestureDetector] for reasons 18 | ///explained at [PeekAndPopController.startPressure] and [PeekAndPopController.peakPressure] 19 | class PeekAndPopDetector extends StatelessWidget { 20 | final PeekAndPopControllerState _peekAndPopController; 21 | 22 | final Widget child; 23 | 24 | const PeekAndPopDetector( 25 | this._peekAndPopController, 26 | this.child, 27 | ); 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return ValueListenableBuilder( 32 | child: _peekAndPopController.uiChildUseCache ? child : null, 33 | builder: (BuildContext context, int pressRerouted, Widget cachedChild) { 34 | return IgnorePointer( 35 | ignoring: pressRerouted != 0, 36 | child: MyGestureDetector.GestureDetector( 37 | startPressure: _peekAndPopController.startPressure, 38 | peakPressure: _peekAndPopController.peakPressure, 39 | onTap: () { 40 | HapticFeedback.mediumImpact(); 41 | _peekAndPopController.peekAndPopComplete(); 42 | }, 43 | onForcePressStart: (ForcePressDetails forcePressDetails) { 44 | _peekAndPopController.pushPeekAndPop(forcePressDetails); 45 | }, 46 | onForcePressUpdate: (ForcePressDetails forcePressDetails) { 47 | _peekAndPopController.updatePeekAndPop(forcePressDetails); 48 | }, 49 | onForcePressEnd: (ForcePressDetails forcePressDetails) { 50 | _peekAndPopController.cancelPeekAndPop(forcePressDetails); 51 | }, 52 | onForcePressPeak: (ForcePressDetails forcePressDetails) { 53 | _peekAndPopController.finishPeekAndPop(forcePressDetails); 54 | }, 55 | child: _peekAndPopController.uiChildUseCache ? cachedChild : child, 56 | ), 57 | ); 58 | }, 59 | valueListenable: _peekAndPopController.pressReroutedNotifier, 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"webview_flutter","path":"/Users/fabriziotognetto/Library/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter-0.3.13/","dependencies":[]}],"android":[{"name":"webview_flutter","path":"/Users/fabriziotognetto/Library/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter-0.3.13/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"webview_flutter","dependencies":[]}],"date_created":"2020-09-23 23:07:44.981689","version":"1.22.0-12.1.pre"} -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/.gitignore: -------------------------------------------------------------------------------- 1 | /gitignore 2 | /android 3 | /build 4 | /ios 5 | .notes.md 6 | .notes.txt 7 | 8 | # Miscellaneous 9 | *.class 10 | *.log 11 | *.pyc 12 | *.swp 13 | .DS_Store 14 | .atom/ 15 | .buildlog/ 16 | .history 17 | .svn/ 18 | 19 | # IntelliJ related 20 | *.iml 21 | *.ipr 22 | *.iws 23 | .idea/ 24 | 25 | # The .vscode folder contains launch configuration and tasks you configure in 26 | # VS Code which you may wish to be included in version control, so this line 27 | # is commented out by default. 28 | #.vscode/ 29 | 30 | # Flutter/Dart/Pub related 31 | **/doc/api/ 32 | .dart_tool/ 33 | .flutter-plugins 34 | .packages 35 | .pub-cache/ 36 | .pub/ 37 | build/ 38 | 39 | # Android related 40 | **/android/**/gradle-wrapper.jar 41 | **/android/.gradle 42 | **/android/captures/ 43 | **/android/gradlew 44 | **/android/gradlew.bat 45 | **/android/local.properties 46 | **/android/**/GeneratedPluginRegistrant.java 47 | 48 | # iOS/XCode related 49 | **/ios/**/*.mode1v3 50 | **/ios/**/*.mode2v3 51 | **/ios/**/*.moved-aside 52 | **/ios/**/*.pbxuser 53 | **/ios/**/*.perspectivev3 54 | **/ios/**/*sync/ 55 | **/ios/**/.sconsign.dblite 56 | **/ios/**/.tags* 57 | **/ios/**/.vagrant/ 58 | **/ios/**/DerivedData/ 59 | **/ios/**/Icon? 60 | **/ios/**/Pods/ 61 | **/ios/**/.symlinks/ 62 | **/ios/**/profile 63 | **/ios/**/xcuserdata 64 | **/ios/.generated/ 65 | **/ios/Flutter/App.framework 66 | **/ios/Flutter/Flutter.framework 67 | **/ios/Flutter/Generated.xcconfig 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_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: 7e361d746130ac1c56193cfbae796aa5601762b6 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.3] - 21.11.2019 2 | 3 | * Minor changes. 4 | 5 | ## [1.0.2] - 07.09.2019 6 | 7 | * Two new PeekAndPopBuilders are added to [PeekAndPopController]. Use [PeekAndPopController.peekAndPopBuilderAtPeek] and 8 | [PeekAndPopController.peekAndPopBuilderAtPop] for both convenience and improved performance. 9 | 10 | * Improved performance. 11 | 12 | * [1.0.2+1] Support for latest dependencies. 13 | 14 | ## [1.0.1] - 03.09.2019 15 | 16 | * Minor changes. 17 | 18 | ## [1.0.0] - 30.08.2019 19 | 20 | * The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 21 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 22 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 23 | 24 | * The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 25 | to the actual iOS version. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 26 | 27 | * The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 28 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box. See this [video](https://youtu.be/IQq_ty5mRYU) for examples. 29 | 30 | * "isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 31 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 32 | while "willBeDone" or "isDone" is true. 33 | 34 | * A workaround is implemented to avoid a Flutter Engine bug that was causing trouble with the optimised blur effect algorithm. 35 | 36 | * Improved enumeration for the stage of the Peek & Pop process. 37 | 38 | * Improved performance. 39 | 40 | * Fine tuning. 41 | 42 | * Improved code style. 43 | 44 | * Improved example project. 45 | 46 | * Updated README. 47 | 48 | * Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 49 | the relevant installation instructions. 50 | 51 | ## [0.2.0] - 23.08.2019 52 | 53 | * Improved performance. 54 | 55 | * Minor changes. 56 | 57 | * Improved code style with trailing commas. 58 | 59 | * [0.2.0+1] Minor changes. 60 | 61 | ## [0.1.9] - 20.08.2019 62 | 63 | * Modifications to Flutter's normal "binding.dart" are no longer required! 64 | 65 | * The Long Press version is temporarily removed. It will be added back soon. 66 | 67 | * Code excerpt added to the README. 68 | 69 | * Updated README. 70 | 71 | * [0.1.9+1] Updated README. 72 | 73 | ## [0.1.8] - 18.08.2019 74 | 75 | * Example project adapted to the updated [snap](https://pub.dev/packages/snap). 76 | 77 | * Minor changes. 78 | 79 | * [0.1.8+1] Updated README. 80 | 81 | ## [0.1.7] - 14.08.2019 82 | 83 | * The "Indicator" feature added. See this [video](https://youtu.be/wOWCV7HJzwc) for examples. 84 | 85 | * Improved performance. 86 | 87 | * Fine tuning. 88 | 89 | ## [0.1.6] - 12.08.2019 90 | 91 | * Improved Long Press version (still under development). 92 | 93 | * Fine tuning. 94 | 95 | * Improved documentation. 96 | 97 | * Updated README. 98 | 99 | ## [0.1.5] - 11.08.2019 100 | 101 | * Improved performance. 102 | 103 | * Improved code style. 104 | 105 | ## [0.1.4] - 11.08.2019 106 | 107 | * A minor bug is fixed. 108 | 109 | ## [0.1.3] - 07.08.2019 110 | 111 | * A minor bug in the example project is fixed. 112 | 113 | * Updated README: 114 | 115 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 116 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 117 | 118 | ## [0.1.2] - 07.08.2019 119 | 120 | * [snap](https://pub.dev/packages/snap) is now implemented directly to the example. 121 | 122 | * More callbacks added for better control. 123 | 124 | * Simple enumeration for the stage of the Peek & Pop process added. 125 | 126 | * Improved animations. 127 | 128 | * Improved documentation. 129 | 130 | ## [0.1.1] - 06.08.2019 131 | 132 | * Improved code style. 133 | 134 | ## [0.1.0] - 06.08.2019 135 | 136 | * Improved Long Press version (still under development). 137 | 138 | * Improved documentation. 139 | 140 | ## [0.0.1] - 05.08.2019 141 | 142 | * Initial release. 143 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ali Yigit Bireroglu 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. 22 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Example Project for peek_and_pop. 4 | 5 | Note: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 6 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 7 | 8 | 9 | # peek_and_pop 10 | 11 | [comment]: <> (Badges) 12 | 13 | Cosmos Software 14 | 15 | 16 | Cosmos Software 17 | 18 |
19 | 20 | 21 | Awesome Flutter 22 | 23 |
24 | 25 | [![Pub](https://img.shields.io/pub/v/peek_and_pop?color=g)](https://pub.dev/packages/peek_and_pop) 26 | [![License](https://img.shields.io/github/license/aliyigitbireroglu/flutter-peek-and-pop?color=blue)](https://github.com/aliyigitbireroglu/flutter-peek-and-pop/blob/master/LICENSE) 27 | 28 | [comment]: <> (Introduction) 29 | 30 |

31 | Peek & Pop implementation for Flutter based on the iOS functionality of the same name. 32 | 33 | **Finally, the v1.0.0 release! More fluent, more optimised and more beautiful than ever. Very customisable and very easy to use.** 34 | 35 | **It is highly recommended to read the documentation and run the example project on a real device to fully understand and inspect the full range of 36 | capabilities.** 37 | 38 | [comment]: <> (ToC) 39 | [Media](#media) | [Description](#description) | [Installation](#installation) | [How-to-Use](#howtouse) 40 | 41 | [comment]: <> (Notice) 42 | ## Notice 43 | * **v0.1.9 and higher no longer requires any modifications to Flutter's normal "binding.dart"! You can leave your Flutter source code alone and happy.** 44 | 45 | * **If you are updating from an earlier version, you can revert your "binding.dart" to its original format.** 46 | * * * 47 | [comment]: <> (Recent) 48 | ## Recent 49 | * **The "Quick Actions" feature is now added. It is highly customisable and you can show a dynamic menu with quick action buttons as the view is 50 | dragged and snapped very easily. The drag and snap limits will be automatically set according to the menu and the view. 51 | [snap](https://pub.dev/packages/snap) is now implemented directly to the package. See [Media](#media) for examples.** 52 | 53 | * **The "Overlap" and "Alignment" features are now added. These two features create a much more fluent Peek & Pop process that is much more similar 54 | to the actual iOS version. See [Media](#media) for examples.** 55 | 56 | * **The "Scale Up" and "Scale Down" features are now added. You can use these features to scale a widget down or up as the Peek & Pop process 57 | proceeds. "Scale Up" is also supported for the "Indicator" feature out of the box.See [Media](#media) for examples.** 58 | 59 | * **Improved enumeration for the stage of the Peek & Pop process.** 60 | 61 | * **The "Indicator" feature is now added. See [Media](#media) for examples.** 62 | 63 | * **Animations are now up to 4x faster with the new optimised blur effect algorithm during the Peek & Pop process.** 64 | * * * 65 | [comment]: <> (Warning) 66 | ## Warning 67 | * **"isHero" is now removed. It wasn't playing well with the package algorithm and it is considered to be unnecessary for the Peek & Pop process. 68 | However, this shouldn't be a problem due to the addition of the new "Overlap" and "Alignment" features. If you must use a Hero widget, only use it 69 | while "willBeDone" or "isDone" is true.** 70 | 71 | * **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 72 | the relevant installation instructions.** 73 | * * * 74 | 75 | 76 | [comment]: <> (Media) 77 | 78 | ## Media 79 | 80 | Watch on **Youtube**: 81 | 82 | [**v1.0.0 Showcase Demo**](https://youtu.be/IQq_ty5mRYU) | [**v1.0.0 Technical Preview**](https://youtu.be/hIjoWfP0krA) 83 |

84 | [v0.1.7](https://youtu.be/wOWCV7HJzwc) 85 | 86 | [v0.1.0 Mixed](https://youtu.be/G5QLwGtcb1I) 87 | 88 | [v0.0.1 Normal](https://youtu.be/PaEpU31z_7Q) | [v0.0.1 Moveable](https://youtu.be/3TjCFwHoOiE) | [v0.0.1 Platform View](https://youtu.be/489YB-QuJ3k) | [v0.0.1 Hero](https://youtu.be/36DAwnFKSKI) 89 |

90 | 91 | 92 |

93 | 94 | 95 | [comment]: <> (Description) 96 | 97 | ## Description 98 | As a fan of the iOS Peek & Pop functionality, I decided to implement it for Flutter as well. 99 | 100 | The package has been tested on iOS but not yet on Android as I don't have access to an Android device with Force Press capabilities. Help about 101 | this would be appreciated. 102 | 103 | ~~For devices that don't support Force Press, the package comes with an adaptation to Long Press *however* the Long Press version of this package is 104 | still under development and is not yet fully tested so consider it as a developers preview.~~ 105 | 106 | (The Long Press version is temporarily removed. It will be added back soon.) 107 | 108 | ## 109 | The power move of this package is what I like to call "Gesture Recognition Rerouting". Normally, when a new widget with GestureDetector or similar 110 | is pushed over an initial widget used for detecting Force Press or when Navigator is used to pop a new page, the user has to restart the gesture 111 | for Flutter to resume updating it. This package fixes that problem as explained in the documentation: 112 | 113 | ``` 114 | //This function is called by the instantiated [PeekAndPopChild] once it is ready to be included in the Peek & Pop process. Perhaps the most 115 | //essential functionality of this package also takes places in this function: The gesture recognition is rerouted from the [PeekAndPopDetector] 116 | //to the instantiated [PeekAndPopChild]. This is important for avoiding the necessity of having the user stop and restart their Force Press. 117 | //Instead, the [PeekAndPopController] does this automatically so that the existing Force Press can continue to update even when if 118 | //[PeekAndPopDetector] is blocked by the view which is often the case especially when using PlatformViews. 119 | ``` 120 | 121 | 122 | [comment]: <> (Installation) 123 | 124 | ## Installation 125 | *It is easy. Don't worry.* 126 | 127 | **If you do not wish to use PlatformViews you can skip the installation instructions.** 128 | 129 | **Old installation instructions are removed. If you wish (for some reason) to use a version older than v0.1.9, see the README of that version for 130 | the relevant installation instructions.** 131 | 132 | For properly displaying PlatformViews, this package requires the latest Flutter [master](https://github.com/flutter/flutter) 133 | branch. *Maybe* it will work with some other version too but tests made with the [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) 134 | seem to only properly display with the latest Flutter [master](https://github.com/flutter/flutter) branch which has improved the PlatformViews that 135 | allow better functionalities such as proper scaling and proper clipping. 136 | 137 | If you do not wish to use PlatformViews, you can skip this step. 138 | 139 | To use latest Flutter [master](https://github.com/flutter/flutter) branch, run the following command. 140 | 141 | **Note**: Don't forget to add io.flutter.embedded_views_previewYES to your Info.plist. See 142 | [webview_flutter](https://pub.flutter-io.cn/packages/webview_flutter) for more info. 143 | 144 | ``` 145 | $ git clone -b master https://github.com/flutter/flutter.git 146 | $ flutter channel master 147 | $ flutter upgrade 148 | $ flutter doctor 149 | $ ./flutter/bin/flutter --version 150 | ``` 151 | 152 | 153 | [comment]: <> (How-to-Use) 154 | 155 | ## How-to-Use 156 | *Also easy.* 157 | 158 | First of all, as explained in the documentation: 159 | 160 | ``` 161 | //I noticed that a fullscreen blur effect via the [BackdropFilter] widget is not good to use while running the animations required for the Peek & 162 | //Pop process as it causes a noticeable drop in the framerate- especially for devices with high resolutions. During a mostly static view, the 163 | //drop is acceptable. However, once the animations start running, this drop causes a visual disturbance. To prevent this, a new optimised blur 164 | //effect algorithm is implemented. Now, the [BackdropFilter] widget is only used until the animations are about to start. At that moment, it is 165 | //replaced by a static image. Therefore, to capture this image, your root CupertinoApp/MaterialApp MUST be wrapped in a [RepaintBoundary] widget 166 | //which uses the [background] key. As a result, the Peek & Pop process is now up to 4x more fluent. 167 | ``` 168 | 169 | TL;DR: Wrap your root CupertinoApp/MaterialApp in a RepaintBoundary widget and use the background GlobalKey from "misc.dart". 170 | 171 | This is required for the new optimised blur effect algorithm: 172 | 173 | ``` 174 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 175 | 176 | class MyApp extends StatelessWidget { 177 | @override 178 | Widget build(BuildContext context) { 179 | return RepaintBoundary( 180 | key: PeekAndPopMisc.background, 181 | child: MaterialApp( 182 | title: 'Peek & Pop Demo', 183 | home: MyHomePage(title: 'Peek & Pop Demo') 184 | ) 185 | ); 186 | } 187 | } 188 | ``` 189 | 190 | If you wish to use the "ScaleUp" or the "Scale Down" features, wrap the widgets you wish to scale down or scale up during the Peek & Pop process with 191 | the scaleUpWrapper and scaleDownWrapper functions from "misc.dart": 192 | 193 | ``` 194 | @override 195 | Widget build(BuildContext context) { 196 | return Scaffold( 197 | appBar: AppBar(title: Text(widget.title)), 198 | body: PeekAndPopMisc.scaleDownWrapper( 199 | ..., 200 | 0.04, 201 | ), 202 | ); 203 | } 204 | ``` 205 | 206 | Then, create a PeekAndPopController such as: 207 | 208 | ``` 209 | PeekAndPopController( 210 | uiChild(), //Widget uiChild 211 | false, //bool uiChildUseCache 212 | {Key key, 213 | peekAndPopBuilder, 214 | peekAndPopBuilderUseCache, 215 | peekAndPopBuilderAtPeek : peekAndPopBuilderAtPeek, 216 | peekAndPopBuilderAtPop : peekAndPopBuilderAtPop, 217 | quickActionsBuilder : quickActionsBuilder, 218 | sigma : 10, 219 | backdropColor : Colors.black, 220 | alpha : 126, 221 | overlayBuilder : overlayBuilder, 222 | useOverlap : true, 223 | customOverlapRect, 224 | useAlignment, : false, 225 | useIndicator : true, 226 | indicatorScaleUpCoefficient : 0.01, 227 | willPeekAndPopComplete : _willPeekAndPopComplete, 228 | willPushPeekAndPop : _willPushPeekAndPop, 229 | willUpdatePeekAndPop : _willUpdatePeekAndPop, 230 | willCancelPeekAndPop : _willCancelPeekAndPop, 231 | willFinishPeekAndPop : _willFinishPeekAndPop, 232 | willClosePeekAndPop : _willClosePeekAndPop, 233 | onPeekAndPopComplete : _onPeekAndPopComplete, 234 | onPushPeekAndPop : _onPushPeekAndPop, 235 | onUpdatePeekAndPop : _onUpdatePeekAndPop, 236 | onCancelPeekAndPop : _onCancelPeekAndPop, 237 | onFinishPeekAndPop : _onFinishPeekAndPop, 238 | onClosePeekAndPop : _onFinishPeekAndPop, 239 | onPressStart : _onPressStart, 240 | onPressUpdate : _onPressUpdate, 241 | onPressEnd : _onPressEnd, 242 | treshold : 0.5, 243 | startPressure : 0.125, 244 | peakPressure : 1.0, 245 | peekScale : 0.5, 246 | peekCoefficient : 0.05, 247 | popTransition, 248 | useHaptics : true}) 249 | 250 | Widget uiChild() {} 251 | 252 | Widget peekAndPopBuilderAtPeek(BuildContext context, PeekAndPopControllerState _peekAndPopController); 253 | Widget peekAndPopBuilderAtPop(BuildContext context, PeekAndPopControllerState _peekAndPopController); 254 | 255 | QuickActionsData quickActionsBuilder(PeekAndPopControllerState _peekAndPopController); 256 | 257 | WidgetBuilder overlayBuiler(BuildContext context); 258 | 259 | bool _willPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 260 | bool _willPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 261 | bool _willUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 262 | bool _willCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 263 | bool _willFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 264 | bool _willClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 265 | 266 | void _onPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController); 267 | void _onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController); 268 | void _onUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController); 269 | void _onCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController); 270 | void _onFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController); 271 | void _onClosePeekAndPop(PeekAndPopControllerState _peekAndPopController); 272 | 273 | void _onPressStart(dynamic dragDetails); 274 | void _onPressUpdate(dynamic dragDetails); 275 | void _onPressEnd(dynamic dragDetails); 276 | 277 | ``` 278 | 279 | **Further Explanations:** 280 | 281 | *For a complete set of descriptions for all parameters and methods, see the [documentation](https://pub.dev/documentation/peek_and_pop/latest/).* 282 | 283 | * Set [uiChildUseCache] to true if your [uiChild] doesn't change during the Peek & Pop process. 284 | * Set [peekAndPopBuilderUseCache] to true if your [peekAndPopBuilder] doesn't change during the Peek & Pop process. 285 | * If [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] are set, [peekAndPopBuilder] and [peekAndPopBuilderUseCache] are ignored. 286 | * If one of [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPeek] is set, the other one must be set too. 287 | * If [quickActionsBuilder] is set, it is recommended that [peekAndPopBuilderAtPop] and [peekAndPopBuilderAtPop] are set too. 288 | * [overlayBuilder] is an optional second view to be displayed during the Peek & Pop process. This entire widget is built after everything else. 289 | * For all [PeekAndPopProcessNotifier] callbacks such as [willPeekAndPopComplete], you can return false to prevent the default action. 290 | * All [PeekAndPopProcessNotifier] and [PeekAndPopProcessCallback] callbacks will return a reference to the created [PeekAndPopController] state. 291 | You can save this instance for further actions. 292 | * [pageTransition] is the transition to be used when the view is opened directly or when the view is closed. A default [SlideTransition] is provided. 293 | * Use [PeekAndPopControllerState]'s [void closePeekAndPop()] method to close the Peek & Pop process. Do not call [Navigator.of(context).pop()] 294 | directly. 295 | * Use [PeekAndPopControllerState]'s [stage] variable to get enumeration for the stage of the Peek & Pop process. If you want to only know when the 296 | Peek & Pop process will be or is completed, you can also use [willBeDone] or [isDone] variables. 297 | 298 | 299 | [comment]: <> (Notes) 300 | ## Notes 301 | I started using and learning Flutter only some weeks ago so this package might have some parts that don't make sense, that should be completely 302 | different, that could be much better, etc. Please let me know! Nicely! 303 | 304 | Any help, suggestion or criticism is appreciated! 305 | 306 | Cheers. 307 | 308 | [comment]: <> (CosmosSoftware) 309 |

310 | 311 |

-------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/0.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/1.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/10.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/10.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/11.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/11.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/12.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/12.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/13.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/13.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/14.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/14.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/15.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/15.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/16.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/16.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/17.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/17.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/18.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/18.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/19.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/19.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/2.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/20.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/20.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/21.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/21.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/22.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/22.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/23.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/23.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/24.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/24.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/25.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/25.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/26.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/26.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/27.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/27.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/28.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/28.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/29.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/29.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/3.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/4.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/5.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/6.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/7.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/7.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/8.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/9.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/Hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/Hero.png -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/assets/Scenery.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/assets/Scenery.jpeg -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/lib/main.dart: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // © Cosmos Software | Ali Yigit Bireroglu / 3 | // All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property") / 4 | // belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and / 5 | // other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright / 6 | // text at all times. / 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | //@formatter:off 9 | 10 | import 'package:flutter/foundation.dart'; 11 | import 'package:flutter/cupertino.dart'; 12 | import 'package:flutter/material.dart'; 13 | import 'package:flutter/services.dart'; 14 | 15 | import 'nav_bar.dart' as MyNavBar; 16 | 17 | import 'package:peek_and_pop/peek_and_pop.dart'; 18 | import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc; 19 | 20 | PeekAndPopControllerState peekAndPopController; 21 | 22 | final GlobalKey scaffold = GlobalKey(); 23 | final GlobalKey header = GlobalKey(); 24 | 25 | void main() => runApp(MyApp()); 26 | 27 | class MyApp extends StatelessWidget { 28 | @override 29 | Widget build(BuildContext context) { 30 | return RepaintBoundary( 31 | key: PeekAndPopMisc.background, 32 | child: MaterialApp( 33 | title: 'Showcase', 34 | home: MyHomePage(title: 'Showcase'), 35 | ), 36 | ); 37 | } 38 | } 39 | 40 | class MyHomePage extends StatefulWidget { 41 | MyHomePage({Key key, this.title}) : super(key: key); 42 | 43 | final String title; 44 | 45 | @override 46 | _MyHomePageState createState() => _MyHomePageState(); 47 | } 48 | 49 | class _MyHomePageState extends State { 50 | ScrollController scrollController; 51 | ValueNotifier scrollControllerNotifier; 52 | List verticalImages = [2, 3, 7, 15, 17, 18, 21]; 53 | 54 | void onScroll() { 55 | scrollControllerNotifier.value = scrollController.offset * 1.0; 56 | } 57 | 58 | @override 59 | void initState() { 60 | super.initState(); 61 | 62 | scrollController = ScrollController(initialScrollOffset: 0); 63 | scrollController.addListener(onScroll); 64 | scrollControllerNotifier = ValueNotifier(0.0); 65 | } 66 | 67 | void showSnackbar() { 68 | scaffold.currentState.showSnackBar(SnackBar(content: const Text("Photo is saved your favourites."))); 69 | } 70 | 71 | Widget atPeekWrapper(Widget child, PeekAndPopControllerState _peekAndPopController) { 72 | return Container( 73 | decoration: BoxDecoration( 74 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 75 | boxShadow: [ 76 | const BoxShadow( 77 | color: Colors.black, 78 | offset: const Offset(0, 15), 79 | spreadRadius: -5, 80 | blurRadius: 20, 81 | ), 82 | ], 83 | ), 84 | child: ClipRRect( 85 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 86 | child: child, 87 | ), 88 | ); 89 | } 90 | 91 | MyNavBar.CupertinoNavigationBar appBar(PeekAndPopControllerState _peekAndPopController) { 92 | return MyNavBar.CupertinoNavigationBar( 93 | key: header, 94 | backgroundColor: const Color(0xff1B1B1B), 95 | border: const Border( 96 | bottom: const BorderSide( 97 | color: Colors.black, 98 | width: 0.0, 99 | style: BorderStyle.solid, 100 | ), 101 | ), 102 | middle: const Text( 103 | "Photo", 104 | style: const TextStyle(color: const Color(0xffFF9500)), 105 | ), 106 | leading: CupertinoButton( 107 | padding: EdgeInsets.only(bottom: 2), 108 | onPressed: () { 109 | HapticFeedback.mediumImpact(); 110 | _peekAndPopController.closePeekAndPop(); 111 | }, 112 | child: const Icon( 113 | CupertinoIcons.clear_circled, 114 | size: 25, 115 | color: const Color(0xffFF9500), 116 | ), 117 | ), 118 | trailing: CupertinoButton( 119 | padding: EdgeInsets.only(bottom: 2), 120 | onPressed: () { 121 | HapticFeedback.mediumImpact(); 122 | showSnackbar(); 123 | }, 124 | child: const Icon( 125 | CupertinoIcons.heart_solid, 126 | size: 25, 127 | color: const Color(0xffFF9500), 128 | ), 129 | ), 130 | transitionBetweenRoutes: false, 131 | ); 132 | } 133 | 134 | Widget atPopWrapper(Widget child, PeekAndPopControllerState _peekAndPopController) { 135 | return Scaffold( 136 | key: scaffold, 137 | backgroundColor: CupertinoColors.darkBackgroundGray, 138 | appBar: appBar(_peekAndPopController), 139 | body: SizedBox.expand(child: child), 140 | ); 141 | } 142 | 143 | Widget gridPeekAndPopBuilderAtPeek(int index, BuildContext context, PeekAndPopControllerState _peekAndPopController) { 144 | return atPeekWrapper( 145 | Image.asset( 146 | "assets/" + index.toString() + ".jpeg", 147 | fit: BoxFit.contain, 148 | key: Key("Image"), 149 | scale: verticalImages.contains(index) ? 0.5 : 1.0, 150 | ), 151 | _peekAndPopController, 152 | ); 153 | } 154 | 155 | Widget gridPeekAndPopBuilderAtPop(int index, BuildContext context, PeekAndPopControllerState _peekAndPopController) { 156 | return atPopWrapper( 157 | Transform.translate( 158 | offset: Offset(0, verticalImages.contains(index) ? 0.0 : -50), 159 | child: Image.asset( 160 | "assets/" + index.toString() + ".jpeg", 161 | fit: BoxFit.contain, 162 | key: Key("Image"), 163 | ), 164 | ), 165 | _peekAndPopController, 166 | ); 167 | } 168 | 169 | QuickActionsData gridQuickActionsBuilder(PeekAndPopControllerState _peekAndPopController) { 170 | return QuickActionsData( 171 | const EdgeInsets.only(left: 12.5, top: 25, right: 12.5, bottom: 25), 172 | const BorderRadius.all(const Radius.circular(10.0)), 173 | [ 174 | QuickAction( 175 | 60, 176 | () { 177 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 178 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 179 | _peekAndPopController.finishPeekAndPop(null); 180 | }); 181 | }, 182 | const BoxDecoration( 183 | color: CupertinoColors.white, 184 | border: const Border( 185 | bottom: const BorderSide( 186 | color: CupertinoColors.inactiveGray, 187 | width: 0.0, 188 | style: BorderStyle.solid, 189 | ), 190 | ), 191 | ), 192 | const Center( 193 | child: const Text( 194 | "Pop", 195 | style: const TextStyle( 196 | color: CupertinoColors.activeBlue, 197 | fontWeight: FontWeight.normal, 198 | fontSize: 20, 199 | ), 200 | textAlign: TextAlign.center, 201 | ), 202 | ), 203 | ), 204 | QuickAction( 205 | 60, 206 | () {}, 207 | const BoxDecoration( 208 | color: CupertinoColors.white, 209 | border: const Border( 210 | bottom: const BorderSide( 211 | color: CupertinoColors.inactiveGray, 212 | width: 0.0, 213 | style: BorderStyle.solid, 214 | ), 215 | ), 216 | ), 217 | const Center( 218 | child: const Text( 219 | "Save", 220 | style: const TextStyle( 221 | color: CupertinoColors.activeBlue, 222 | fontWeight: FontWeight.normal, 223 | fontSize: 20, 224 | ), 225 | textAlign: TextAlign.center, 226 | ), 227 | ), 228 | ), 229 | QuickAction( 230 | 60, 231 | () {}, 232 | const BoxDecoration( 233 | color: CupertinoColors.white, 234 | border: const Border( 235 | bottom: const BorderSide( 236 | color: CupertinoColors.inactiveGray, 237 | width: 0.0, 238 | style: BorderStyle.solid, 239 | ), 240 | ), 241 | ), 242 | const Center( 243 | child: const Text( 244 | "Share", 245 | style: const TextStyle( 246 | color: CupertinoColors.activeBlue, 247 | fontWeight: FontWeight.normal, 248 | fontSize: 20, 249 | ), 250 | textAlign: TextAlign.center, 251 | ), 252 | ), 253 | ), 254 | QuickAction( 255 | 60, 256 | () { 257 | _peekAndPopController.peekAndPopChild.quickActions.currentState.animationController.reverse(); 258 | Future.wait([_peekAndPopController.peekAndPopChild.snapController.currentState.move(const Offset(0.0, 0.0))]).then((_) { 259 | _peekAndPopController.cancelPeekAndPop(null); 260 | }); 261 | }, 262 | const BoxDecoration( 263 | color: CupertinoColors.white, 264 | ), 265 | const Center( 266 | child: const Text( 267 | "Dismiss", 268 | style: const TextStyle( 269 | color: CupertinoColors.destructiveRed, 270 | fontWeight: FontWeight.normal, 271 | fontSize: 20, 272 | ), 273 | textAlign: TextAlign.center, 274 | ), 275 | ), 276 | ), 277 | ], 278 | ); 279 | } 280 | 281 | @override 282 | Widget build(BuildContext context) { 283 | return CupertinoPageScaffold( 284 | backgroundColor: CupertinoColors.darkBackgroundGray, 285 | child: PeekAndPopMisc.scaleDownWrapper( 286 | CustomScrollView( 287 | controller: scrollController, 288 | slivers: [ 289 | MyNavBar.CupertinoSliverNavigationBar( 290 | largeTitle: Text( 291 | widget.title, 292 | style: const TextStyle(color: const Color(0xffFF9500)), 293 | ), 294 | backgroundColor: const Color(0xff1B1B1B), 295 | border: const Border( 296 | bottom: const BorderSide( 297 | color: Colors.black, 298 | width: 0.0, 299 | style: BorderStyle.solid, 300 | ), 301 | ), 302 | transitionBetweenRoutes: false, 303 | ), 304 | SliverPadding( 305 | padding: EdgeInsets.all(10), 306 | sliver: SliverGrid.count( 307 | mainAxisSpacing: 10.0, 308 | crossAxisSpacing: 10.0, 309 | crossAxisCount: 3, 310 | children: List.generate(30, (int index) { 311 | return PeekAndPopController( 312 | ValueListenableBuilder( 313 | builder: (BuildContext context, double scrollController, Widget cachedChild) { 314 | double height = MediaQuery.of(context).size.width / 3.0; 315 | double position = index % 3 * height; 316 | double alignment = ((scrollController - position) / (position + height)).clamp(-1.0, 1.0); 317 | 318 | return Container( 319 | decoration: BoxDecoration( 320 | image: DecorationImage( 321 | image: AssetImage( 322 | "assets/" + index.toString() + ".jpeg", 323 | ), 324 | alignment: Alignment(alignment, alignment), 325 | fit: BoxFit.cover, 326 | ), 327 | borderRadius: const BorderRadius.all(const Radius.circular(10.0)), 328 | ), 329 | ); 330 | }, 331 | valueListenable: scrollControllerNotifier, 332 | ), 333 | true, 334 | peekAndPopBuilderAtPeek: (BuildContext context, PeekAndPopControllerState _peekAndPopController) => gridPeekAndPopBuilderAtPeek(index, context, _peekAndPopController), 335 | peekAndPopBuilderAtPop: (BuildContext context, PeekAndPopControllerState _peekAndPopController) => gridPeekAndPopBuilderAtPop(index, context, _peekAndPopController), 336 | quickActionsBuilder: gridQuickActionsBuilder, 337 | sigma: 10, 338 | backdropColor: Colors.white, 339 | useOverlap: true, 340 | useAlignment: false, 341 | indicatorScaleUpCoefficient: 0.01, 342 | peekScale: 0.95, 343 | peekCoefficient: 0.025, 344 | ); 345 | }), 346 | ), 347 | ) 348 | ], 349 | ), 350 | 0.04, 351 | ), 352 | ); 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/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.5.0-nullsafety" 11 | bloc: 12 | dependency: transitive 13 | description: 14 | name: bloc 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "6.0.3" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0-nullsafety" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.1.0-nullsafety.2" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.2.0-nullsafety" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0-nullsafety" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.15.0-nullsafety.2" 53 | cupertino_icons: 54 | dependency: "direct main" 55 | description: 56 | name: cupertino_icons 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "0.1.2" 60 | fake_async: 61 | dependency: transitive 62 | description: 63 | name: fake_async 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.1.0-nullsafety" 67 | flick: 68 | dependency: transitive 69 | description: 70 | name: flick 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.0.2" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_test: 80 | dependency: "direct dev" 81 | description: flutter 82 | source: sdk 83 | version: "0.0.0" 84 | matcher: 85 | dependency: transitive 86 | description: 87 | name: matcher 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "0.12.10-nullsafety" 91 | meta: 92 | dependency: transitive 93 | description: 94 | name: meta 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.3.0-nullsafety.2" 98 | path: 99 | dependency: transitive 100 | description: 101 | name: path 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.8.0-nullsafety" 105 | peek_and_pop: 106 | dependency: "direct main" 107 | description: 108 | path: ".." 109 | relative: true 110 | source: path 111 | version: "1.0.3" 112 | sky_engine: 113 | dependency: transitive 114 | description: flutter 115 | source: sdk 116 | version: "0.0.99" 117 | snap: 118 | dependency: transitive 119 | description: 120 | name: snap 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.0.4" 124 | source_span: 125 | dependency: transitive 126 | description: 127 | name: source_span 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.8.0-nullsafety" 131 | stack_trace: 132 | dependency: transitive 133 | description: 134 | name: stack_trace 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.10.0-nullsafety" 138 | stream_channel: 139 | dependency: transitive 140 | description: 141 | name: stream_channel 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.1.0-nullsafety" 145 | string_scanner: 146 | dependency: transitive 147 | description: 148 | name: string_scanner 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.1.0-nullsafety" 152 | term_glyph: 153 | dependency: transitive 154 | description: 155 | name: term_glyph 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.2.0-nullsafety" 159 | test_api: 160 | dependency: transitive 161 | description: 162 | name: test_api 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "0.2.19-nullsafety" 166 | transparent_image: 167 | dependency: transitive 168 | description: 169 | name: transparent_image 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.0.0" 173 | typed_data: 174 | dependency: transitive 175 | description: 176 | name: typed_data 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.3.0-nullsafety.2" 180 | vector_math: 181 | dependency: transitive 182 | description: 183 | name: vector_math 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.1.0-nullsafety.2" 187 | webview_flutter: 188 | dependency: "direct main" 189 | description: 190 | name: webview_flutter 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "0.3.13" 194 | sdks: 195 | dart: ">=2.10.0-0.0.dev <2.10.0" 196 | flutter: ">=1.5.0 <2.0.0" 197 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name : pretty_example 2 | description : Pretty Example Project for peek_and_pop. 3 | version : 1.0.3 4 | author : Ali Yigit Bireroglu 5 | repository : https://github.com/aliyigitbireroglu/flutter-peek-and-pop 6 | homepage : https://www.cosmossoftware.coffee 7 | 8 | environment : 9 | sdk: ">=2.1.0 <3.0.0" 10 | 11 | dependencies : 12 | flutter : 13 | sdk: flutter 14 | peek_and_pop : 15 | path: ../ 16 | cupertino_icons: ^0.1.2 17 | webview_flutter: ^0.3.13 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter : 24 | uses-material-design: true 25 | 26 | assets : 27 | - assets/ 28 | -------------------------------------------------------------------------------- /peek_and_pop/pretty_example/test/pretty_example_test.dart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/pretty_example/test/pretty_example_test.dart -------------------------------------------------------------------------------- /peek_and_pop/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/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.5.0-nullsafety" 11 | bloc: 12 | dependency: "direct main" 13 | description: 14 | name: bloc 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "6.0.3" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0-nullsafety" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.1.0-nullsafety.2" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.2.0-nullsafety" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0-nullsafety" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.15.0-nullsafety.2" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.1.0-nullsafety" 60 | flick: 61 | dependency: transitive 62 | description: 63 | name: flick 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.0.3" 67 | flutter: 68 | dependency: "direct main" 69 | description: flutter 70 | source: sdk 71 | version: "0.0.0" 72 | flutter_test: 73 | dependency: "direct dev" 74 | description: flutter 75 | source: sdk 76 | version: "0.0.0" 77 | matcher: 78 | dependency: transitive 79 | description: 80 | name: matcher 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "0.12.10-nullsafety" 84 | meta: 85 | dependency: transitive 86 | description: 87 | name: meta 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.3.0-nullsafety.2" 91 | path: 92 | dependency: transitive 93 | description: 94 | name: path 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.8.0-nullsafety" 98 | sky_engine: 99 | dependency: transitive 100 | description: flutter 101 | source: sdk 102 | version: "0.0.99" 103 | snap: 104 | dependency: "direct main" 105 | description: 106 | name: snap 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.0.5" 110 | source_span: 111 | dependency: transitive 112 | description: 113 | name: source_span 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.8.0-nullsafety" 117 | stack_trace: 118 | dependency: transitive 119 | description: 120 | name: stack_trace 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.10.0-nullsafety" 124 | stream_channel: 125 | dependency: transitive 126 | description: 127 | name: stream_channel 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "2.1.0-nullsafety" 131 | string_scanner: 132 | dependency: transitive 133 | description: 134 | name: string_scanner 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.1.0-nullsafety" 138 | term_glyph: 139 | dependency: transitive 140 | description: 141 | name: term_glyph 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.2.0-nullsafety" 145 | test_api: 146 | dependency: transitive 147 | description: 148 | name: test_api 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "0.2.19-nullsafety" 152 | transparent_image: 153 | dependency: "direct main" 154 | description: 155 | name: transparent_image 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.0.0" 159 | typed_data: 160 | dependency: transitive 161 | description: 162 | name: typed_data 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.3.0-nullsafety.2" 166 | vector_math: 167 | dependency: transitive 168 | description: 169 | name: vector_math 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "2.1.0-nullsafety.2" 173 | sdks: 174 | dart: ">=2.10.0-0.0.dev <2.10.0" 175 | -------------------------------------------------------------------------------- /peek_and_pop/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name : peek_and_pop 2 | description : Peek & Pop implementation for Flutter based on the iOS functionality of the same name. 3 | version : 1.0.3 4 | author : Ali Yigit Bireroglu 5 | repository : https://github.com/aliyigitbireroglu/flutter-peek-and-pop 6 | homepage : https://www.cosmossoftware.coffee 7 | 8 | environment : 9 | sdk: ">=2.8.0 <3.0.0" 10 | 11 | dependencies : 12 | flutter : 13 | sdk: flutter 14 | snap : ^1.0.5 15 | transparent_image: ^1.0.0 16 | bloc : ^6.0.3 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | flutter : 23 | -------------------------------------------------------------------------------- /peek_and_pop/test/peek_and_pop_test.dart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyigitbireroglu/flutter-peek-and-pop/232534da374a0babeb2a077a60b8e809e64cd8a1/peek_and_pop/test/peek_and_pop_test.dart --------------------------------------------------------------------------------