Skip to content

Commit

Permalink
Merge pull request rasitayaz#44 from rasitayaz/dev
Browse files Browse the repository at this point in the history
update to 3.1.0
  • Loading branch information
rasitayaz authored Dec 6, 2023
2 parents e354c41 + 960ab43 commit 389eaf4
Show file tree
Hide file tree
Showing 8 changed files with 498 additions and 199 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.1.0

* Improved the child bounce animation by adding a 3D tilt effect to it inspired by [Bounce](https://pub.dev/packages/bounce) package. Can be disabled by setting `childTiltEnabled` to `false` in `PieTheme`.
* Added `overlayStyle` to `PieTheme` to switch between the old and new overlay styles. `PieOverlayStyle.behind` (the old style) is used by default because the new one causes render issues in some cases.
* Other minor improvements and bug fixes.

## 3.0.0

* When a `PieMenu` activates, other gestures are now automatically cancelled. You no longer need to use `NeverScrollableScrollPhysics` to disable scrolling or to deactivate the functionality of your interactive menu child.
Expand Down
186 changes: 93 additions & 93 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,38 +68,47 @@ class _HomePageState extends State<HomePage> {

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'Flutter Pie Menu 🥧',
style: TextStyle(fontWeight: FontWeight.w600),
return PieCanvas(
theme: const PieTheme(
rightClickShowsMenu: true,
tooltipTextStyle: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
),
),
body: IndexedStack(
index: _navigationIndex,
children: const [
StylingPage(),
ListViewPage(),
AboutPage(),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _navigationIndex,
onTap: (index) => setState(() => _navigationIndex = index),
items: const [
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.palette),
label: 'Styling',
),
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.list),
label: 'ListView',
child: Scaffold(
appBar: AppBar(
title: const Text(
'Flutter Pie Menu 🥧',
style: TextStyle(fontWeight: FontWeight.w600),
),
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.circleInfo),
label: 'About',
),
],
),
body: IndexedStack(
index: _navigationIndex,
children: const [
StylingPage(),
ListViewPage(),
AboutPage(),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _navigationIndex,
onTap: (index) => setState(() => _navigationIndex = index),
items: const [
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.palette),
label: 'Styling',
),
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.list),
label: 'ListView',
),
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.circleInfo),
label: 'About',
),
],
),
),
);
}
Expand Down Expand Up @@ -358,75 +367,66 @@ class _ListViewPageState extends State<ListViewPage> {

@override
Widget build(BuildContext context) {
return PieCanvas(
theme: const PieTheme(
rightClickShowsMenu: true,
tooltipTextStyle: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
),
return ListView.separated(
padding: EdgeInsets.only(
top: spacing,
bottom: spacing,
left: MediaQuery.of(context).padding.left + spacing,
right: MediaQuery.of(context).padding.right + spacing,
),
child: ListView.separated(
padding: EdgeInsets.only(
top: spacing,
bottom: spacing,
left: MediaQuery.of(context).padding.left + spacing,
right: MediaQuery.of(context).padding.right + spacing,
),
physics: const BouncingScrollPhysics(),
itemCount: 16,
separatorBuilder: (context, index) => const SizedBox(height: spacing),
itemBuilder: (context, index) {
return SizedBox(
height: 200,
child: PieMenu(
onPressed: () {
context.showSnackBar(
'#$index — Long press or right click to show the menu',
);
},
actions: [
PieAction(
tooltip: const Text('Like'),
onSelect: () => context.showSnackBar('Like #$index'),
child: const FaIcon(FontAwesomeIcons.solidHeart),
),
PieAction(
tooltip: const Text('Comment'),
onSelect: () => context.showSnackBar('Comment #$index'),
child: const FaIcon(FontAwesomeIcons.solidComment),
),
PieAction(
tooltip: const Text('Save'),
onSelect: () => context.showSnackBar('Save #$index'),
child: const FaIcon(FontAwesomeIcons.solidBookmark),
),
PieAction(
tooltip: const Text('Share'),
onSelect: () => context.showSnackBar('Share #$index'),
child: const FaIcon(FontAwesomeIcons.share),
),
],
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'#$index',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 64,
),
physics: const BouncingScrollPhysics(),
itemCount: 16,
separatorBuilder: (context, index) => const SizedBox(height: spacing),
itemBuilder: (context, index) {
return SizedBox(
height: 200,
child: PieMenu(
onPressed: () {
context.showSnackBar(
'#$index — Long press or right click to show the menu',
);
},
actions: [
PieAction(
tooltip: const Text('Like'),
onSelect: () => context.showSnackBar('Like #$index'),
child: const FaIcon(FontAwesomeIcons.solidHeart),
),
PieAction(
tooltip: const Text('Comment'),
onSelect: () => context.showSnackBar('Comment #$index'),
child: const FaIcon(FontAwesomeIcons.solidComment),
),
PieAction(
tooltip: const Text('Save'),
onSelect: () => context.showSnackBar('Save #$index'),
child: const FaIcon(FontAwesomeIcons.solidBookmark),
),
PieAction(
tooltip: const Text('Share'),
onSelect: () => context.showSnackBar('Share #$index'),
child: const FaIcon(FontAwesomeIcons.share),
),
],
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'#$index',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 64,
),
),
),
),
);
},
),
),
);
},
);
}
}
Expand Down
117 changes: 117 additions & 0 deletions lib/src/bouncing_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import 'dart:math';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:pie_menu/src/pie_theme.dart';

/// This widget is highly inspired by [Bounce](https://pub.dev/packages/bounce)
/// package created by [Guillaume Cendre](https://github.com/mrcendre)
class BouncingWidget extends StatefulWidget {
const BouncingWidget({
super.key,
required this.theme,
required this.animation,
required this.locallyPressedOffset,
required this.child,
});

final PieTheme theme;
final Animation<double> animation;
final Offset? locallyPressedOffset;
final Widget child;

@override
State<BouncingWidget> createState() => _BouncingWidgetState();
}

class _BouncingWidgetState extends State<BouncingWidget> {
var lastSize = Size.zero;

@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: widget.animation,
builder: (context, child) {
final v = 0.5 / max(lastSize.width, lastSize.height);
final transform = Matrix4.identity()..setEntry(3, 2, v);

transform.scale(
lerpDouble(1, widget.theme.childBounceFactor, widget.animation.value),
);

final offset = widget.locallyPressedOffset;

if (widget.theme.childTiltEnabled && offset != null) {
final x = offset.dx / lastSize.width;
final y = offset.dy / lastSize.height;

const tiltAngle = pi / 10;

final xAngle = (y - 0.5) * tiltAngle;
final yAngle = (x - 0.5) * (-tiltAngle);

transform.rotateX(xAngle * widget.animation.value);
transform.rotateY(yAngle * widget.animation.value);
}

return Transform(
transform: transform,
origin: Offset(lastSize.width / 2, lastSize.height / 2),
child: _WidgetSizeWrapper(
onSizeChange: (newSize) {
if (lastSize == newSize) return;
setState(() => lastSize = newSize);
},
child: widget.child,
),
);
},
child: widget.child,
);
}
}

typedef _OnWidgetSizeChange = Function(Size newSize);

class _WidgetSizeRenderObject extends RenderProxyBox {
_WidgetSizeRenderObject(this.onSizeChange);

final _OnWidgetSizeChange onSizeChange;
Size? currentSize;

@override
void performLayout() {
super.performLayout();

try {
Size? newSize = child?.size;

if (newSize != null && currentSize != newSize) {
currentSize = newSize;
WidgetsBinding.instance.addPostFrameCallback((_) {
onSizeChange(newSize);
});
}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
}

class _WidgetSizeWrapper extends SingleChildRenderObjectWidget {
const _WidgetSizeWrapper({
required this.onSizeChange,
required Widget super.child,
});

final _OnWidgetSizeChange onSizeChange;

@override
RenderObject createRenderObject(BuildContext context) {
return _WidgetSizeRenderObject(onSizeChange);
}
}
Loading

0 comments on commit 389eaf4

Please sign in to comment.