xcframework pod lib lint fail - cocoapods

I created an xcframework, this xcframework uses a mix of oc and swift, and dependency on the oc third-party library and the swift third-party library, I want to publish it to the cocoapods , but there are always errors during verification, I use this command for verification
pod lib lint --verbose --allow-warnings --no-clean, but failed.
Undefined symbols for architecture x86_64:
"enum case for SwiftEntryKit.EKAttributes.Position.top(SwiftEntryKit.EKAttributes.Position.Type) -> SwiftEntryKit.EKAttributes.Position", referenced from:
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.Position.bottom(SwiftEntryKit.EKAttributes.Position.Type) -> SwiftEntryKit.EKAttributes.Position", referenced from:
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.PositionConstraints.SafeArea.overridden(SwiftEntryKit.EKAttributes.PositionConstraints.SafeArea.Type) -> SwiftEntryKit.EKAttributes.PositionConstraints.SafeArea", referenced from:
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.RoundCorners.bottom(SwiftEntryKit.EKAttributes.RoundCorners.Type) -> (CoreGraphics.CGFloat) -> SwiftEntryKit.EKAttributes.RoundCorners", referenced from:
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.RoundCorners.top(SwiftEntryKit.EKAttributes.RoundCorners.Type) -> (CoreGraphics.CGFloat) -> SwiftEntryKit.EKAttributes.RoundCorners", referenced from:
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.BackgroundStyle.color(SwiftEntryKit.EKAttributes.BackgroundStyle.Type) -> (SwiftEntryKit.EKColor) -> SwiftEntryKit.EKAttributes.BackgroundStyle", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.PositionConstraints.Edge.ratio(SwiftEntryKit.EKAttributes.PositionConstraints.Edge.Type) -> (CoreGraphics.CGFloat) -> SwiftEntryKit.EKAttributes.PositionConstraints.Edge", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.SwiftEntryKit.RollbackWindow.main(SwiftEntryKit.SwiftEntryKit.RollbackWindow.Type) -> SwiftEntryKit.SwiftEntryKit.RollbackWindow", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.Scroll.disabled(SwiftEntryKit.EKAttributes.Scroll.Type) -> SwiftEntryKit.EKAttributes.Scroll", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.Animation.Translate.AnchorPosition.automatic(SwiftEntryKit.EKAttributes.Animation.Translate.AnchorPosition.Type) -> SwiftEntryKit.EKAttributes.Animation.Translate.AnchorPosition", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.Position.center(SwiftEntryKit.EKAttributes.Position.Type) -> SwiftEntryKit.EKAttributes.Position", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.EKAttributes.PositionConstraints.Edge.intrinsic(SwiftEntryKit.EKAttributes.PositionConstraints.Edge.Type) -> SwiftEntryKit.EKAttributes.PositionConstraints.Edge", referenced from:
function signature specialization <Arg[1] = Dead> of static SASContractSDK.Overlay.entryAlert(__C.UIView) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheet(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[7] = Dead> of static SASContractSDK.Overlay.entrySheetHide(_: __C.UIView, top: Swift.Bool, offset: CoreGraphics.CGFloat, round: CoreGraphics.CGFloat, bgcolor: Swift.Int, dismiss: Swift.Bool, cancelled: (() -> ())?) -> () in SASContractSDK(Overlay.o)
function signature specialization <Arg[2] = Dead> of static SASContractSDK.Overlay.entryAlert(_: __C.UIView, dismiss: Swift.Bool) -> () in SASContractSDK(Overlay.o)
"enum case for SwiftEntryKit.SwiftEntryKit.EntryDismissalDescriptor.all(SwiftEntryKit.SwiftEntryKit.EntryDismissalDescriptor.Type) -> SwiftEntryKit.SwiftEntryKit.EntryDismissalDescriptor", referenced from:
static SASContractSDK.Overlay.entryHide((() -> ())?) -> () in SASContractSDK(Overlay.o)
#objc static SASContractSDK.Overlay.entryHide((() -> ())?) -> () in SASContractSDK(Overlay.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Why is this happening and how should I fix it
This is my project address:
https://github.com/AdamShi/SASContractSDK

I have solved this problem. The reason is that I set s.static_framework = true in the podspec file, which generates a static library, so the verification can only be passed by adding --skip-import-validation ; So in the end I deleted s.static_framework = true, no longer use static library, but use dynamic library, you don't need --skip-import-validation, you can pass the verification directly.
To sum up, it is best to generate a dynamic library, which can pass the verification without adding --skip-import-validation; if it is a static library, you need --skip-import-validation to pass the verification

Related

Flutter Deleting a record through the API

I am using a Laravel Api and a Flutter app as the client. This is a basic CRUD app and i was able to update the records through the API but when it comes to deleting a record, an exception is thrown and i am unable to findout the issue.
Laravel 8 App looks like this
routes\api.php
Route::apiResource('categories', \App\Http\Controllers\Api\CategoryController::class);
app\Http\Controllers\Api\CategoryController.php
public function destroy(Category $category)
{
$category->delete();
return response()->noContent();
}
Flutter App looks like this
lib\screens\categories.dart
import 'package:flutter/material.dart';
import 'package:demo_app/models/category.dart';
import 'package:demo_app/widgets/category_edit.dart';
import 'package:demo_app/providers/category_provider.dart';
import 'package:provider/provider.dart';
// import 'package:http/http.dart' as http;
class Categories extends StatefulWidget {
const Categories({super.key});
#override
CategoriesState createState() => CategoriesState();
}
class CategoriesState extends State<Categories> {
#override
Widget build(BuildContext context) {
final provider = Provider.of<CategoryProvider>(context);
List<Category> categories = provider.categories;
return Scaffold(
appBar: AppBar(
title: const Text('Categories'),
),
body: ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
Category category = categories[index];
return ListTile(
title: Text(category.name),
trailing:
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return CategoryEdit(category, provider.updateCategory);
});
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () => showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('confirmation'),
content: const Text('Are you sure you want to delete?'),
actions: [
TextButton(
onPressed: () => deleteCategory(provider.deleteCategory, category),
child: const Text('Confirm')
),
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel')
),
]
);
}
),
),
],
),
);
},
)
);
}
Future deleteCategory(Function callback, Category category) async{
await callback(category);
if (!mounted) return;
Navigator.pop(context);
}
}
lib\services\api.dart
// import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:demo_app/models/category.dart';
// import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ApiService{
ApiService();
final String baseUrl = 'http://flutter-api.test/api/';
Future<List<Category>> fetchCategories() async {
http.Response response =
await http.get(Uri.parse('${baseUrl}categories'));
List categories = jsonDecode(response.body);
return categories.map((category) => Category.fromJson(category)).toList();
}
Future <Category> updateCategory(Category category) async {
// String uri = '${baseUrl}categories/$category.id';
String uri = '${baseUrl}categories/${category.id}';
http.Response response = await http.put(Uri.parse(uri),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
},
body: jsonEncode({'name': category.name}));
if(response.statusCode != 200){
throw Exception('Error happened on update');
}
return Category.fromJson(jsonDecode(response.body));
}
Future<void> deleteCategory(id) async {
String uri = '${baseUrl}categories/$id';
http.Response response = await http.delete(Uri.parse(uri));
if(response.statusCode != 204){
throw Exception('Error happened on delete');
}
}
}
lib\providers\category_provider.dart
// import 'dart:io';
import 'package:demo_app/models/category.dart';
import 'package:flutter/material.dart';
import 'package:demo_app/services/api.dart';
class CategoryEdit extends StatefulWidget {
final Category category;
final Function categoryCallback;
const CategoryEdit(this.category, this.categoryCallback, {Key? key}) : super(key: key);
#override
CategoryEditState createState() => CategoryEditState();
}
class CategoryEditState extends State<CategoryEdit> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final categoryNameController = TextEditingController();
ApiService apiService = ApiService();
String errorMessage = '';
#override
void initState(){
categoryNameController.text = widget.category.name;
super.initState();
}
#override
Widget build(BuildContext context){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(children: <Widget>[
TextFormField(
onChanged: (text) => setState(() => errorMessage = ''),
controller: categoryNameController,
validator: (String? value) {
if (value!.isEmpty) {
return 'Enter category name';
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Category Name',
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ElevatedButton(
child: const Text('Save'),
onPressed: () => saveCategory(context),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red
),
child: const Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
],
),
Text(errorMessage, style: const TextStyle(color: Colors.red),)
]
)
)
);
}
Future saveCategory(BuildContext context) async {
final form = _formKey.currentState;
if(!form!.validate())
{
return;
}
widget.category.name = categoryNameController.text;
await widget.categoryCallback(widget.category);
if (!mounted) return;
Navigator.pop(context);
}
}
This is the exception i get
flutter: Exception: Error happened on delete
It returns the Error Code 500 and i was able to sort the error from the Server side

Hero animation with gallery flicker Flutter

I'm trying to create a basic Hero animation between a gallery grid view page (using photo manager plugin) and a detail page. When the hero animation is done both back and forward, the picture is flickering .
Here is the example I've made :
The full code runnable :
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:photo_manager/photo_manager.dart';
void main() {
runApp(const TestApp());
}
class TestApp extends StatefulWidget {
const TestApp({Key? key}) : super(key: key);
#override
State<TestApp> createState() => _TestAppState();
}
class _TestAppState extends State<TestApp> {
final List<AssetEntity> assetsList = [];
bool granted = false;
void loadAssets() async {
granted = await PhotoManager.requestPermission();
if (granted) {
FilterOptionGroup option = FilterOptionGroup()
..addOrderOption(const OrderOption(
type: OrderOptionType.createDate,
asc: false,
));
final albums = await PhotoManager.getAssetPathList(filterOption: option, type: RequestType.image);
print("albums : $albums");
if (albums.isNotEmpty) {
var alb = albums.where((element) {
return element.name == 'Test';
});
var album = alb.first;
// Now that we got the album, fetch all the assets it contains
List<AssetEntity> currentList =
await album.getAssetListRange(start: 0, end: 200);
// Update the state and notify UI
assetsList.clear();
assetsList.addAll(currentList);
}
setState(() {});
}
}
#override
void initState() {
loadAssets();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: granted
? _gridView()
: Center(
child: Container(
color: Colors.blue,
width: 200,
height: 200,
child: TextButton(
onPressed: () async {
granted = await PhotoManager.requestPermission();
setState(() {});
},
child: const Text(
"Ask permission",
style: TextStyle(color: Colors.white),
),
)),
)),
);
}
Widget _gridView() {
return GridView.builder(
itemCount: assetsList.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (context, index) {
return Hero(
createRectTween: (Rect? begin, Rect? end) {
RectTween _rectTween = RectTween(begin: begin, end: end);
return _rectTween;
},
tag: assetsList[index].id,
child: GalleryThumbnail(
asset: assetsList[index],
onTap: (bytes) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return DetailsPage(asset: assetsList[index], bytes: bytes);
}));
},
));
});
}
}
class GalleryThumbnail extends StatelessWidget {
final AssetEntity asset;
final ValueChanged<Uint8List> onTap;
const GalleryThumbnail({Key? key, required this.asset, required this.onTap})
: super(key: key);
#override
Widget build(BuildContext context) {
return FutureBuilder<Uint8List?>(
future: Platform.isIOS
? asset.thumbDataWithOption(
ThumbOption.ios(
width: 500,
height: 500,
deliveryMode: DeliveryMode.opportunistic,
resizeMode: ResizeMode.fast,
resizeContentMode: ResizeContentMode.fit,
quality: 100
// resizeContentMode: ResizeContentMode.fill,
),
)
: asset.thumbDataWithSize(250, 250),
builder: (_, snapshot) {
final bytes = snapshot.data;
if (snapshot.hasError) {
return Container();
}
// If we have no data
if (bytes == null) return Container();
// If there's data, display it as an image
return GestureDetector(
onTap: () {
onTap(bytes);
},
child: Image.memory(bytes, fit: BoxFit.cover,gaplessPlayback: true,));
},
);
}
}
class DetailsPage extends StatefulWidget {
final AssetEntity asset;
final Uint8List bytes;
const DetailsPage({Key? key, required this.asset, required this.bytes})
: super(key: key);
#override
_DetailsPageState createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
late ImageProvider _imageProvider;
Future<void> loadFile() async {
try {
File? file = await widget.asset.file;
if (file == null) return;
_imageProvider = Image.file(file).image;
setState(() {});
} catch (e) {
print("error to load file : " + e.toString());
}
}
#override
void initState() {
_imageProvider = Image.memory(widget.bytes).image;
loadFile();
super.initState();
}
#override
Widget build(BuildContext context) {
double ratio = widget.asset.height / widget.asset.width;
return Scaffold(
body: Stack(
children: [
Hero(
createRectTween: (Rect? begin, Rect? end) {
RectTween _rectTween = RectTween(begin: begin, end: end);
return _rectTween;
},
tag: widget.asset.id,
child: Center(
child: Image(image: _imageProvider,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height*ratio,
gaplessPlayback: true),
),
),
const SafeArea(
child: Padding(
padding: EdgeInsets.all(8.0),
child: BackButton(),
)),
],
),
);
}
}
I've implemented hero animation somewhere else in my project and I'm not getting this behavior where as here I do.
Why this is happening and how to correct this ?
Add
transitionOnUserGestures: true,
to Hero() widget in current & next page
This happens because the Hero of the image thumbail wraps the FutureBuilder, and then the future triggers again during the animation, wraps the Image instead of the FutureBuilder.

