Created
May 8, 2025 15:27
-
-
Save callmephil/28ed2aa12dcbbc8c32af44494386ae40 to your computer and use it in GitHub Desktop.
card overlay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
/// Global Chat Overlay Manager | |
class ChatOverlayService { | |
static final navigatorKey = GlobalKey<NavigatorState>(); | |
static final _chatKey = GlobalKey<_ChatContainerState>(); | |
static final chatContainer = ChatContainer(key: _chatKey); | |
static void toggle() => _chatKey.currentState?.toggle(); | |
static void show() => _chatKey.currentState?.show(); | |
static void hide() => _chatKey.currentState?.hide(); | |
} | |
/// The app entry point | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
navigatorKey: ChatOverlayService.navigatorKey, | |
builder: (context, child) { | |
return Stack(children: [child!, ChatOverlayService.chatContainer]); | |
}, | |
home: const HomeScreen(), | |
); | |
} | |
} | |
/// Sample home screen | |
class HomeScreen extends StatelessWidget { | |
const HomeScreen({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text("Global Chat Overlay")), | |
body: const Center(child: Text("Main screen")), | |
floatingActionButton: FloatingActionButton( | |
onPressed: ChatOverlayService.toggle, | |
child: const Icon(Icons.chat), | |
), | |
); | |
} | |
} | |
/// Reusable floating container | |
class ChatContainer extends StatefulWidget { | |
const ChatContainer({super.key}); | |
@override | |
State<ChatContainer> createState() => _ChatContainerState(); | |
} | |
class _ChatContainerState extends State<ChatContainer> | |
with SingleTickerProviderStateMixin { | |
late final AnimationController _controller; | |
late final Animation<Offset> _offsetAnimation; | |
bool _visible = false; | |
@override | |
void initState() { | |
super.initState(); | |
_controller = AnimationController( | |
vsync: this, | |
duration: const Duration(milliseconds: 250), | |
); | |
_offsetAnimation = Tween<Offset>( | |
begin: const Offset(0, 1), | |
end: Offset.zero, | |
).animate(CurvedAnimation( | |
parent: _controller, | |
curve: Curves.linear, | |
)); | |
} | |
void show() { | |
if (!_visible) { | |
setState(() => _visible = true); | |
_controller.forward(); | |
} | |
} | |
void hide() async { | |
await _controller.reverse(); | |
setState(() => _visible = false); | |
} | |
void toggle() => _visible ? hide() : show(); | |
@override | |
Widget build(BuildContext context) { | |
if (!_visible) return const SizedBox.shrink(); | |
return Positioned( | |
bottom: 20, | |
left: 20, | |
child: Material( | |
type: MaterialType.transparency, | |
child: SlideTransition( | |
position: _offsetAnimation, | |
child: ChatPopup(onClose: hide), | |
), | |
), | |
); | |
} | |
} | |
/// The chat popup box | |
class ChatPopup extends StatelessWidget { | |
final VoidCallback onClose; | |
const ChatPopup({super.key, required this.onClose}); | |
@override | |
Widget build(BuildContext context) { | |
return AnimatedContainer( | |
duration: Durations.medium1, | |
width: 300, | |
height: 400, | |
decoration: BoxDecoration( | |
color: Colors.white, | |
borderRadius: BorderRadius.circular(16), | |
// boxShadow: const [BoxShadow(blurRadius: 10, color: Colors.black26)], | |
), | |
child: Column( | |
children: [ | |
Container( | |
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), | |
decoration: const BoxDecoration( | |
color: Colors.blue, | |
borderRadius: BorderRadius.vertical(top: Radius.circular(16)), | |
), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
const Text( | |
'Chat', | |
style: TextStyle(color: Colors.white, fontSize: 18), | |
), | |
IconButton( | |
icon: const Icon(Icons.close, color: Colors.white), | |
onPressed: onClose, | |
), | |
], | |
), | |
), | |
const Expanded(child: Center(child: Text('Chat messages here'))), | |
Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: TextField( | |
decoration: InputDecoration( | |
hintText: "Type a message...", | |
border: OutlineInputBorder( | |
borderRadius: BorderRadius.circular(12), | |
), | |
), | |
), | |
), | |
], | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment