Flutter - ClipPath Flutter - ClipPath flutter flutter

Flutter - ClipPath


with this simple custom ShapeBorder:

class MessageBorder extends ShapeBorder {  final bool usePadding;  MessageBorder({this.usePadding = true});  @override  EdgeInsetsGeometry get dimensions => EdgeInsets.only(bottom: usePadding? 20 : 0);  @override  Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;  @override  Path getOuterPath(Rect rect, {TextDirection textDirection}) {    rect = Rect.fromPoints(rect.topLeft, rect.bottomRight - Offset(0, 20));    return Path()      ..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2)))      ..moveTo(rect.bottomCenter.dx - 10, rect.bottomCenter.dy)      ..relativeLineTo(10, 20)      ..relativeLineTo(20, -20)      ..close();  }  @override  void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}  @override  ShapeBorder scale(double t) => this;}

and that usage code:

Container(  height: 64,  decoration: ShapeDecoration(    color: Colors.white,    shape: MessageBorder(),    shadows: [      BoxShadow(color: Colors.black, blurRadius: 4.0, offset: Offset(2, 2)),    ],  ),  alignment: Alignment.centerRight,  padding: EdgeInsets.only(right: 8),  child: Container(    width: 30,    decoration: BoxDecoration(      color: Colors.blueAccent,      shape: BoxShape.circle,    ),  ),),

you can have the result like this:

enter image description here

EDIT: if you want your Widget to be clickable then use something like this:

class ButtonMessage extends StatelessWidget {  final String text;  final GestureTapCallback onTap;  const ButtonMessage(this.text, this.onTap);  @override  Widget build(BuildContext context) {    return Material(      color: Colors.white,      elevation: 4,      clipBehavior: Clip.antiAlias,      shape: MessageBorder(),      child: InkWell(        splashColor: Colors.orange,        hoverColor: Colors.blueGrey,        highlightColor: Colors.transparent,        onTap: onTap,        child: Container(          height: 64,          padding: EdgeInsets.only(bottom: 20, right: 8),          child: Row(            mainAxisAlignment: MainAxisAlignment.end,            children: <Widget>[              Container(                width: 7,                height: 8,                decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),              ),              Container(width: 3,),              Container(                width: 7,                height: 8,                decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),              ),              Container(width: 3,),              Container(                width: 7,                height: 8,                decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),              ),              Container(width: 6,),              Container(                width: 25,                height: 24,                decoration: BoxDecoration(color: Color(0xFF1287BA), shape: BoxShape.circle),                child: Center(                  child: Text(text, style: TextStyle(color: Color(0xFFFFFFFF))),                ),              ),            ],          ),        ),      ),    );  }}

EDIT2: clickable baloon with a custom shadows:

class ButtonMessage extends StatelessWidget {  final String text;  final GestureTapCallback onTap;  const ButtonMessage(this.text, this.onTap);  @override  Widget build(BuildContext context) {    return Container(      decoration: ShapeDecoration(        shape: MessageBorder(usePadding: false),        shadows: [          BoxShadow(color: Colors.black, blurRadius: 4, offset: Offset(2, 2)),        ],      ),      child: Material(        color: Colors.white,        clipBehavior: Clip.antiAlias,        shape: MessageBorder(),        child: InkWell(          splashColor: Colors.orange,          hoverColor: Colors.blueGrey,          highlightColor: Colors.transparent,          onTap: onTap,          child: Container(            height: 64,            padding: EdgeInsets.only(bottom: 20, right: 8),            child: Row(              mainAxisAlignment: MainAxisAlignment.end,              children: <Widget>[                Container(                  width: 7,                  height: 8,                  decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),                ),                Container(width: 3,),                Container(                  width: 7,                  height: 8,                  decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),                ),                Container(width: 3,),                Container(                  width: 7,                  height: 8,                  decoration: BoxDecoration(color: Color(0xFFCCCCCC), shape: BoxShape.circle),                ),                Container(width: 6,),                Container(                  width: 25,                  height: 24,                  decoration: BoxDecoration(color: Color(0xFF1287BA), shape: BoxShape.circle),                  child: Center(                    child: Text(text, style: TextStyle(color: Color(0xFFFFFFFF))),                  ),                ),              ],            ),          ),        ),      ),    );  }}