Flutter: Advanced neon UI for border container

Issue

I am trying to do it

enter image description here

I know how to add shadow to a container, but I don’t know how to add different color on it or white reflection.

I tried to do like this:

Container(
  width: MediaQuery.of(context).size.width * 0.7,
  height: 50,
  decoration: BoxDecoration(
    boxShadow: [
            BoxShadow(
              color: Color(0XFF900ee5),
              offset: Offset(0, 0),
              blurRadius: 20,
              spreadRadius: 10,
            )
          ],
      borderRadius: BorderRadius.circular(100),
      border: Border.all(color: Color(0XFFff00ff), width: 4)),
      child: Center(child: AutoSizeText('BUTTON')),
);

It does not work, I will try with paint but do you have any link that can help me with white reflection to render more real?

Solution

As always all here depends on your imagination, the more elements – the more realistic it will look. The tricky part here is the shadow, I myself cheated there a bit, you could scale one big shadow to be from both sides of the line and then add new black shadow in center to look more natural.

enter image description here

Code to reproduce

import 'dart:typed_data';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'CustomPaint spotlight',
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          title: Text('CustomPaint spotlight'),
        ),
        body: Center(
          child: 
          CustomPaint(
            foregroundPainter: BorderPainter(),
            child: Container(
              width: 500,
              height: 100,
            ),
          ),
        ),
      ),
    );
  }
}

class BorderPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    double sh = size.height; // for convenient shortage
    double sw = size.width; // for convenient shortage
    double th = sh * 0.1; // total frame thickness
    double side = sw * 0.12; 

    Paint outerPaint = Paint()
      ..color = Color(0xFF9600FC)
      ..strokeWidth = th
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;

    Paint lightTopPaint = Paint()
      ..color = Color(0XFFD197F9)
      ..style = PaintingStyle.fill;

    Paint lightSmallPaint = Paint()
      ..color = Colors.white
      ..strokeWidth = th*0.06
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke;

    Paint arcPaint = Paint()
      ..color = Color(0xFF3D0066)
      ..style = PaintingStyle.fill;

    Paint minilinePaint = Paint()
      ..color = Color(0xFF180029)
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = th*0.06;
      
    Path outerPath = Path()
      ..moveTo(side, 0)
      ..lineTo(sw - side, 0)
      ..quadraticBezierTo(sw, 0, sw, sh/2)
      ..quadraticBezierTo(sw, sh, sw - side, sh)
      ..lineTo(side, sh)
      ..quadraticBezierTo(0, sh, 0, sh/2)
      ..quadraticBezierTo(0, 0, side, 0);
      
      
    Path lightTop = Path()
      ..moveTo(-th, sh/2)
      ..quadraticBezierTo(0, 0, side, -th/3)
      ..lineTo(sw-side, -th/3)
      ..quadraticBezierTo(sw, 0, sw+th, sh/2)
      ..quadraticBezierTo(sw, 0, sw-side, th/20)
      ..lineTo(side, th/20)
      ..quadraticBezierTo(0, 0, -th, sh/2);

        Path lightBottom = Path()
      ..moveTo(-th, sh/2)
      ..quadraticBezierTo(0, sh, side, sh+th/3)
      ..lineTo(sw-side, sh+th/3)
      ..quadraticBezierTo(sw, sh, sw+th, sh/2)
      ..quadraticBezierTo(sw, sh, sw-side, sh - th/20)
      ..lineTo(side, sh - th/20)
      ..quadraticBezierTo(0, sh, -th, sh/2);

    Path lightSmallTop = Path()
      ..moveTo(side*0.8, th*0.3)
      ..lineTo(sw-side*0.8, th*0.3);

    Path miniLineTop = Path()
      ..moveTo(side*0.8, th/3)
      ..lineTo(sw - side*0.8, th/3);

    Path miniLineBottom = Path()
      ..moveTo(side*0.8, sh+th/3)
      ..lineTo(sw - side*0.8, sh+th/3);

    Path lightSmallBottom = Path()
      ..moveTo(side*0.8, sh -th*0.3)
      ..lineTo(sw-side*0.8, sh -th*0.3);



    Path leftArc = Path()
      ..moveTo(side, -th/2)
      ..quadraticBezierTo(0, 0, -th/2, sh/2)
      ..quadraticBezierTo(0, sh, side, sh)
      ..quadraticBezierTo(0, sh, 0, sh/2)
      ..quadraticBezierTo(0, 0, side, -th/2);

    Path rightArc = Path()
      ..moveTo(sw - side, th/2)
      ..quadraticBezierTo(sw, 0, sw + th/2, sh/2)
      ..quadraticBezierTo(sw, sh, sw-side, sh)
      ..quadraticBezierTo(sw, sh, sw, sh/2)
      ..quadraticBezierTo(sw, 0, sw-side, th/2);


    Float64List matrix4 = Float64List.fromList([1,0,0,0,
                              0,0.3,0,0,
                              0,0,1,0,
                              0,0,0,1,]);


    canvas.drawShadow(outerPath.transform(matrix4).shift(Offset(0,-sh)), Color(0xFF9600FC), sh, true);
    canvas.drawShadow(outerPath.transform(matrix4).shift(Offset(0,0)), Color(0xFF9600FC), sh, true);

    canvas.drawPath(outerPath, outerPaint);
    canvas.drawPath(lightTop, lightTopPaint);
    canvas.drawPath(miniLineTop, minilinePaint);
    canvas.drawPath(miniLineBottom, minilinePaint);
    canvas.drawPath(lightBottom, lightTopPaint);
    canvas.drawPath(lightSmallTop, lightSmallPaint);
    canvas.drawPath(lightSmallBottom, lightSmallPaint);
    canvas.drawPath(leftArc, arcPaint);
    canvas.drawPath(rightArc, arcPaint);

  }

  @override
  bool shouldRepaint(BorderPainter oldDelegate) => false;

  @override
  bool shouldRebuildSemantics(BorderPainter oldDelegate) => false;
}

Answered By – Simon Sot

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.