Flutter: How I can fix page controller animation error

I have a page containing a page view slider with a page controller and I get this error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception:
Looking up a deactivated widget's ancestor is unsafe. E/flutter (
7013): At this point the state of the widget's element tree is no
longer stable. E/flutter ( 7013): To safely refer to a widget's
ancestor in its dispose() method, save a reference to the ancestor by
calling dependOnInheritedWidgetOfExactType() in the widget's
didChangeDependencies() method.
I'm trying to solve it but I can't and I don't know the reason for this error.
This my code which I use:
var pageController = PageController(initialPage: 0);
var pageViewModelData = List<PageViewData>();
Timer sliderTimer;
var currentShowIndex = 0;
#override
void initState() {
pageViewModelData.add(PageViewData(
titleText: 'Cape Town',
subText: 'Extraordinary five-star\noutdoor activites',
assetsImage: 'assets/images/explore_2.jpg',
));
pageViewModelData.add(PageViewData(
titleText: 'Find best deals',
subText: 'Extraordinary five-star\noutdoor activites',
assetsImage: 'assets/images/explore_1.jpg',
));
pageViewModelData.add(PageViewData(
titleText: 'Find best deals',
subText: 'Extraordinary five-star\noutdoor activites',
assetsImage: 'assets/images/explore_3.jpg',
));
sliderTimer = Timer.periodic(Duration(seconds: 4), (timer) {
if (currentShowIndex == 0) {
pageController.animateTo(MediaQuery.of(context).size.width, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 1) {
pageController.animateTo(MediaQuery.of(context).size.width * 2, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 2) {
pageController.animateTo(0, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
}
});
super.initState();
}
#override
void dispose() {
sliderTimer?.cancel();
super.dispose();
}
I get the error start from this line:
MediaQuery.of(context).size.width
Can anyone tell me the reason for this issue! Thanks
You can copy paste run full code below
Value of MediaQuery.of(context).size.width is not not ready in initState()
You can use WidgetsBinding.instance.addPostFrameCallback
code snippet
WidgetsBinding.instance.addPostFrameCallback((_) {
print('width ${MediaQuery.of(context).size.width}');
sliderTimer = Timer.periodic(Duration(seconds: 4), (timer) {
if (currentShowIndex == 0) {
pageController.animateTo(MediaQuery.of(context).size.width, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 1) {
pageController.animateTo(MediaQuery.of(context).size.width * 2, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 2) {
pageController.animateTo(0, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
}
});
});
working demo
output
I/flutter ( 1876): width 411.42857142857144
full code
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: 'Flutter Tutorial',
home: new AnimatedIconExample(),
));
}
class AnimatedIconExample extends StatefulWidget {
#override
_AnimatedIconExampleState createState() => _AnimatedIconExampleState();
}
class _AnimatedIconExampleState extends State<AnimatedIconExample>
with SingleTickerProviderStateMixin {
PageController pageController = PageController();
AnimationController controller;
Timer sliderTimer;
var currentShowIndex = 0;
#override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(seconds: 1));
WidgetsBinding.instance.addPostFrameCallback((_) {
print('width ${MediaQuery.of(context).size.width}');
sliderTimer = Timer.periodic(Duration(seconds: 4), (timer) {
if (currentShowIndex == 0) {
pageController.animateTo(MediaQuery.of(context).size.width, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 1) {
pageController.animateTo(MediaQuery.of(context).size.width * 2, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
} else if (currentShowIndex == 2) {
pageController.animateTo(0, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
}
});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: GestureDetector(
child: Center(
child: AnimatedIcon(
icon: AnimatedIcons.menu_close, progress: controller),
),
onTap: () {
controller.reverse();
pageController.animateToPage(0,
duration: Duration(seconds: 1), curve: Curves.linear);
},
),
title: Text("Animated PageView Controller")),
body: PageView(
controller: pageController,
scrollDirection: Axis.vertical,
children: <Widget>[
buildPage0(),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.yellow),
Container(color: Colors.pink),
],
),
);
}
show(int page) {
controller.forward();
pageController.animateToPage(page,
duration: Duration(seconds: 1), curve: Curves.linear);
}
Container buildPage0() {
return Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ListTile(onTap: () => show(1), title: Center(child: Text("Green"))),
ListTile(onTap: () => show(2), title: Center(child: Text("Blue"))),
ListTile(onTap: () => show(3), title: Center(child: Text("Yellow"))),
ListTile(onTap: () => show(4), title: Center(child: Text("Pink"))),
],
),
);
}
}

Animated FloatingActionButton in Stack don't trigger onPressed event

I've created an animated Floating Action Button (FAB) menu:
Main FAB which spawns other FABs when clicked.
It is based on several online tutorials.
Works fine besides one major issue:
The spawned FABs don't trigger an onPressed event.
Seems like there's a problem with the combination of transform animation and the stack widget (which the FABs are children of).
Works fine if I replace the stack with a row...
Seems like the issue was addressed here, but without a proper solution:
FloatingActionButton onPressed not triggering
Here's the complete code for that FAB menu.
Just supply it a list with buttons data, similar to this one:
List<Map<String, dynamic>> _buttonsData = [
{'color': Colors.green ,'icon': Icons.stop},
{'color': Colors.blue ,'icon': Icons.subway},
{'color': Colors.green ,'icon': Icons.add},];
FancyFab2(_buttonsData, null)
The code:
import 'package:flutter/material.dart';
class FancyFab extends StatefulWidget {
FancyFab(this._buttonsData, this._onSelected);
final List<Map<String, dynamic>> _buttonsData;
final ValueChanged<int> _onSelected;
#override
createState() => FancyFabState(_buttonsData, _onSelected);
}
class FancyFabState extends State<FancyFab> with SingleTickerProviderStateMixin {
final List<Map<String, dynamic>> _buttonsData;
final ValueChanged<int> _onSelected;
// state vars
AnimationController _controller;
Animation <double> _transform;
bool _isOpened = false;
FancyFabState(this._buttonsData, this._onSelected);
#override
void initState() {
// call base
super.initState();
// _controller
_controller = AnimationController(
duration: Duration(milliseconds: 100),
vsync: this
);
_transform = Tween<double>(
begin: 0.0,
end: -64.0,
).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn
),
);
}
#override
void dispose() {
// controller
_controller.dispose();
// call base
super.dispose();
}
#override
Widget build(BuildContext context) {
return _buildFab(_controller);
}
Widget _buildFab(AnimationController controller) {
return AnimatedBuilder(
animation: controller,
builder: (context, builder) {
return Stack(
children: List.generate(_buttonsData.length, (index) => _buildStackWidget(context, index))
);
}
);
}
Widget _buildStackWidget(BuildContext context, int index) {
Map<String, dynamic> buttonData = _buttonsData[index];
if (index == _buttonsData.length - 1)
return _buildMenuButton(index, buttonData);
else
return _buildMenuItem(index, buttonData);
}
Widget _buildMenuItem(int index, Map<String, dynamic> buttonData) {
return Transform.translate(
offset: Offset((1 + index) * _transform.value, 0.0),
child: FloatingActionButton(
heroTag: 100 + index,
backgroundColor: buttonData['color'],
//onPressed: () => _onSelected(index),
onPressed: () => print('click'),
child: Icon(buttonData['icon']),
),
);
}
Widget _buildMenuButton(int index, Map<String, dynamic> buttonData) {
return FloatingActionButton(
heroTag: 200,
backgroundColor: buttonData['color'],
onPressed: _toggle,
child: Icon(buttonData['icon']),
);
}
void _toggle() {
print('toggle');
_isOpened = !_isOpened;
if (true == _isOpened)
_controller.forward();
else
_controller.reverse();
}
}
That's because you are moving the items outside your Stack so you can't hitTest on those positions.
I modified a few lines of your code to make it works :
Add constraints to your Stack (you can use SizedBox also) , I'm using container to set a different color of background.
Widget _buildFab(AnimationController controller) {
return AnimatedBuilder(
animation: controller,
builder: (context, builder) {
return Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: Colors.blueGrey,
child: Stack(
children: List.generate(_buttonsData.length,
(index) => _buildStackWidget(context, index))),
);
});
}
Center your items
Widget _buildMenuItem(int index, Map<String, dynamic> buttonData) {
return Center(
child: Transform.translate(
offset: Offset((1 + index) * _transform.value, 0.0),
child: FloatingActionButton(
heroTag: 100 + index,
backgroundColor: buttonData['color'],
//onPressed: () => _onSelected(index),
onPressed: () => print('click'),
child: Icon(buttonData['icon']),
),
),
);
}
Widget _buildMenuButton(int index, Map<String, dynamic> buttonData) {
return Center(
child: FloatingActionButton(
heroTag: 200,
backgroundColor: buttonData['color'],
onPressed: _toggle,
child: Icon(buttonData['icon']),
),
);
}

Repeating Animation and Adjustments in Flutter

I'm trying to clone the timer of the app I use when I workout: Strong. So far, I've managed to implement all the main features and animations (which aren't many). I know my code is messy and there's probably better ways to implement what I'm trying to do if there are any suggestions on that they're also appreciated. I'm having two problems with my application. 1. When the timer starts I get the following error:
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
flutter: The following NoSuchMethodError was thrown building Peinture(dirty, state: _PeintureState#82e34):
flutter: The getter 'inMilliseconds' was called on null.
flutter: Receiver: null
flutter: Tried calling: inMilliseconds
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
flutter: #1 _PeintureState.build (package:workout_timer/main.dart:241:72)
flutter: #2 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
flutter: #3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
flutter: #4 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #5 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #6 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #7 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #8 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #10 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #11 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #12 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #13 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #14 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #15 StatelessElement.update (package:flutter/src/widgets/framework.dart:3781:5)
flutter: #16 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #17 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4585:32)
flutter: #18 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4975:17)
flutter: #19 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #20 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #21 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #22 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #23 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #24 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #25 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #26 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #27 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #28 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4585:32)
flutter: #29 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4975:17)
flutter: #30 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #31 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #32 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #33 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #34 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #35 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #36 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #37 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #38 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #39 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #40 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #41 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #42 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #43 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #44 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #45 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #46 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #47 StatelessElement.update (package:flutter/src/widgets/framework.dart:3781:5)
flutter: #48 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #49 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #50 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #51 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #52 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #53 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #54 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #55 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #56 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #57 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #58 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #59 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #60 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #61 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #62 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #63 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #64 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #65 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #66 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #67 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #68 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #69 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #70 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #71 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #72 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #73 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
flutter: #74 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
flutter: #75 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
flutter: #76 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #77 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #78 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
flutter: #79 _invoke (dart:ui/hooks.dart:154:13)
flutter: #80 _drawFrame (dart:ui/hooks.dart:143:3)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
Which I've made sure to check I'm not getting anything null but I still get it.
And the second.
When the timer finishes I get the following error:
[VERBOSE-2:shell.cc(184)] Dart Error: Unhandled exception:
setState() called after dispose(): _TimeState#10749(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/framewo<…>
And when I try to start a timer again I get this:
flutter: Another exception was thrown: NoSuchMethodError: The getter 'inMilliseconds' was called on null.
Here's is my code:
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttery/layout.dart';
Duration time;
Duration previousTime;
Duration currentTime;
AnimationController timeController, circleController;
bool reverse = false;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
Stopwatch stopwatch = new Stopwatch();
#override
void initState() {
super.initState();
timeController = new AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
timeController.addListener(() {
setState(() {});
});
}
#override
void dispose() {
timeController.dispose();
circleController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: Opacity(
opacity: timeController.value != null ? 1.0 - timeController.value : 1.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 1);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("1:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 2);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("2:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 3);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("3:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 5);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("5:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
],
),
),
),
Center(
child: Opacity(
opacity: timeController.value != null ? 0.0 + timeController.value : 0.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: time != null ? buildTimes(stopwatch, time, previousTime) : []
),
),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Color.fromRGBO(224, 245, 255, 1.0), animate: false)
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Colors.blue, animate: true)
)
],
),
);
}
}
List<Widget> buildTimes(stopwatch, time, previousTime) {
return [
Time(stopwatch: stopwatch, time: time),
Text(
previousTime != null
? previousTime.toString().substring(3, 7)
: "",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30.0,
color: Colors.black54),
),
];
}
class Peinture extends StatefulWidget {
final Color color;
final bool animate;
Peinture({this.color, this.animate});
#override
_PeintureState createState() => _PeintureState(color: color, animate: animate);
}
class _PeintureState extends State<Peinture> {
Timer timer;
Color color;
bool animate;
_PeintureState({this.color, this.animate}) {
timer = Timer.periodic(Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
setState(() {
if (currentTime != null) {
print(currentTime.inMilliseconds);
if (currentTime.inMilliseconds <= 0) {
reverse = true;
timeController.reverse();
previousTime = null;
time = previousTime;
currentTime = time;
reverse = false;
}
}
});
}
#override
Widget build(BuildContext context) {
return Opacity(
opacity: reverse == false ? 1.0 : timeController.value,
child: CustomPaint(
painter: CirclePainter(
radius: 150.0,
thickness: 8.0,
color: color,
startAngle: -pi / 2,
endAngle: time != null && animate ? -pi / 2 + (((currentTime.inMilliseconds - circleController.value)) / 60000) * (2*pi) : -pi / 2 + (2 * pi) - (0 / (2*pi)),
),
),
);
}
}
class CirclePainter extends CustomPainter {
final double radius;
final double thickness;
final Color color;
final double startAngle;
final double endAngle;
final Paint circlePaint;
CirclePainter({this.radius, this.thickness, this.color, this.startAngle, this.endAngle})
: circlePaint = new Paint()
..color = color
..strokeWidth = thickness
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
#override
void paint(Canvas canvas, Size size) {
canvas.drawArc(Rect.fromLTWH(-radius, -radius, radius * 2, radius * 2),
startAngle, endAngle - startAngle, false, circlePaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class Time extends StatefulWidget {
final Duration time;
final Stopwatch stopwatch;
Time({this.stopwatch, this.time});
#override
_TimeState createState() => _TimeState(stopwatch: stopwatch, time: time);
}
class _TimeState extends State<Time> {
Timer timer;
Duration time;
Stopwatch stopwatch;
_TimeState({this.time, this.stopwatch}) {
timer = new Timer.periodic(new Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
if (stopwatch.isRunning) {
setState(() {
currentTime = time - stopwatch.elapsed;
});
}
}
#override
Widget build(BuildContext context) {
return Text(
currentTime != null ? currentTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 60.0, color: Colors.black87),
);
}
}
Thanks for the help and again any suggestions as to how you'd go about it would be appreciated.
Try this
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttery/layout.dart';
Duration time;
Duration previousTime;
Duration currentTime;
AnimationController timeController, circleController;
bool reverse = false;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
Stopwatch stopwatch = new Stopwatch();
#override
void initState() {
super.initState();
timeController = new AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
timeController.addListener(() {
setState(() {});
});
}
#override
void dispose() {
timeController.dispose();
circleController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: Opacity(
opacity: timeController.value != null
? 1.0 - timeController.value
: 1.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 1);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("1:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 2);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("2:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 3);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("3:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 5);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("5:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
],
),
),
),
Center(
child: Opacity(
opacity: timeController.value != null
? 0.0 + timeController.value
: 0.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: time != null
? buildTimes(stopwatch, time, previousTime)
: []),
),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(
color: Color.fromRGBO(224, 245, 255, 1.0), animate: false),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Colors.blue, animate: true),
)
],
),
);
}
}
List<Widget> buildTimes(stopwatch, time, previousTime) {
return [
Time(stopwatch: stopwatch, time: time),
Text(
previousTime != null ? previousTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 30.0, color: Colors.black54),
),
];
}
class Peinture extends StatefulWidget {
final Color color;
final bool animate;
Peinture({this.color, this.animate});
#override
_PeintureState createState() =>
_PeintureState(color: color, animate: animate);
}
class _PeintureState extends State<Peinture> {
Timer timer;
Color color;
bool animate;
_PeintureState({this.color, this.animate}) {
timer = Timer.periodic(Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
setState(() {
if (currentTime != null) {
if (currentTime.inMilliseconds <= 0) {
reverse = true;
timeController.reverse();
previousTime = null;
time = previousTime;
currentTime = time;
reverse = false;
}
}
});
}
#override
Widget build(BuildContext context) {
return Opacity(
opacity: reverse == false ? 1.0 : timeController.value,
child: CustomPaint(
painter: CirclePainter(
radius: 150.0,
thickness: 8.0,
color: color,
startAngle: -pi / 2,
endAngle: time != null && animate && currentTime != null
? -pi / 2 +
(((currentTime.inMilliseconds - circleController.value)) /
60000) *
(2 * pi)
: -pi / 2 + (2 * pi) - (0 / (2 * pi)),
),
),
);
}
}
class CirclePainter extends CustomPainter {
final double radius;
final double thickness;
final Color color;
final double startAngle;
final double endAngle;
final Paint circlePaint;
CirclePainter(
{this.radius, this.thickness, this.color, this.startAngle, this.endAngle})
: circlePaint = new Paint()
..color = color
..strokeWidth = thickness
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
#override
void paint(Canvas canvas, Size size) {
canvas.drawArc(Rect.fromLTWH(-radius, -radius, radius * 2, radius * 2),
startAngle, endAngle - startAngle, false, circlePaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class Time extends StatefulWidget {
final Duration time;
final Stopwatch stopwatch;
Time({this.stopwatch, this.time});
#override
_TimeState createState() => _TimeState(stopwatch: stopwatch, time: time);
}
class _TimeState extends State<Time> {
Timer timer;
Duration time;
Stopwatch stopwatch;
_TimeState({this.time, this.stopwatch}) {
timer = new Timer.periodic(new Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
if (stopwatch.isRunning) {
setState(() {
currentTime = time - stopwatch.elapsed;
});
}
}
#override
Widget build(BuildContext context) {
return Text(
currentTime != null ? currentTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 60.0, color: Colors.black87),
);
}
}

Resources