Skip to content

Instantly share code, notes, and snippets.

@kspo
Created November 16, 2023 19:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kspo/e56270215d00066be267e762e8b516cf to your computer and use it in GitHub Desktop.
Save kspo/e56270215d00066be267e762e8b516cf to your computer and use it in GitHub Desktop.
Simple Text Cloud Widget
import 'dart:math';
import 'package:flutter/material.dart';
import 'arrow.shape.dart';
class TextCloud extends StatefulWidget {
// final String text;
final Color color;
final EdgeInsets padding;
final Widget child;
// final double width;
// final double height;
final AxisDirection axisDirection;
final double locationOfArrow;
const TextCloud({
super.key,
// required this.text,
required this.child,
this.color = Colors.white,
this.padding = const EdgeInsets.all(10),
// this.width = 200,
// this.height = 100,
this.axisDirection = AxisDirection.left,
this.locationOfArrow = 0.25,
});
@override
State<TextCloud> createState() => _TextCloudState();
}
class _TextCloudState extends State<TextCloud> {
var key = GlobalKey();
Size redboxSize = Size(0, 0);
@override
void initState() {
WidgetsBinding.instance?.addPostFrameCallback((_) {
setState(() {
redboxSize = getRedBoxSize(key.currentContext!);
});
});
super.initState();
}
Size getRedBoxSize(BuildContext context) {
final box = context.findRenderObject() as RenderBox;
return box.size;
}
@override
Widget build(BuildContext context) {
Size arrowSize = const Size(25, 25);
double angle = 0;
switch (widget.axisDirection) {
case AxisDirection.left:
angle = pi * -0.5;
break;
case AxisDirection.up:
angle = pi * -2;
break;
case AxisDirection.right:
angle = pi * 0.5;
break;
case AxisDirection.down:
angle = pi;
break;
default:
angle = 0;
}
return Stack(
clipBehavior: Clip.none,
children: [
Container(
key: key,
// width: width,
// height: height,
padding: widget.padding,
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(5),
),
child: widget.child,
),
Positioned(
left: widget.axisDirection == AxisDirection.left
? -arrowSize.width + 5
: (widget.axisDirection == AxisDirection.up ||
widget.axisDirection == AxisDirection.down
? redboxSize.width * widget.locationOfArrow -
arrowSize.width / 2
: null),
right: widget.axisDirection == AxisDirection.right
? -arrowSize.width + 5
: null,
top: widget.axisDirection == AxisDirection.up
? -arrowSize.width + 5
: (widget.axisDirection == AxisDirection.right ||
widget.axisDirection == AxisDirection.left
? redboxSize.height * widget.locationOfArrow -
arrowSize.width / 2
: null),
bottom: widget.axisDirection == AxisDirection.down
? -arrowSize.width + 5
: null,
child: Transform.rotate(
angle: angle,
child: CustomPaint(
size: arrowSize,
painter: ArrowPaint(color: widget.color),
),
),
),
],
);
}
}
@kspo
Copy link
Author

kspo commented Nov 16, 2023

import 'package:flutter/material.dart';
import 'package:stackoverflow/text_cloud.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.light,
      theme: ThemeData.dark().copyWith(),
      home: Scaffold(
        body: Center(
          child: TextCloud(
            child: SizedBox(  // HERE You can place any widget, Size will be automatically calculated
              height: 150,
              child: Text(
                "Big Bang Theory is the best TV sitcom ever!",
                style: TextStyle(
                  color: Colors.black,
                  fontWeight: FontWeight.w600,
                  fontSize: 15,
                ),
              ),
            ),
            axisDirection: AxisDirection.left,
            locationOfArrow: 0.65,
          ),
        ),
      ),
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment