A Flutter widget for chat like a speech bubble in Whatsapp and others.
See sources.
Bubble(
child: Text('Hello, World!'),
),
Bubble(
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
child: Text('Hi, developer!'),
),
Bubble(
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.rightBottom,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.leftBottom,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.no,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TOMORROW', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
If stick
set to false
the right offset of bubble equal to the offset from
the left, not taking into account the size of the nip. This allows the bubbles
to line up. If stick
set to true
, the far side will be stick to the edge.
Bubble(
stick: true,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
stick: true,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
stick: true,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
stick: true,
nip: BubbleNip.rightBottom,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
stick: true,
nip: BubbleNip.leftBottom,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
stick: true,
nip: BubbleNip.no,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TOMORROW', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
alignment: Alignment.center,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nip: BubbleNip.rightBottom,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftBottom,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.center,
nip: BubbleNip.no,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TOMORROW', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
alignment: Alignment.center,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nipWidth: 8,
nipHeight: 24,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nipWidth: 8,
nipHeight: 24,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.center,
nip: BubbleNip.no,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TOMORROW', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
alignment: Alignment.center,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.zero,
alignment: Alignment.topRight,
nipWidth: 8,
nipHeight: 24,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.zero,
alignment: Alignment.topLeft,
nipWidth: 8,
nipHeight: 24,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.elliptical(5.0, 10.0),
alignment: Alignment.topRight,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.elliptical(5.0, 10.0),
alignment: Alignment.topLeft,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.circular(20.0),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
radius: Radius.circular(20.0),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.center,
nip: BubbleNip.no,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TOMORROW', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
for (var i = 0; i <= 5; i++)
Bubble(
margin: BubbleEdges.only(top: 10),
nipRadius: i.toDouble(),
alignment: Alignment.topRight,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
for (var i = 0; i <= 5; i++)
Bubble(
margin: BubbleEdges.only(top: 10),
nipRadius: i.toDouble(),
alignment: Alignment.topLeft,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Scheme:
for (var i = 0; i <= 15; i += 3)
Bubble(
margin: BubbleEdges.only(top: 10),
nipOffset: i.toDouble(),
alignment: Alignment.topRight,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World!', textAlign: TextAlign.right),
),
for (var i = 0; i <= 15; i += 3)
Bubble(
margin: BubbleEdges.only(top: 10),
nipOffset: i.toDouble(),
alignment: Alignment.topLeft,
nipWidth: 30,
nipHeight: 10,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
alignment: Alignment.center,
color: const Color.fromRGBO(212, 234, 244, 1),
child: const Text('TODAY',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11)),
),
Bubble(
margin: const BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: const Color.fromRGBO(225, 255, 199, 1),
child: const Text('Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: const BubbleEdges.only(top: 2),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
showNip: false,
color: const Color.fromRGBO(225, 255, 199, 1),
child: const Text('How are you?', textAlign: TextAlign.right),
),
Bubble(
margin: const BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: const Text('Hi, developer!'),
),
Bubble(
margin: const BubbleEdges.only(top: 2),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
showNip: false,
child: const Text('Well, see for yourself'),
),
Bubble(
alignment: Alignment.center,
color: Color.fromRGBO(212, 234, 244, 1.0),
child: Text('TODAY', textAlign: TextAlign.center, style: TextStyle(fontSize: 11.0)),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World! Hello, World! Hello, World! Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer! Hi, developer! Hi, developer! Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10, left: 40),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromRGBO(225, 255, 199, 1.0),
child: Text('Hello, World! Hello, World! Hello, World! Hello, World!', textAlign: TextAlign.right),
),
Bubble(
margin: BubbleEdges.only(top: 10, right: 40),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer! Hi, developer! Hi, developer! Hi, developer!'),
),
A thick shadow.
for (var i = 1; i <= 8; i *= 2)
Column(
children: <Widget>[
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: i.toDouble(),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: i.toDouble(),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
],
),
A thin shadow.
double px = 1 / MediaQuery.of(context).devicePixelRatio;
...
Bubble(
elevation: 0,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 0.5 * px,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 1 * px,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 1,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 0,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 0.5 * px,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 1 * px,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
elevation: 1,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
shadowColor: Colors.red,
elevation: 2,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
shadowColor: Colors.green,
elevation: 2,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
shadowColor: Colors.blue,
elevation: 2,
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
shadowColor: Colors.red,
elevation: 2,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
shadowColor: Colors.green,
elevation: 2,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
shadowColor: Colors.blue,
elevation: 2,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
padding: BubbleEdges.all(2),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
padding: BubbleEdges.all(2),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
padding: BubbleEdges.all(20),
alignment: Alignment.topRight,
nip: BubbleNip.rightTop,
color: Color.fromARGB(255, 225, 255, 199),
child: Text('Hello, World!'),
),
Bubble(
margin: BubbleEdges.only(top: 10),
padding: BubbleEdges.all(20),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
child: Text('Hi, developer!'),
),