Commit fa9f91bc by Rizal Hermawan

fix: fixed bugs after downgrading the flutter version

parents
{
"configVersion": 2,
"packages": [
{
"name": "async",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/async-2.8.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "boolean_selector",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "characters",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "charcode",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/charcode-1.3.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "clock",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "collection",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "fake_async",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "flutter",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "flutter_test",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter_test",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "matcher",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "meta",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/meta-1.7.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "path",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/path-1.8.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "sky_engine",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/bin/cache/pkg/sky_engine",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "source_span",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "stack_trace",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "stream_channel",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "string_scanner",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "term_glyph",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "test_api",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "typed_data",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "vector_math",
"rootUri": "file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "implicitly_animated_reorderable_list_2",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "2.12"
}
],
"generated": "2023-12-04T07:55:04.703197Z",
"generator": "pub",
"generatorVersion": "2.14.4"
}
async
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/async-2.8.1/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/async-2.8.1/lib/
boolean_selector
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/
characters
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib/
charcode
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/charcode-1.3.1/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/charcode-1.3.1/lib/
clock
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/
collection
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/
fake_async
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/
matcher
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib/
meta
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/meta-1.7.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/meta-1.7.0/lib/
path
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/
source_span
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib/
stack_trace
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/
stream_channel
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/
string_scanner
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/
term_glyph
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/
test_api
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2/lib/
typed_data
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/
vector_math
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib/
sky_engine
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/bin/cache/pkg/sky_engine/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/bin/cache/pkg/sky_engine/lib/
flutter
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter/lib/
flutter_test
2.12
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter_test/
file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter_test/lib/
implicitly_animated_reorderable_list_2
2.12
file:///C:/24%20Rizal%20Hermawan/job/mobile/codingan/edit_pub/implicitly_animated_reorderable_list_2-0.5.1/
file:///C:/24%20Rizal%20Hermawan/job/mobile/codingan/edit_pub/implicitly_animated_reorderable_list_2-0.5.1/lib/
2
2.5.3
\ No newline at end of file
# This file is deprecated. Tools should instead consume
# `.dart_tool/package_config.json`.
#
# For more info see: https://dart.dev/go/dot-packages-deprecation
#
# Generated by pub on 2023-12-04 14:55:04.690276.
async:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/async-2.8.1/lib/
boolean_selector:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/
characters:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib/
charcode:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/charcode-1.3.1/lib/
clock:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib/
collection:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib/
fake_async:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib/
flutter:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter/lib/
flutter_test:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/packages/flutter_test/lib/
matcher:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib/
meta:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/meta-1.7.0/lib/
path:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib/
sky_engine:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/bin/cache/pkg/sky_engine/lib/
source_span:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib/
stack_trace:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/
stream_channel:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/
string_scanner:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/
term_glyph:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/
test_api:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2/lib/
typed_data:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib/
vector_math:file:///C:/24%20Rizal%20Hermawan/flutter_2.5.3/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib/
implicitly_animated_reorderable_list_2:lib/
## 0.4.4
* **Fixes**
## 0.4.3
* **Fixed** `WidgetsBinding` null warning
## 0.4.2
* **Fixed** #54, #72
## 0.4.0
* **Added** NNBD support
* **Fixed** #19, #49, #50, #52
* **Improved** `Handle` is now able to capture pointer events which allows an `ImplicitlyAnimatedReorderableList` to be placed inside another scrollable without any workarounds.
* **Breaking** Renamed `dragDuration` to `reorderDuration`
* **Added** Field `liftDuration`
* **Added** Field `settleDuration`
## 0.3.2
* **Fixed** #47
## 0.3.1
* **Fixed** #43
* **Fixed** Changelog
## 0.3.0
* **Fixed** #23
## 0.2.5
* **Fixed** #14
## 0.2.1
* **Improved** `ImplicitlyAnimatedList` now always uses the latest items, even if `listEquals()` is `true`.
## 0.2.0
* **Added** support for headers and footers on the `ImplicitlyAnimatedReorderableList`.
* **Added** `child` property on `Reorderable` that can be used instead off the `builder` that will use a default elevation animation instead of being forced to specify your own custom animation.
## 0.1.10
* **Fixed** Bugs
## 0.1.4
* **Improved** `Handle` is now scroll aware and only initiates a drag when the scroll position didn't change.
* **Added** horizontal scrollDirection support for `ImplicitlyAnimatedReorderableList`
## 0.1.0
* Initial release
MIT License
Copyright (c) 2020 bxqm
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# Implicitly Animated Reorderable List
[![pub package](https://img.shields.io/pub/v/implicitly_animated_reorderable_list_2.svg)](https://pub.dartlang.org/packages/implicitly_animated_reorderable_list_2)
[![GitHub Stars](https://img.shields.io/github/stars/bxqm/implicitly_animated_reorderable_list_2.svg?logo=github)](https://github.com/bxqm/implicitly_animated_reorderable_list_2)
A Flutter `ListView` that implicitly calculates the changes between two lists using the `MyersDiff` algorithm and animates between them for you. The `ImplicitlyAnimatedReorderableList` adds reordering support to its items with fully custom animations.
<p style="text-align:center">
<img width="356px" alt="Demo" src="https://raw.githubusercontent.com/bxqm/implicitly_animated_reorderable_list_2/master/assets/demo.gif"/>
</p>
Click [here](https://github.com/bxqm/implicitly_animated_reorderable_list_2/blob/master/example/lib/ui/) to view the full example.
## Installing
Add it to your `pubspec.yaml` file:
```yaml
dependencies:
implicitly_animated_reorderable_list_2: ^0.4.2
```
Install packages from the command line
```
flutter packages get
```
If you like this package, consider supporting it by giving it a star on [GitHub](https://github.com/bxqm/implicitly_animated_reorderable_list_2) and a like on [pub.dev](https://pub.dev/packages/implicitly_animated_reorderable_list_2) :heart:
## Usage
The package contains two `ListViews`: `ImplicitlyAnimatedList` which is the base class and offers implicit animation for item `insertions`, `removals` as well as `updates`, and `ImplicitlyAnimatedReorderableList` which extends the `ImplicitlyAnimatedList` and adds reordering support to its items. See examples below on how to use them.
### ImplicitlyAnimatedList
`ImplicitlyAnimatedList` is based on `AnimatedList` and uses the `MyersDiff` algorithm to calculate the difference between two lists and calls `insertItem` and `removeItem` on the `AnimatedListState` for you.
#### Example
```dart
// Specify the generic type of the data in the list.
ImplicitlyAnimatedList<MyGenericType>(
// The current items in the list.
items: items,
// Called by the DiffUtil to decide whether two object represent the same item.
// For example, if your items have unique ids, this method should check their id equality.
areItemsTheSame: (a, b) => a.id == b.id,
// Called, as needed, to build list item widgets.
// List items are only built when they're scrolled into view.
itemBuilder: (context, animation, item, index) {
// Specifiy a transition to be used by the ImplicitlyAnimatedList.
// See the Transitions section on how to import this transition.
return SizeFadeTransition(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: animation,
child: Text(item.name),
);
},
// An optional builder when an item was removed from the list.
// If not specified, the List uses the itemBuilder with
// the animation reversed.
removeItemBuilder: (context, animation, oldItem) {
return FadeTransition(
opacity: animation,
child: Text(oldItem.name),
);
},
);
```
> If you have a `CustomScrollView` you can use the `SliverImplicitlyAnimatedList`.
> As `AnimatedList` doesn't support item moves, a move is handled by removing the item from the old index and inserting it at the new index.
### ImplicitlyAnimatedReorderableList
`ImplicitlyAnimatedReorderableList` is based on `ImplicitlyAnimatedList` and adds reordering support to the list.
#### Example
```dart
ImplicitlyAnimatedReorderableList<MyGenericType>(
items: items,
areItemsTheSame: (oldItem, newItem) => oldItem.id == newItem.id,
onReorderFinished: (item, from, to, newItems) {
// Remember to update the underlying data when the list has been
// reordered.
setState(() {
items
..clear()
..addAll(newItems);
});
},
itemBuilder: (context, itemAnimation, item, index) {
// Each item must be wrapped in a Reorderable widget.
return Reorderable(
// Each item must have an unique key.
key: ValueKey(item),
// The animation of the Reorderable builder can be used to
// change to appearance of the item between dragged and normal
// state. For example to add elevation when the item is being dragged.
// This is not to be confused with the animation of the itemBuilder.
// Implicit animations (like AnimatedContainer) are sadly not yet supported.
builder: (context, dragAnimation, inDrag) {
final t = dragAnimation.value;
final elevation = lerpDouble(0, 8, t);
final color = Color.lerp(Colors.white, Colors.white.withOpacity(0.8), t);
return SizeFadeTransition(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: itemAnimation,
child: Material(
color: color,
elevation: elevation,
type: MaterialType.transparency,
child: ListTile(
title: Text(item.name),
// The child of a Handle can initialize a drag/reorder.
// This could for example be an Icon or the whole item itself. You can
// use the delay parameter to specify the duration for how long a pointer
// must press the child, until it can be dragged.
trailing: Handle(
delay: const Duration(milliseconds: 100),
child: Icon(
Icons.list,
color: Colors.grey,
),
),
),
),
);
},
);
},
// Since version 0.2.0 you can also display a widget
// before the reorderable items...
header: Container(
height: 200,
color: Colors.red,
),
// ...and after. Note that this feature - as the list itself - is still in beta!
footer: Container(
height: 200,
color: Colors.green,
),
// If you want to use headers or footers, you should set shrinkWrap to true
shrinkWrap: true,
);
```
> For a more in depth example click [here](https://github.com/bxqm/implicitly_animated_reorderable_list_2/blob/master/example/lib/ui/lang_page.dart).
### Transitions
You can use some custom transitions (such as the `SizeFadeTransition`) for item animations by importing the transitions pack:
```dart
import 'package:implicitly_animated_reorderable_list_2/transitions.dart';
```
If you want to contribute your own custom transitions, feel free to make a pull request.
### Caveats
Note that this package is still in its very early phase and not enough testing has been done to guarantee stability.
Also note that computing the diff between two very large lists may take a significant amount of time (the computation is done on a background isolate though unless `spawnIsolate` is set to `false`).
### Acknowledgements
The diff algorithm that `ImplicitlyAnimatedList` uses was written by [Dawid Bota](https://gitlab.com/otsoaUnLoco) at [GitLab](https://gitlab.com/otsoaUnLoco/animated-stream-list).
### Roadmap
You can take a look at the [Roadmap](https://github.com/bxqm/implicitly_animated_reorderable_list_2/blob/master/roadmap.md) to see which featues I am working on or plan to implement in future versions.
This diff is collapsed. Click to expand it.
import 'package:implicitly_animated_reorderable_list_2/src/diff/myers_diff.dart';
// ignore_for_file: avoid_print
class Item {
Item(this.id, this.value);
int id;
int value;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Item && runtimeType == other.runtimeType && id == other.id;
@override
int get hashCode => id.hashCode;
}
Future<void> main() async {
final List<Item> list = List.generate(1000, (index) => Item(index, index));
final List<Item> newList = List.from(list)..shuffle();
final start = DateTime.now();
await MyersDiff.diff<Item>(
newList,
list,
areItemsTheSame: (a, b) => a.id == b.id,
);
final millis = DateTime.now().difference(start).inMilliseconds;
print('Diffing ${newList.length} elements took $millis milliseconds.');
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package io.flutter.plugins;
import io.flutter.plugin.common.PluginRegistry;
/**
* Generated file. Do not edit.
*/
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}
package com.example.example
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
sdk.dir=/Users/david/Library/Android/sdk
flutter.sdk=/Users/david/prog/flutter
\ No newline at end of file
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]}]
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
#include "Generated.xcconfig"
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/david/prog/flutter
FLUTTER_APPLICATION_PATH=/Users/david/Github/implicitly_animated_reorderable_list_2/example
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json
#include "Generated.xcconfig"
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/david/prog/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/david/Github/implicitly_animated_reorderable_list_2/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end
NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */
//
// Generated file. Do not edit.
//
// clang-format off
#import "GeneratedPluginRegistrant.h"
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
#import "GeneratedPluginRegistrant.h"
/* import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:implicitly_animated_reorderable_list_2/implicitly_animated_reorderable_list_2.dart';
import 'util/box.dart';
class Examples extends StatelessWidget {
const Examples({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
// * ImplicitlyAnimatedList
// Specify the generic type of the data in the list.
ImplicitlyAnimatedList<Language>(
// The current items in the list.
data: items,
// Called by the DiffUtil to decide whether two object represent the same item.
// For example, if your items have unique ids, this method should check their id equality.
areItemsTheSame: (a, b) => a.id == b.id,
// Called, as needed, to build list item widgets.
// List items are only built when they're scrolled into view.
itemBuilder: (context, animation, item, index) {
// Specifiy a transition to be used by the ImplicitlyAnimatedList.
// In this case a custom transition.
return SizeFadeTranstion(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: animation,
child: Text(item.name),
);
},
// An optional builder when an item was removed from the list.
// If not specified, the List uses the itemBuilder with
// the animation reversed.
removedItemBuilder: (context, animation, oldItem) {
return FadeTransition(
opacity: animation,
child: Text(oldItem.name),
);
},
);
// * ImplicitlyAnimatedReorderableList
ImplicitlyAnimatedReorderableList<Language>(
data: items,
areItemsTheSame: (a, b) => a.id == b.id,
itemBuilder: (context, itemAnimation, item, index) {
// Each item must be wrapped in a Reorderable widget.
return Reorderable(
// Each item must have a unique key.
key: ValueKey(item),
// The animation of the Reorderable builder can be used to
// change to appearance of the item between dragged and normal
// state. For example to add elevation. Implicit animation are
// not yet supported.
builder: (context, dragAnimation, inDrag) {
final t = dragAnimation.value;
final elevation = lerpDouble(0, 8, t);
final color = Color.lerp(Colors.white, Colors.white.withOpacity(0.8), t);
return SizeFadeTranstion(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: itemAnimation,
child: Box(
color: color,
elevation: elevation,
child: ListTile(
title: Text(item.name),
// The child of a Handle can initialize a drag/reorder.
// This could for example be an Icon or the whole item itself. You can
// use the delay parameter to specify the duration for how long a pointer
// must press the child, until it can be dragged.
trailing: Handle(
delay: const Duration(milliseconds: 100),
child: Icon(
Icons.list,
color: Colors.grey,
),
),
),
),
);
},
);
},
);
}
}
*/
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:example/ui/ui.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
);
return MaterialApp(
title: 'Implicitly Animated Reorderable List Example',
theme: ThemeData.light().copyWith(
accentColor: Colors.amber.shade800,
dividerTheme: DividerThemeData(
thickness: 1,
color: Colors.grey.shade300,
),
),
debugShowCheckedModeBanner: false,
home: const LanguagePage(),
);
}
}
import 'package:flutter/material.dart';
import 'package:implicitly_animated_reorderable_list_2/implicitly_animated_reorderable_list_2.dart';
import 'package:implicitly_animated_reorderable_list_2/transitions.dart';
import '../util/util.dart';
class LanguageSearchPage extends StatefulWidget {
const LanguageSearchPage({Key? key}) : super(key: key);
@override
_LanguageSearchPageState createState() => _LanguageSearchPageState();
}
class _LanguageSearchPageState extends State<LanguageSearchPage> {
final List<Language> filteredLanguages = List.from(languages);
late final _controller = TextEditingController()
..addListener(
_onQueryChanged,
);
String get text => _controller.text.trim();
void _onQueryChanged() {
filteredLanguages.clear();
if (text.isEmpty) {
filteredLanguages
..clear()
..addAll(languages);
setState(() {});
return;
}
final query = text.toLowerCase();
for (final lang in languages) {
final englishName = lang.englishName.toLowerCase();
final nativeName = lang.nativeName.toLowerCase();
final startsWith = englishName.startsWith(query) || nativeName.startsWith(query);
if (startsWith) {
filteredLanguages.add(lang);
}
}
for (final lang in languages) {
final englishName = lang.englishName.toLowerCase();
final nativeName = lang.nativeName.toLowerCase();
final contains = englishName.contains(query) || nativeName.contains(query);
if (contains && !filteredLanguages.contains(lang)) {
filteredLanguages.add(lang);
}
}
setState(() {});
}
Widget _buildItem(Language lang) {
final theme = Theme.of(context);
final textTheme = theme.textTheme;
return Box(
border: Border(
bottom: BorderSide(
color: Colors.grey.shade200,
),
),
color: Colors.white,
onTap: () => Navigator.pop(context, lang),
child: ListTile(
title: HighlightText(
query: text,
text: lang.nativeName,
style: textTheme.bodyText2?.copyWith(
fontSize: 16,
),
activeStyle: textTheme.bodyText2?.copyWith(
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
subtitle: HighlightText(
query: text,
text: lang.englishName,
style: textTheme.bodyText1?.copyWith(
fontSize: 15,
),
activeStyle: textTheme.bodyText1?.copyWith(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
),
);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final textTheme = theme.textTheme;
final padding = MediaQuery.of(context).viewPadding.top;
return Scaffold(
appBar: _buildAppBar(padding, theme, textTheme),
body: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child:
filteredLanguages.isNotEmpty ? _buildList() : _buildNoLanguagesPlaceholder(),
),
);
}
Widget _buildList() {
return ImplicitlyAnimatedList<Language>(
items: filteredLanguages,
updateDuration: const Duration(milliseconds: 400),
areItemsTheSame: (a, b) => a == b,
itemBuilder: (context, animation, lang, _) {
return SizeFadeTransition(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: animation,
child: _buildItem(lang),
);
},
updateItemBuilder: (context, animation, lang) {
return FadeTransition(
opacity: animation,
child: _buildItem(lang),
);
},
);
}
PreferredSize _buildAppBar(double padding, ThemeData theme, TextTheme textTheme) {
return PreferredSize(
preferredSize: Size.fromHeight(56 + padding),
child: Box(
height: 56 + padding,
width: double.infinity,
color: theme.accentColor,
elevation: 4,
shadowColor: Colors.black.withOpacity(0.2),
child: Column(
children: <Widget>[
SizedBox(height: padding),
Expanded(
child: Row(
children: <Widget>[
const BackButton(
color: Colors.white,
),
Expanded(
child: TextField(
autofocus: true,
controller: _controller,
textInputAction: TextInputAction.search,
style: textTheme.bodyText2?.copyWith(
color: Colors.white,
fontSize: 18,
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
hintText: 'Search for a language',
hintStyle: textTheme.bodyText2?.copyWith(
color: Colors.grey.shade200,
fontSize: 16,
),
),
),
),
AnimatedOpacity(
duration: const Duration(milliseconds: 350),
opacity: text.isEmpty ? 0.0 : 1.0,
child: IconButton(
icon: const Icon(
Icons.clear,
color: Colors.white,
),
onPressed: () => _controller.text = '',
),
),
],
),
),
],
),
),
);
}
Widget _buildNoLanguagesPlaceholder() {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const <Widget>[
Icon(
Icons.translate,
color: Colors.grey,
),
SizedBox(height: 16),
Text(
'No languages found!',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:implicitly_animated_reorderable_list_2/implicitly_animated_reorderable_list_2.dart';
import 'package:implicitly_animated_reorderable_list_2/transitions.dart';
class TestPage extends StatefulWidget {
const TestPage();
@override
State<StatefulWidget> createState() => TestPageState();
}
class TestPageState extends State<TestPage> {
static const maxLength = 1000;
List<Test> nestedList = List.generate(maxLength, (i) => Test(i));
Timer? _timer;
@override
void initState() {
super.initState();
// crazyListOperationMadness();
}
void crazyListOperationMadness() {
void assignNewList() {
nestedList = List.generate(Random().nextInt(maxLength), (i) => Test(i))..shuffle();
setState(() {});
}
_timer = Timer.periodic(
const Duration(milliseconds: 10),
(_) async {
assignNewList();
assignNewList();
nestedList = List.generate(Random().nextInt(maxLength), (i) => Test(i))
..shuffle();
setState(() {});
},
);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final textTheme = theme.textTheme;
return Scaffold(
appBar: AppBar(backgroundColor: Colors.amber),
body: Scrollbar(
child: ImplicitlyAnimatedReorderableList<Test>(
padding: const EdgeInsets.all(24),
items: nestedList,
areItemsTheSame: (oldItem, newItem) => oldItem == newItem,
onReorderFinished: (item, from, to, newList) {
setState(() {
nestedList
..clear()
..addAll(newList);
});
},
header: InkWell(
onTap: () {
if (_timer == null) {
crazyListOperationMadness();
} else {
_timer?.cancel();
_timer = null;
}
},
child: Container(
height: 120,
color: _timer == null ? Colors.red : Colors.yellow,
child: Center(
child: Text(
'Header',
style: textTheme.headline6?.copyWith(color: Colors.white),
),
),
),
),
footer: Container(
height: 120,
color: Colors.red,
child: Center(
child: Text(
'Footer',
style: textTheme.headline6?.copyWith(color: Colors.white),
),
),
),
itemBuilder: (context, itemAnimation, item, index) {
return Reorderable(
key: ValueKey(item),
builder: (context, dragAnimation, inDrag) => AnimatedBuilder(
animation: dragAnimation,
builder: (context, child) => Card(
elevation: 4,
// SizeFadeTransition clips, so use the
// Card as a parent to avoid the box shadow
// to be clipped.
child: SizeFadeTransition(
animation: itemAnimation,
child: Handle(
delay: const Duration(milliseconds: 600),
child: Container(
height: 120,
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('${item.key}'),
const Icon(Icons.menu),
],
),
),
),
),
),
),
);
},
),
),
);
}
}
class Test {
final int key;
Test(this.key);
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is Test && o.key == key;
}
@override
int get hashCode => key.hashCode;
}
export 'lang_page.dart';
export 'search_page.dart';
export 'test_page.dart';
import 'dart:math';
import 'package:flutter/material.dart';
enum ShadowDirection {
topLeft,
top,
topRight,
right,
bottomRight,
bottom,
bottomLeft,
left,
center,
}
class Box extends StatelessWidget {
final double borderRadius;
final double elevation;
final double? height;
final double? width;
final Border? border;
final BorderRadius? customBorders;
final EdgeInsets? margin;
final EdgeInsets? padding;
final Widget? child;
final Color color;
final Color shadowColor;
final List<BoxShadow>? boxShadows;
final VoidCallback? onTap;
final VoidCallback? onLongPress;
final VoidCallback? onDoubleTap;
final BoxShape boxShape;
final AlignmentGeometry? alignment;
final ShadowDirection shadowDirection;
final Color? splashColor;
final Duration? duration;
final BoxConstraints? constraints;
const Box({
Key? key,
this.child,
this.border,
this.color = Colors.transparent,
this.borderRadius = 0.0,
this.elevation = 0.0,
this.splashColor,
this.shadowColor = Colors.black12,
this.onTap,
this.onDoubleTap,
this.onLongPress,
this.height,
this.width,
this.margin,
this.customBorders,
this.alignment,
this.boxShadows,
this.constraints,
this.duration,
this.boxShape = BoxShape.rectangle,
this.shadowDirection = ShadowDirection.bottomRight,
this.padding = const EdgeInsets.all(0),
}) : super(key: key);
static const wrap = -1;
bool get circle => boxShape == BoxShape.circle;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final w = width;
final h = height;
final br = customBorders ??
BorderRadius.circular(
boxShape == BoxShape.rectangle
? borderRadius
: w != null
? w / 2.0
: h != null
? h / 2.0
: 0,
);
Widget content = Padding(
padding: padding ?? EdgeInsets.zero,
child: child,
);
if (boxShape == BoxShape.circle || (customBorders != null || borderRadius > 0.0)) {
content = ClipRRect(
borderRadius: br,
child: content,
);
}
if (onTap != null || onLongPress != null || onDoubleTap != null) {
content = Material(
color: Colors.transparent,
type: MaterialType.transparency,
shape: circle ? const CircleBorder() : RoundedRectangleBorder(borderRadius: br),
child: InkWell(
splashColor: splashColor ?? theme.splashColor,
highlightColor: theme.highlightColor,
hoverColor: theme.hoverColor,
focusColor: theme.focusColor,
customBorder:
circle ? const CircleBorder() : RoundedRectangleBorder(borderRadius: br),
onTap: onTap,
onLongPress: onLongPress,
onDoubleTap: onDoubleTap,
child: content,
),
);
}
final List<BoxShadow>? boxShadow = boxShadows ??
((elevation > 0 && (shadowColor.opacity > 0))
? [
BoxShadow(
color: shadowColor,
offset: _getShadowOffset(min(elevation / 5.0, 1.0)),
blurRadius: elevation,
spreadRadius: 0,
),
]
: null);
final boxDecoration = BoxDecoration(
color: color,
borderRadius: circle || br == BorderRadius.zero ? null : br,
shape: boxShape,
boxShadow: boxShadow,
border: border,
);
return duration != null
? AnimatedContainer(
height: h,
width: w,
margin: margin,
alignment: alignment,
duration: duration!,
decoration: boxDecoration,
constraints: constraints,
child: content,
)
: Container(
height: h,
width: w,
margin: margin,
alignment: alignment,
decoration: boxDecoration,
constraints: constraints,
child: content,
);
}
Offset _getShadowOffset(double ele) {
final ym = 5 * ele;
final xm = 2 * ele;
switch (shadowDirection) {
case ShadowDirection.topLeft:
return Offset(-1 * xm, -1 * ym);
case ShadowDirection.top:
return Offset(0, -1 * ym);
case ShadowDirection.topRight:
return Offset(xm, -1 * ym);
case ShadowDirection.right:
return Offset(xm, 0);
case ShadowDirection.bottomRight:
return Offset(xm, ym);
case ShadowDirection.bottom:
return Offset(0, ym);
case ShadowDirection.bottomLeft:
return Offset(-1 * xm, ym);
case ShadowDirection.left:
return Offset(-1 * xm, 0);
default:
return Offset.zero;
}
}
}
import 'package:flutter/material.dart';
class HighlightText extends StatefulWidget {
final TextStyle? activeStyle;
final TextStyle? style;
final String query;
final String text;
final TextAlign textAlign;
final TextDirection? textDirection;
final bool softWrap;
final TextOverflow overflow;
final double textScaleFactor;
final int? maxLines;
const HighlightText({
Key? key,
this.activeStyle,
this.style,
this.query = '',
this.text = '',
this.textAlign = TextAlign.start,
this.textDirection,
this.softWrap = true,
this.overflow = TextOverflow.ellipsis,
this.textScaleFactor = 1.0,
this.maxLines,
}) : super(key: key);
@override
_HighlightTextState createState() => _HighlightTextState();
}
class _HighlightTextState extends State<HighlightText> {
TextStyle get style => widget.style ?? Theme.of(context).textTheme.bodyText2!;
TextStyle get activeStyle =>
widget.activeStyle ?? style.copyWith(fontWeight: FontWeight.bold);
@override
Widget build(BuildContext context) {
final idxs = getQueryHighlights(widget.text, widget.query);
return RichText(
textAlign: widget.textAlign,
maxLines: widget.maxLines,
overflow: widget.overflow,
softWrap: widget.softWrap,
textDirection: widget.textDirection,
textScaleFactor: widget.textScaleFactor,
text: TextSpan(
children: idxs.map((idx) {
return TextSpan(
text: widget.text.substring(idx.first, idx.second),
style: idx.third ? activeStyle : style,
);
}).toList(),
),
);
}
}
String replaceLast(String source, String matcher, String replacement) {
final index = source.lastIndexOf(matcher);
return source.replaceRange(index, index + matcher.length, replacement);
}
List<Triplet<int, int, bool>> getQueryHighlights(String text, String query) {
final t = text.toLowerCase();
final q = query.toLowerCase();
if (t.isEmpty || q.isEmpty || !t.contains(q)) return [Triplet(0, t.length, false)];
List<Triplet<int, int, bool>> idxs = [];
var w = t;
do {
final i = w.lastIndexOf(q);
final e = i + q.length;
if (i != -1) {
w = replaceLast(w, q, '');
idxs.insert(0, Triplet(i, e, true));
}
} while (w.contains(q));
if (idxs.isEmpty) {
idxs.add(Triplet(0, t.length, false));
} else {
final List<Triplet<int, int, bool>> result = [];
Triplet<int, int, bool>? last;
for (final idx in idxs) {
final isLast = idx == idxs.last;
if (last == null) {
if (idx.first == 0) {
result.add(idx);
} else {
result..add(Triplet(0, idx.first, false))..add(idx);
}
} else if (last.second == idx.first) {
result.add(idx);
} else {
result..add(Triplet(last.second, idx.first, false))..add(idx);
}
if (isLast && idx.second != t.length) {
result.add(Triplet(idx.second, t.length, false));
}
last = idx;
}
idxs = result;
}
return idxs;
}
class Triplet<A, B, C> {
A first;
B second;
C third;
Triplet(
this.first,
this.second,
this.third,
);
Triplet copyWith({
A? first,
B? second,
C? third,
}) {
return Triplet(
first ?? this.first,
second ?? this.second,
third ?? this.third,
);
}
@override
String toString() => 'Triple first: $first, second: $second, third: $third';
@override
bool operator ==(Object o) {
return o is Triplet && o.first == first && o.second == second && o.third == third;
}
@override
int get hashCode {
return hashList([
first,
second,
third,
]);
}
}
const english = Language(
englishName: 'English',
nativeName: 'English',
);
const french = Language(
englishName: 'French',
nativeName: 'Français',
);
const german = Language(
englishName: 'German',
nativeName: 'Deutsch',
);
const spanish = Language(
englishName: 'Spanish',
nativeName: 'Español',
);
const chinese = Language(
englishName: 'Chinese',
nativeName: '中文',
);
const danish = Language(
englishName: 'Danish',
nativeName: 'Dansk',
);
const hindi = Language(
englishName: 'Hindi',
nativeName: 'हिंदी',
);
const afrikaans = Language(
englishName: 'Afrikaans',
nativeName: 'Afrikaans',
);
const portuguese = Language(
englishName: 'Portuguese',
nativeName: 'Português',
);
const List<Language> languages = [
english,
french,
german,
spanish,
chinese,
danish,
hindi,
afrikaans,
portuguese,
];
class Language {
final String englishName;
final String nativeName;
const Language({
required this.englishName,
required this.nativeName,
});
@override
String toString() => 'Language englishName: $englishName, nativeName: $nativeName';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is Language && o.englishName == englishName && o.nativeName == nativeName;
}
@override
int get hashCode => englishName.hashCode ^ nativeName.hashCode;
}
export 'box.dart';
export 'highlight_text.dart';
export 'languages.dart';
\ No newline at end of file
name: example
description: Example for how to use an ImplicitlyAnimatedReorderableList
publish_to: none
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_slidable: ^0.6.0-nullsafety.0
implicitly_animated_reorderable_list_2:
path: ../../implicitly_animated_reorderable_list_2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:example/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
Fore more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
-->
<base href="/">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="example">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>example</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('flutter-first-frame', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
{
"name": "example",
"short_name": "example",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
cmake_minimum_required(VERSION 3.15)
project(example LANGUAGES CXX)
set(BINARY_NAME "example")
cmake_policy(SET CMP0063 NEW)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Configure build options.
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTICONFIG)
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
CACHE STRING "" FORCE)
else()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
endif()
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
# Use Unicode for all projects.
add_definitions(-DUNICODE -D_UNICODE)
# Compilation settings that should be applied to most targets.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_17)
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
target_compile_options(${TARGET} PRIVATE /EHsc)
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
endfunction()
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
# Flutter library and tool build rules.
add_subdirectory(${FLUTTER_MANAGED_DIR})
# Application build
add_subdirectory("runner")
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# Support files are copied into place next to the executable, so that it can
# run in place. This is done instead of making a separate bundle (as on Linux)
# so that building and running from within Visual Studio will work.
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
# Make the "install" step default, as it's required to run.
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
CONFIGURATIONS Profile;Release
COMPONENT Runtime)
cmake_minimum_required(VERSION 3.15)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
# === Flutter Library ===
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"flutter_export.h"
"flutter_windows.h"
"flutter_messenger.h"
"flutter_plugin_registrar.h"
"flutter_texture_registrar.h"
)
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
add_dependencies(flutter flutter_assemble)
# === Wrapper ===
list(APPEND CPP_WRAPPER_SOURCES_CORE
"core_implementations.cc"
"standard_codec.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
"plugin_registrar.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
list(APPEND CPP_WRAPPER_SOURCES_APP
"flutter_engine.cc"
"flutter_view_controller.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
# Wrapper sources needed for a plugin.
add_library(flutter_wrapper_plugin STATIC
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_PLUGIN}
)
apply_standard_settings(flutter_wrapper_plugin)
set_target_properties(flutter_wrapper_plugin PROPERTIES
POSITION_INDEPENDENT_CODE ON)
set_target_properties(flutter_wrapper_plugin PROPERTIES
CXX_VISIBILITY_PRESET hidden)
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
target_include_directories(flutter_wrapper_plugin PUBLIC
"${WRAPPER_ROOT}/include"
)
add_dependencies(flutter_wrapper_plugin flutter_assemble)
# Wrapper sources needed for the runner.
add_library(flutter_wrapper_app STATIC
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_APP}
)
apply_standard_settings(flutter_wrapper_app)
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
target_include_directories(flutter_wrapper_app PUBLIC
"${WRAPPER_ROOT}/include"
)
add_dependencies(flutter_wrapper_app flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
${CPP_WRAPPER_SOURCES_APP}
${PHONY_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
windows-x64 $<CONFIG>
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_PLUGIN}
${CPP_WRAPPER_SOURCES_APP}
)
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void RegisterPlugins(flutter::PluginRegistry* registry) {
}
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter/plugin_registry.h>
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment