Skip to content

Instantly share code, notes, and snippets.

@jlamimoso
Last active April 1, 2022 19:54
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 jlamimoso/ea09bf631dfbbcdb4d73d1e11d5f0b4a to your computer and use it in GitHub Desktop.
Save jlamimoso/ea09bf631dfbbcdb4d73d1e11d5f0b4a to your computer and use it in GitHub Desktop.
Chat Bubble example
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue),
debugShowCheckedModeBanner: false,
home: const MyWidget(title: 'Chat Demo'),
);
}
}
class MyWidget extends StatefulWidget {
const MyWidget({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
List <Widget> messages = [];
void setSampleMessages(messages, now) {
messages.add(
DateChip(
date: DateTime(now.year, now.month, now.day - 2),
)
);
messages.add(
Bubble(
message: 'message 1111',
date: DateTime.parse("2022-03-30 13:27:03"),
delivered: true,
isMe: false,
)
);
messages.add(
Bubble(
message: 'answser message 1111',
date: DateTime.parse("2022-03-30 13:29:33"),
delivered: true,
isMe: true,
seen: true,
)
);
messages.add(
DateChip(
date: DateTime(now.year, now.month, now.day - 1),
)
);
messages.add(
Bubble(
message: 'message 2222 2222',
date: DateTime.parse("2022-03-31 09:02:09"),
delivered: true,
isMe: false,
)
);
messages.add(
Bubble(
message: 'answser message 2222 2222',
date: DateTime.parse("2022-03-31 09:37:23"),
delivered: true,
isMe: true,
seen: true,
)
);
messages.add(
DateChip(
date: DateTime(now.year, now.month, now.day),
)
);
messages.add(
Bubble(
message: 'message 3333 3333 3333 3333333333 3333 3333 33',
date: DateTime.parse("2022-03-31 09:02:09"),
delivered: true,
isMe: false,
)
);
messages.add(
Bubble(
message: 'answser message 3333 3333 3333 3333333333 3333 3333 33',
date: DateTime.parse("2022-03-31 09:37:23"),
delivered: true,
isMe: true,
seen: true,
)
);
}
@override
Widget build(BuildContext context) {
setSampleMessages(messages, DateTime.now());
return Scaffold(
backgroundColor: Colors.blueGrey.shade50,
appBar: AppBar(
backgroundColor: const Color.fromRGBO(11, 80, 31, 1.0),
elevation: .9,
title: Text(
widget.title,
style: const TextStyle(color: Colors.white),
),
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onPressed: () {},
),
actions: <Widget>[
IconButton(
icon: const Icon(
Icons.videocam,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.call,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.more_vert,
color: Colors.white,
),
onPressed: () {},
)
],
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.separated(
itemBuilder: (context, index) {
return messages[index];
},
separatorBuilder: (context, index) {
return const SizedBox(height: 1);
},
itemCount: messages.length,
),
),
);
}
}
class Bubble extends StatelessWidget {
const Bubble({required this.message, required this.date, required this.delivered,
this.seen = false, required this.isMe});
final String message;
final DateTime date;
final bool delivered, isMe, seen;
@override
Widget build(BuildContext context) {
final time = '${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
final bg = isMe ? Colors.greenAccent.shade100 : Colors.white;
final align = isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start;
final icon = delivered ? Icons.done_all : Icons.done;
final margin = isMe ? const EdgeInsets.fromLTRB(40, 4, 4, 4) : const EdgeInsets.fromLTRB(4, 4, 40, 4);
final color = seen ? Colors.lightBlue : Colors.black38;
final radius = isMe
? const BorderRadius.only(
topLeft: Radius.circular(20.0),
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20),
)
: const BorderRadius.only(
topRight: Radius.circular(20.0),
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
);
return Column(
crossAxisAlignment: align,
children: <Widget>[
Container(
//margin: const EdgeInsets.all(3.0),
margin: margin,
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: .5,
spreadRadius: 1.0,
color: Colors.black.withOpacity(.12)
)
],
color: bg,
borderRadius: radius,
),
child: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(2, 2, 4, 2),
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: message,
style: const TextStyle(fontSize: 16)),
const WidgetSpan(
child: SizedBox(
width: 50,
child: Text(' '),
),
),
// TextSpan(text: ' '),
]
),
),
),
Positioned(
right: 1,
bottom: -2,
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: time,
style: const TextStyle(
color: Colors.black38,
fontSize: 12.0,
)
),
const WidgetSpan(
child: SizedBox(width: 1),
),
WidgetSpan(
child: Icon(
icon,
size:15,
color: color,
),
),
],
),
),
),
],
),
),
],
);
}
}
class DateChip extends StatelessWidget {
final DateTime date;
final Color color;
const DateChip({
Key? key,
required this.date,
this.color = Colors.white, // const Color(0xffffffff),
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(6)),
color: color,
),
margin: const EdgeInsets.all(6),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text(
Algo.dateChipText(date),
),
),
), ]
);
}
}
///all the algorithms of the plugin
///[dateChipText] to get the text which is need to show on the [DateChip]
abstract class Algo {
Algo._();
static String dateChipText(final DateTime date) {
final dateChipText = DateChipText(date);
return dateChipText.getText();
}
}
///initial formatter to find the date txt
final DateFormat _formatter = DateFormat('yyyy-MM-dd');
///[DateChipText] class included with algorithms which are need to implement [DateChip]
///[date] parameter is required
///
class DateChipText {
final DateTime date;
DateChipText(this.date);
///generate and return [DateChip] string
///
///
String getText() {
final now = DateTime.now();
if (_formatter.format(now) == _formatter.format(date)) {
return 'Today';
} else if (_formatter
.format(DateTime(now.year, now.month, now.day - 1)) ==
_formatter.format(date)) {
return 'Yesterday';
} else {
return '${DateFormat('d').format(date)} ${DateFormat('MMMM').format(date)} of ${DateFormat('y').format(date)}';
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment