import 'dart:math';
import 'package:flutter/material.dart';
import 'package:freestyle_speed_dial/freestyle_speed_dial.dart';
import 'package:tuple/tuple.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color.fromARGB(255, 18, 32, 47),
materialTapTargetSize: MaterialTapTargetSize.padded),
home: const ExamplePage());
}
}
class ExamplePage extends StatelessWidget {
const ExamplePage({super.key});
@override
Widget build(BuildContext context) {
final List<double> positions = [-1, 1];
const double verticalPosition = -1.75;
return Scaffold(
body: Center(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(
horizontal: min(200, MediaQuery.of(context).size.width / 3),
vertical: 200),
child: Wrap(spacing: 200, runSpacing: 200, children: [
// Example 6 (Vertical Slide-In-Place With Labels):
// Advanced speed dial where every sub-button/item has an additional label.
// Both the item and the label start animating from their target position.
SpeedDialBuilder(
buttonBuilder: (context, isActive, toggle) =>
FloatingActionButton(
onPressed: toggle,
child: AnimatedRotation(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOutCubicEmphasized,
turns: isActive ? 0.125 : 0,
child: const Icon(Icons.add))),
reverse: true,
itemBuilder: (context,
Tuple3<IconData, String, LayerLink> item,
i,
animation) {
final offsetAnimation = Tween<Offset>(
begin: Offset.zero,
end: Offset(positions[i], verticalPosition),
).animate(animation);
return SlideTransition(
position: offsetAnimation,
child: FadeTransition(
opacity: animation,
child: CompositedTransformTarget(
link: item.item3,
child: FloatingActionButton.small(
onPressed: () {},
child: Icon(item.item1),
),
)));
},
secondaryItemBuilder: (context,
Tuple3<IconData, String, LayerLink> item,
i,
animation) {
return CompositedTransformFollower(
link: item.item3,
child: FadeTransition(
opacity: animation,
child: Card(
margin: const EdgeInsets.only(top: 50),
child: Padding(
padding: const EdgeInsets.all(5),
child: Text(item.item2),
)))
);
},
items: [
// You can also define and use your own container class
// if you don't want to use the tuple package.
Tuple3<IconData, String, LayerLink>(
Icons.arrow_upward, 'Out', LayerLink()),
Tuple3<IconData, String, LayerLink>(
Icons.arrow_downward, 'In', LayerLink())
]),
]))));
}
}
I managed to put it under the FAB but im not sure if this is the right approach, also I have tried combinations off modifying targetAnchor and followerAnchor to try to align it but I have not been able to achieve the design: