How can I align little circles equally into a big circle? - flutter

I've made one big rounded container and now I want to align different tiny circle containers equally into it. How can I do that without adjusting the position all the time? Is there a better way so that even when I change the size of the tiny circles, the position remain equally?
this is a piece of code:
return Material(
color: Colors.black,
child: Center(
child: Stack(
textDirection: TextDirection.ltr,
children: [
DialBottomCircle,
Positioned(
//maybe as buttons
child: CircleNumbers(
textNumber: '0',
),
bottom: 0,
top: 260.0,
left: 245.0,
),
Positioned(
child: CircleNumbers(
textNumber: '9',
),
bottom: -70.0,
top: 225.0,
left: 175.0),

use CustomMultiChildLayout, something like this:
#override
Widget build(BuildContext context) {
var numbers = List.generate(10, (index) => '$index');
return Material(
shape: CircleBorder(),
color: Colors.red,
child: CustomMultiChildLayout(
delegate: FooDelegate(numbers.length),
children: [
for (var i = 0; i < numbers.length; i++)
LayoutId(
id: i,
child: Material(
elevation: 4,
color: Colors.white,
shape: CircleBorder(),
clipBehavior: Clip.antiAlias,
child: InkWell(
splashColor: Colors.orange,
onTap: () => print('${numbers[i]} pressed'),
child: FittedBox(
child: Text(numbers[i]),
),
),
),
),
],
),
);
);
class FooDelegate extends MultiChildLayoutDelegate {
final int numChildren;
FooDelegate(this.numChildren);
#override
void performLayout(Size size) {
final s = Size.square(size.shortestSide / 6.5);
final radius = (size.shortestSide - s.shortestSide) * 0.45;
final childConstraints = BoxConstraints.tight(s);
final delta = ((size - s) as Offset) / 2;
for (var i = 0; i < numChildren; i++) {
layoutChild(i, childConstraints);
var angle = i * math.pi / 6;
var offset = Offset(math.cos(angle), math.sin(angle)) * radius;
positionChild(i, offset + delta);
}
}
#override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => true;
}

Related

How can I drag items onto an InteractiveViewer in the correct spot?

I'm trying to build an app which will have a page where users can drag objects onto a battlefield to create their own map. I am trying to have a little menu on the right side of the screen which will have the objects you can place, and the main area is an InteractiveViewer with a stack where I want to put the objects. In the code below, I can drag items onto the viewer, but I can't figure out how to put the objects in the right spot on the viewer. By "right spot", I mean that I want the objects to stay in the spot I put them, but I can't figure out how to get the coordinates of where the objects should be relative to the current viewport. I can't figure out how to get the right x and y offsets.
Here is my code:
class Battlefield extends StatefulWidget {
double mapWidth = 0;
double mapHeight = 0;
Battlefield({super.key}) {
mapHeight = 200 * 50.0; // note, these values will change
mapWidth = 200 * 50.0;
}
#override
_BattlefieldState createState() => _BattlefieldState();
}
class _BattlefieldState extends State<Battlefield> {
TransformationController _controller = TransformationController();
Box _box = Box();
List<Widget> _children = [];
List<Widget> getChildren() {
List<Widget> children = _children;
// this box I add so I can have a reference point for debugging
children.add(Positioned(
child: SizedBox(
child: ColoredBox(color: Colors.red),
width: 500,
height: 500,
),
left: widget.mapWidth / 2 - 250,
top: widget.mapHeight / 2 - 250,
));
return children;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Battlefield"),
),
body: ResponsiveScreen(
squarishMainArea: InteractiveViewer(
constrained: false,
transformationController: _controller,
minScale: 0.1,
maxScale: 3.0,
child: CustomPaint(
painter: GridBackground(),
child: SizedBox(
width: widget.mapWidth,
height: widget.mapHeight,
child: DragTarget<Box>(
builder: (context, candidateData, rejectedData) {
return Stack(
children: getChildren(),
);
},
onAccept: (box) {
setState(() {
_children.add(Positioned(
child: SizedBox(
child: ColoredBox(color: Colors.black),
width: 50,
height: 50,
),
left: box.xPos,
top: box.yPox,
));
});
},
),
),
)),
rectangularMenuArea: Container(
decoration: BoxDecoration(color: Colors.blue),
child: Draggable<Box>(
data: _box,
feedback: SizedBox(
child: ColoredBox(color: Colors.grey),
width: 50,
height: 50,
),
child: SizedBox(
child: ColoredBox(color: Colors.black),
width: 50,
height: 50,
),
onDragEnd: (details) {
// here is where I am setting the position of the box.
// I want it to be a property of the box so I can save it to a db
final x = _controller.value.getMaxScaleOnAxis();
final offset = _controller.value.getTranslation();
final viewportOffsetX = offset.x;
final viewportOffsetY = offset.y;
_box.xPos = details.offset.dx - (viewportOffsetX * 1 / x);
_box.yPox = details.offset.dy - (viewportOffsetY * 1 / x);
},
),
)),
);
}
}
class Box {
double xPos = 0;
double yPox = 0;
Box();
}
For reference, the ResponsiveScreen widget I am using is from here: https://github.com/flutter/samples/blob/main/game_template/lib/src/style/responsive_screen.dart

Flutter How to stack image and total member text

I was able to show the pictures as in the video by taking advantage of Johannes Milke's video that I left the link of. But that's not all I want. I need a structure that looks like these images but shows the total number of users. I leave the image of exactly what I want and my related codes.
What I want to achieve; Creating a structure where I can write the total number of users
There are a few packages on pub dev but not what I wanted. Thank you
Video:Source Video
image i want to make:
My stacked widget:
import 'package:flutter/material.dart';
class StackedWidgets extends StatelessWidget {
final List<Widget> items;
final TextDirection direction;
final double size;
final double xShift;
const StackedWidgets({
Key? key,
required this.items,
this.direction = TextDirection.ltr,
this.size = 100,
this.xShift = 20,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final allItems = items
.asMap()
.map((index, item) {
final left = size - xShift;
final value = Container(
width: size,
height: size,
child: item,
margin: EdgeInsets.only(left: left * index),
);
return MapEntry(index, value);
})
.values
.toList();
return Stack(
children: direction == TextDirection.ltr
? allItems.reversed.toList()
: allItems,
);
}
}
Usage my stacked widget:
Widget buildStackedImages({
TextDirection direction = TextDirection.ltr,
}) {
final double size = 100;
final double xShift = 20;
final urlImages = [
'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80',
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
'https://images.unsplash.com/photo-1616766098956-c81f12114571?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
];
final items = urlImages.map((urlImage) => buildImage(urlImage)).toList();
return StackedWidgets(
direction: direction,
items: items,
size: size,
xShift: xShift,
);
}
Widget buildImage(String urlImage) {
final double borderSize = 5;
return ClipOval(
child: Container(
padding: EdgeInsets.all(borderSize),
color: Colors.white,
child: ClipOval(
child: Image.network(
urlImage,
fit: BoxFit.cover,
),
),
),
);
}
Add a label also to this class
import 'package:flutter/material.dart';
class StackedWidgets extends StatelessWidget {
final List<Widget> items;
final TextDirection direction;
final double size;
final double xShift;
final String lable;
const StackedWidgets({
Key? key,
required this.items,
this.direction = TextDirection.ltr,
this.size = 100,
this.xShift = 20,
this.label = '',
}) : super(key: key);
#override
Widget build(BuildContext context) {
final allItems = items
.asMap()
.map((index, item) {
final left = size - xShift;
final value = Container(
width: size,
height: size,
child: item,
margin: EdgeInsets.only(left: left * index),
);
return MapEntry(index, value);
})
.values
.toList();
return Row(
children: [
Stack(
children: direction == TextDirection.ltr
? allItems.reversed.toList()
: allItems,
),
Text(label),
]
);
}
}
In items pass the number widget and label too
return StackedWidgets(
direction: direction,
items: [...items, Container(
width: 25,//you can also add padding if required
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.orange,
),
child: Text('+22'))],
size: size,
xShift: xShift,
label: "users are here",
);
I will prefer this way,
Run on dartPad
class InTEST extends StatefulWidget {
const InTEST({Key? key}) : super(key: key);
#override
State<InTEST> createState() => _InTESTState();
}
class _InTESTState extends State<InTEST> {
int maxRenderAvatar = 5;
int numberOfActiveUser = 33;
double size = 100;
double borderSize = 5;
Widget buildStackedImages({
TextDirection direction = TextDirection.ltr,
}) {
List<String> urlImages = List.filled(
numberOfActiveUser, //based on your list
'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80');
List<Widget> items = [];
final renderItemCount = numberOfActiveUser > maxRenderAvatar
? maxRenderAvatar
: urlImages.length;
for (int i = 0; i < renderItemCount; i++) {
items.add(
Positioned(
left: (i * size * .8),
child: buildImage(
urlImages[i],
),
),
);
}
// add counter if urlImages.length > maxRenderAvatar
if (numberOfActiveUser > maxRenderAvatar) {
items.add(
Positioned(
left: maxRenderAvatar * size * .8,
child: Container(
width: size,
height: size,
padding: EdgeInsets.all(borderSize),
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 4),
color: Colors.amber,
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Text(
"+ ${urlImages.length - maxRenderAvatar}",
style: TextStyle(
fontSize: 23,
),
),
),
),
);
}
return SizedBox(
height: size + (borderSize * 2), //10 for borderSize
width: MediaQuery.of(context).size.width,
child: Stack(
children: items,
),
);
}
Widget buildImage(String urlImage) {
return ClipOval(
child: Container(
padding: EdgeInsets.all(borderSize),
color: Colors.white,
child: ClipOval(
child: Image.network(
urlImage,
width: size,
height: size,
fit: BoxFit.cover,
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Slider(
value: numberOfActiveUser.toDouble(),
min: 0,
max: 55,
onChanged: (v) {
numberOfActiveUser = v.toInt();
setState(() {});
}),
Slider(
value: maxRenderAvatar.toDouble(),
min: 0,
max: 42,
onChanged: (v) {
maxRenderAvatar = v.toInt();
setState(() {});
}),
buildStackedImages(),
],
),
);
}
}

Flutter Resizable Container using Gestures

I want to create a resizable container which can be resized by user using horizontal drag.
This Gif can explain the requirement:
I tried GestureDetector.horizontal drag but the results are way off:
Container(
color: primary,
width: size.width,
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onHorizontalDragUpdate: (details) {
final double newWidth;
if (details.delta.dx > 0) {
// movement in positive direction
final newWidth = size.width + 1;
print(newWidth);
final updatedSize = Size(newWidth, size.height);
setState(() {
size = updatedSize;
});
} else {
// movement in negative direction
final newWidth = math.max(size.width - 1, 5).toDouble();
print(newWidth);
final updatedSize = Size(newWidth, size.height);
setState(() {
size = updatedSize;
});
}
},
child: const Icon(
Icons.navigate_before_rounded,
color: Colors.white,
),
),
GestureDetector(
onHorizontalDragUpdate: (det) {
if (det.delta.dx > 1) {
var newWidth = size.width + 1;
final updatedSize = Size(newWidth, size.height);
setState(() {
size = updatedSize;
});
} else {
var newWidth = size.width - 1;
newWidth = math.max(newWidth, 10);
final updatedSize = Size(newWidth, size.height);
setState(() {
size = updatedSize;
});
}
},
child: const Icon(
Icons.navigate_next_rounded,
color: Colors.white,
),
),
],
),
),
I am looking for a way to get size change of one side using drag, also the width should decrease or increase on the basis of dragging direction and if possible the whole container can be moved as well.
You can use Stack with Positioned widget to handle container sizing and to drag the full container I am using transform.
Run on dartPad
You can play with this widget.
class FContainer extends StatefulWidget {
FContainer({Key? key}) : super(key: key);
#override
State<FContainer> createState() => _FContainerState();
}
class _FContainerState extends State<FContainer> {
///initial position
double leftPos = 33;
double rightPos = 33;
double transformX = 0;
#override
Widget build(BuildContext context) {
return Center(
child: LayoutBuilder(
builder: (context, constraints) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
transform: Matrix4.translationValues(transformX, 0, 0),
height: 60,
width: constraints.maxWidth,
child: Stack(
children: [
Positioned(
top: 0,
bottom: 0,
left: leftPos,
right: rightPos,
child: Row(
children: [
GestureDetector(
onTap: () {},
onHorizontalDragUpdate: (details) {
leftPos = details.globalPosition.dx;
setState(() {});
debugPrint(leftPos.toString());
},
child: Container(
height: 60,
color: Colors.purple,
child: const Icon(
Icons.navigate_next_rounded,
color: Colors.black,
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
onHorizontalDragUpdate: (details) {
final midPos = details.delta;
transformX += midPos.dx;
setState(() {});
debugPrint(midPos.toString());
},
child: Container(
color: Colors.purple,
),
),
),
GestureDetector(
onTap: () {},
onHorizontalDragUpdate: (details) {
rightPos = constraints.maxWidth -
details.globalPosition.dx;
setState(() {});
debugPrint(rightPos.toString());
},
child: Container(
height: 60,
color: Colors.purple,
child: const Icon(
Icons.navigate_before_rounded,
color: Colors.black,
),
),
),
],
),
)
],
),
)
],
),
),
);
}
}
You can wrap with if condition to avoid getting out of the screen.

Flutter GestureDector used to drag widget: Coordinates to not match second drag

I want to be able to drag an widget to any place on the screen. The first time the widget is dragged and place in a section of the screen. There is no issue. On the second attempt to drag of the widget container, the coordinates to not match and the widget jumps to the top of the screen. I want to have multiple widgets that can be dragged.
Any suggestions welcomed.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
// visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'HomePage'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double ytop = 50.0;
double xleft = 50.0;
GlobalKey blueKey = GlobalKey();
String position = '';
#override
void initState() {
// _getPositions();
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_getPositions();
});
}
#override
Widget build(BuildContext context) {
// _getPositions();
print('$xleft <---> $ytop');
return Scaffold(
// appBar: AppBar(
// title: Text(widget.title),
// ),
body: Container(
child: Stack(
children: <Widget>[
Positioned(
top: 30,
left: 10,
child: Text(
'Filler Text',
),
),
Positioned(
top: ytop,
left: xleft,
child: GestureDetector(
dragStartBehavior: DragStartBehavior.down,
onVerticalDragStart: _onVerticalDragStartHandler,
onVerticalDragUpdate: _onDragUpdateHandler,
onVerticalDragEnd: (details) => {print('On END $details')},
onTap: () {
print('HELLO');
_getPositions();
},
child: Container(
key: blueKey,
width: 100,
height: 100,
decoration: myBlueBoxDecoration,
),
// ),
),
),
],
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
/// Track starting point of a vertical gesture
void _onVerticalDragStartHandler(DragStartDetails details) {
setState(() {
ytop = details.globalPosition.dy;
xleft = details.globalPosition.dx;
// final dd = details.globalPosition.dy;
print('Vertical Start Local Vertical Left: $xleft Top: $ytop');
});
}
void _onDragUpdateHandler(DragUpdateDetails details) {
setState(
() {
ytop = details.localPosition.dy;
xleft = details.localPosition.dx;
xleft = xleft < 0 ? 0 : xleft;
ytop = ytop < 10 ? 10 : ytop;
// xleft = xleft > 259 ? 259 : xleft;
// ytop = ytop > 618 ? 618 : ytop;
print('Drage Update:--> Left: $xleft Top: $ytop\n');
print('');
},
);
}
_getPositions() {
final RenderBox renderBoxRed = blueKey.currentContext.findRenderObject();
final positionRed = renderBoxRed.localToGlobal(Offset.zero);
position = 'POSITION of Red: $positionRed';
print(position);
}
}
BoxDecoration myBlueBoxDecoration = BoxDecoration(
color: const Color(0xff7c94b6),
border: Border.all(color: Colors.green, width: 1),
borderRadius: BorderRadius.circular(12),
);
I fixed the problem by moving to LongPressDraggable. It would be good to reduce the time that makes the widget able to drag. See the code below. Any suggestions on the original implementation welcomed.
Positioned(
top: ytop,
left: xleft,
child: LongPressDraggable(
childWhenDragging: Container(
// key: blueKey,
width: w,
height: h,
decoration: myBlueBoxDecoration,
),
onDragStarted: genericCall,
onDragEnd: (d) {
setState(() {
xleft = d.offset.dx;
ytop = d.offset.dy;
print(d.offset.dx);
});
},
feedback: Container(
// key: blueKey,
width: 100,
height: 100,
decoration: myGreenBoxDecoration,
),
child: Container(
key: blueKey,
width: 100,
height: 100,
decoration: myBlueBoxDecoration,
),
),
),
I guess the old man is thinking to slow. Here is fix I needed.
Positioned(
top: ytop,
left: xleft,
child: Draggable(
childWhenDragging: Container(
// key: blueKey,
width: w,
height: h,
decoration: myBlueBoxDecoration,
),
onDragStarted: genericCall,
onDragEnd: (d) {
setState(() {
xleft = d.offset.dx;
ytop = d.offset.dy;
print(d.offset.dx);
});
},
feedback: Container(
// key: blueKey,
width: 100,
height: 100,
decoration: myGreenBoxDecoration,
),
child: Container(
key: blueKey,
width: 100,
height: 100,
decoration: myBlueBoxDecoration,
),
),
),

How to make custom Bottom Navigation Bar in Flutter

I have a design of Bottom Navigation Bar like this:
I try my best to create custom of Bottom Navigation Bar with this code:
class FABBottomAppBarItem {
FABBottomAppBarItem({this.iconData, this.text});
IconData iconData;
String text;
}
class FABBottomAppBar extends StatefulWidget {
FABBottomAppBar({
this.items,
this.centerItemText,
this.height: 60.0,
this.iconSize: 24.0,
this.backgroundColor,
this.color,
this.selectedColor,
this.notchedShape,
this.onTabSelected,
}) {
assert(this.items.length == 2 || this.items.length == 4);
}
final List<FABBottomAppBarItem> items;
final String centerItemText;
final double height;
final double iconSize;
final Color backgroundColor;
final Color color;
final Color selectedColor;
final NotchedShape notchedShape;
final ValueChanged<int> onTabSelected;
#override
State<StatefulWidget> createState() => FABBottomAppBarState();
}
class FABBottomAppBarState extends State<FABBottomAppBar> {
int _selectedIndex = 0;
_updateIndex(int index) {
widget.onTabSelected(index);
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
List<Widget> items = List.generate(widget.items.length, (int index) {
return _buildTabItem(
item: widget.items[index],
index: index,
onPressed: _updateIndex,
);
});
items.insert(items.length >> 1, _buildMiddleTabItem());
return BottomAppBar(
shape: widget.notchedShape,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items,
),
color: widget.backgroundColor,
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: widget.height,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: widget.iconSize),
Text(
widget.centerItemText ?? '',
style: TextStyle(color: widget.color),
),
],
),
),
);
}
Widget _buildTabItem({
FABBottomAppBarItem item,
int index,
ValueChanged<int> onPressed,
}) {
Color color = _selectedIndex == index ? widget.selectedColor : widget.color;
return Expanded(
child: SizedBox(
height: widget.height,
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () => onPressed(index),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(item.iconData, color: color, size: widget.iconSize),
Text(
item.text,
style: TextStyle(color: color),
)
],
),
),
),
),
);
}
}
And I implemented that custom like this:
bottomNavigationBar: FABBottomAppBar(
centerItemText: 'เสา',
color: Colors.grey,
backgroundColor: Colors.white,
selectedColor: Colors.red,
notchedShape: CircularNotchedRectangle(),
onTabSelected: _onTapped,
items: [
FABBottomAppBarItem(iconData: Icons.home, text: 'หน้าแรก'),
FABBottomAppBarItem(iconData: Icons.search, text: 'ค้นหา'),
FABBottomAppBarItem(iconData: Icons.account_circle, text: 'โปรไฟล์'),
FABBottomAppBarItem(iconData: Icons.more_horiz, text: 'อื่นๆ'),
],
),
body: _list[_page],
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {
},
child: Icon(Icons.add),
elevation: 2.0,
),
),
And the result of that code is:
How to make my Custom Nav Bar like the design? Because in the design, the FAB/Asset/Icon inside the Bottom Navigation Bar and have curved upwards as I marked with arrows in the design.
I edited CircularNotchedRectangle.
Use CircularOuterNotchedRectangle instead of CircularNotchedRectangle.
PS. I added extraOffset param for extra thick. but it's not working exactly correct. But I just wanted to show you how to approach.
class CircularOuterNotchedRectangle extends NotchedShape {
/// Creates a [CircularOuterNotchedRectangle].
///
/// The same object can be used to create multiple shapes.
const CircularOuterNotchedRectangle({this.extraOffset = 10.0});
final double extraOffset;
/// Creates a [Path] that describes a rectangle with a smooth circular notch.
///
/// `host` is the bounding box for the returned shape. Conceptually this is
/// the rectangle to which the notch will be applied.
///
/// `guest` is the bounding box of a circle that the notch accommodates. All
/// points in the circle bounded by `guest` will be outside of the returned
/// path.
///
/// The notch is curve that smoothly connects the host's top edge and
/// the guest circle.
// TODO(amirh): add an example diagram here.
#override
Path getOuterPath(Rect host, Rect guest) {
if (guest == null || !host.overlaps(guest)) return Path()..addRect(host);
// The guest's shape is a circle bounded by the guest rectangle.
// So the guest's radius is half the guest width.
final double notchRadius = guest.width / 2.0;
// We build a path for the notch from 3 segments:
// Segment A - a Bezier curve from the host's top edge to segment B.
// Segment B - an arc with radius notchRadius.
// Segment C - a Bezier curve from segment B back to the host's top edge.
//
// A detailed explanation and the derivation of the formulas below is
const double s1 = 15.0;
const double s2 = 1.0;
final double r = notchRadius + extraOffset/2;
final double a = -1.0 * r - s2;
final double b = host.top + guest.center.dy;
final double n2 = math.sqrt(b * b * r * r * (a * a + b * b - r * r));
final double p2xA = ((a * r * r) - n2) / (a * a + b * b);
final double p2xB = ((a * r * r) + n2) / (a * a + b * b);
final double p2yA = math.sqrt(r * r - p2xA * p2xA) - extraOffset/2;
final double p2yB = math.sqrt(r * r - p2xB * p2xB) - extraOffset/2;
final List<Offset> p = List<Offset>(6);
// p0, p1, and p2 are the control points for segment A.
p[0] = Offset(a - s1, b);
p[1] = Offset(a, b);
p[2] = p2yA > p2yB ? Offset(p2xA, -p2yA) : Offset(p2xB, p2yB);
// p3, p4, and p5 are the control points for segment B, which is a mirror
// of segment A around the y axis.
p[3] = Offset(-1.0 * p[2].dx, -p[2].dy);
p[4] = Offset(-1.0 * p[1].dx, p[1].dy);
p[5] = Offset(-1.0 * p[0].dx, p[0].dy);
// translate all points back to the absolute coordinate system.
for (int i = 0; i < p.length; i += 1) p[i] += guest.center;
return Path()
..moveTo(host.left, -host.top)
..lineTo(p[0].dx, p[0].dy)
..quadraticBezierTo(p[1].dx, p[1].dy, p[2].dx, -p[2].dy)
..arcToPoint(
p[3],
radius: Radius.circular(notchRadius),
clockwise: true,
)
..quadraticBezierTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy)
..lineTo(host.right, host.top)
..lineTo(host.right, host.bottom)
..lineTo(host.left, host.bottom)
..close();
}
}
Please try this one, its may helps you
Scaffold(
backgroundColor: Colors.blueAccent,
floatingActionButton: Padding(
padding: EdgeInsets.only(top: 20),
child: SizedBox(
height: 70,
width: 70,
child: FloatingActionButton(
backgroundColor: Colors.transparent,
elevation: 0,
onPressed: () {},
child: Container(
height: 75,
width: 75,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 4),
shape: BoxShape.circle,
color: Colors.red
),
child: Icon(Icons.add, size: 40),
),
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: new Container(
height: 80.0,
color: Colors.white,
padding: new EdgeInsets.only(top: 20.0),
child: new Theme(
data: Theme.of(context).copyWith(
// sets the background color of the `BottomNavigationBar`
canvasColor: Colors.white,
// sets the active color of the `BottomNavigationBar` if `Brightness` is light
primaryColor: Colors.red,
bottomAppBarColor: Colors.green,
textTheme: Theme
.of(context)
.textTheme
.copyWith(caption: new TextStyle(color: Colors.grey))), // sets the inactive color of the `BottomNavigationBar`
child:
new BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex:0 ,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text('Home'),
backgroundColor: Colors.black
),
BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: new Text('Search'),
),
BottomNavigationBarItem(
icon: Icon(Icons.bookmark_border,color: Colors.transparent,),
title: Text('Center')
),
BottomNavigationBarItem(
icon: Icon(Icons.perm_identity),
title: Text('Person')
),
BottomNavigationBarItem(
icon: Icon(Icons.more_horiz),
title: Text('More')
),
]),
),
),
)
I would probably wrap your FloatingActionButton in a ClipRRect and Container like
floatingActionButton: ClipRRect(
borderRadius: BorderRadius.circular(80),
child: Container(
color: Colors.black,
padding: EdgeInsets.all(8),
child: FloatingActionButton(
onPressed: () {},
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
Giving as color same of the BottomNavigationBoar. It should work