Flutter 颤振:如何使聊天信息中的电报式气泡
电流输出: 预期产出:Flutter 颤振:如何使聊天信息中的电报式气泡,flutter,dart,flutter-layout,Flutter,Dart,Flutter Layout,电流输出: 预期产出: Align( alignment: Alignment.topRight, child: Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), margin: EdgeInsets.only(right: 12, top: 8), decoration: BoxDecoration( color: Color(0xFF48699
Align(
alignment: Alignment.topRight,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
margin: EdgeInsets.only(right: 12, top: 8),
decoration: BoxDecoration(
color: Color(0xFF486993),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Text("This is my message"),
),
)
代码:
Align(
alignment: Alignment.topRight,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
margin: EdgeInsets.only(right: 12, top: 8),
decoration: BoxDecoration(
color: Color(0xFF486993),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Text("This is my message"),
),
)
给你:
import 'package:flutter/material.dart';
void main() => runApp(
MyApp()
);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Padding(
padding: EdgeInsets.all(7),
child: Align(
alignment: Alignment.centerRight,
child: Stack(
children: [
Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
decoration: BoxDecoration(
color: Color(0xFF486993),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: 'This is telegram message ',
style: TextStyle(
color: Colors.white,
fontSize: 14.0
),
),
TextSpan(
text: '3:16 PM',
style: TextStyle(
color: Colors.grey,
fontSize: 12.0,
fontStyle: FontStyle.italic
),
),
],
),
),
Icon(Icons.check, color: Color(0xFF7ABAF4), size: 16,)
]
),
),
Positioned(
bottom: 0,
right: 0,
child: CustomPaint(
painter: ChatBubbleTriangle(),
)
)
]
)
),
),
);
}
}
class ChatBubbleTriangle extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = Color(0xFF486993);
var path = Path();
path.lineTo(-15, 0);
path.lineTo(0, -15);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(
MyApp()
);
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主页:填充(
填充:边缘设置。全部(7),
子对象:对齐(
对齐:alignment.centerRight,
子:堆栈(
儿童:[
容器(
填充:常量边集。对称(垂直:8,水平:20),
装饰:盒子装饰(
颜色:颜色(0xFF486993),
borderRadius:borderRadius.all(半径圆形(20)),
),
孩子:排(
mainAxisSize:mainAxisSize.min,
儿童:[
RichText(
text:TextSpan(
儿童:[
TextSpan(
文字:“这是电报信息”,
样式:TextStyle(
颜色:颜色,白色,
字体大小:14.0
),
),
TextSpan(
文本:“下午3:16”,
样式:TextStyle(
颜色:颜色。灰色,
字体大小:12.0,
fontStyle:fontStyle.italic
),
),
],
),
),
图标(Icons.check,颜色:颜色(0xFF7ABAF4),大小:16,)
]
),
),
定位(
底部:0,
右:0,,
孩子:定制油漆(
画师:ChatBubbletTriangle(),
)
)
]
)
),
),
);
}
}
类ChatBubbletTriangle扩展了CustomPainter{
@凌驾
空心油漆(帆布,尺寸){
var paint=paint()…color=color(0xFF486993);
var path=path();
path.lineTo(-15,0);
行至(0,-15)的路径;
lineTo(0,0);
画布.绘制路径(路径,绘制);
}
@凌驾
bool应重新绘制(自定义代理){
返回true;
}
}
您必须更改paint
方法,因为现在它只是一个三角形
否则,它看起来就像你要求的那样。我自己试图重新创建电报布局,我想出了这个来制作形状
enum _TailDirection { right, left }
class ChatBubblePainter extends CustomPainter {
ChatBubblePainter({this.color, this.isSentByMe});
final Color color;
final bool isSentByMe;
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
Path paintBubbleTail(_TailDirection direction) {
double startingPoint;
double point;
double endPoint;
double curvePoint;
if (direction == _TailDirection.right) {
startingPoint = size.width - 5;
point = size.width + 10;
endPoint = size.width + 3;
curvePoint = size.width;
}
if (direction == _TailDirection.left) {
startingPoint = 5;
point = -10;
endPoint = -3;
curvePoint = 0;
}
return Path()
..moveTo(startingPoint, size.height)
..lineTo(point, size.height)
..quadraticBezierTo(endPoint, size.height, curvePoint, size.height - 10);
}
final RRect bubbleBody = RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(5.0));
final Path bubbleTail = isSentByMe
? paintBubbleTail(_TailDirection.right)
: paintBubbleTail(_TailDirection.left);
canvas.drawRRect(bubbleBody, paint);
canvas.drawPath(bubbleTail, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
下面是在flatter中创建整洁的语音泡泡所需要的 首先创建一个扩展painter类的自定义painter类
class CustomChatBubble extends CustomPainter {
CustomChatBubble({this.color, @required this.isOwn});
final Color color;
final bool isOwn;
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color ?? Colors.blue;
Path paintBubbleTail() {
Path path;
if (!isOwn) {
path = Path()
..moveTo(5, size.height - 5)
..quadraticBezierTo(-5, size.height, -16, size.height - 4)
..quadraticBezierTo(-5, size.height - 5, 0, size.height - 17);
}
if (isOwn) {
path = Path()
..moveTo(size.width - 6, size.height - 4)
..quadraticBezierTo(
size.width + 5, size.height, size.width + 16, size.height - 4)
..quadraticBezierTo(
size.width + 5, size.height - 5, size.width, size.height - 17);
}
return path;
}
final RRect bubbleBody = RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(16));
final Path bubbleTail = paintBubbleTail();
canvas.drawRRect(bubbleBody, paint);
canvas.drawPath(bubbleTail, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
然后在聊天屏幕中使用它。请注意,此屏幕仅用于演示目的,因此您可以根据需要对其进行修改
class ChatSampleWidget extends StatefulWidget {
@override
_ChatSampleWidgetState createState() => _ChatSampleWidgetState();
}
class _ChatSampleWidgetState extends State<ChatSampleWidget> {
TextEditingController _editingController = TextEditingController();
FocusNode _focusNode = FocusNode();
final TextStyle textStyle = TextStyle(color: Colors.white);
@override
void initState() {
super.initState();
}
@override
dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chatter'),
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
CustomPaint(
painter: CustomChatBubble(isOwn: false),
child: Container(
padding: EdgeInsets.all(8),
child: Text(
'Message from someone else \n Says sometihngs',
style: textStyle,
))),
],
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
CustomPaint(
painter:
CustomChatBubble(color: Colors.grey, isOwn: false),
child: Container(
padding: EdgeInsets.all(10),
child: FlutterLogo())),
],
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CustomPaint(
painter:
CustomChatBubble(color: Colors.green, isOwn: true),
child: Container(
padding: EdgeInsets.all(8),
child: Text(
'Message from me',
style: textStyle,
))),
],
)
],
),
),
Positioned(
bottom: 0,
child: Container(
padding: EdgeInsets.all(8),
width: MediaQuery.of(context).size.width,
color: Colors.grey.withOpacity(0.1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: TextField(
controller: _editingController,
focusNode: _focusNode,
decoration:
InputDecoration(hintText: 'Say something...'),
),
),
IconButton(
icon: Icon(
Icons.send,
size: 30,
),
onPressed: () {
print(_editingController.text);
})
],
),
))
],
),
),
);
}
}
class ChatSampleWidget扩展了StatefulWidget{
@凌驾
_ChatSampleWidgetState createState()=>\u ChatSampleWidgetState();
}
类ChatSampleWidgetState扩展状态{
TextEditingController _editingController=TextEditingController();
FocusNode_FocusNode=FocusNode();
最终文本样式文本样式=文本样式(颜色:Colors.white);
@凌驾
void initState(){
super.initState();
}
@凌驾
处置{
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“聊天”),
),
正文:安全区(
子:堆栈(
儿童:[
容器(
填充:边缘设置。全部(20),
子:列(
mainAxisAlignment:mainAxisAlignment.start,
儿童:[
划船(
mainAxisAlignment:mainAxisAlignment.start,
儿童:[
定制油漆(
油漆工:定制泡沫(isOwn:false),
子:容器(
填充:边缘设置。全部(8),
子:文本(
'来自其他人的消息\n说了些什么',
风格:textStyle,
))),
],
),
大小盒子(
身高:5,,
),
划船(
mainAxisAlignment:mainAxisAlignment.start,
儿童:[
定制油漆(
画家:
CustomChatBubble(颜色:Colors.grey,isOwn:false),
子:容器(
填充:边缘设置。全部(10),
child:flatterlogo()),
],
),
大小盒子(
身高:5,,
),
划船(
mainAxisAlignment:mainAxisAlignment.end,
儿童:[
定制油漆(
画家:
CustomChatBubble(颜色:Colors.green,isOwn:true),
子:容器(
填充:边缘设置。全部(8),
子:文本(
“我的消息”,
风格:textStyle,
))),
],
)
],
),
),
定位(
底部:0,
子:容器(
填充:边缘设置。全部(8),
宽度:MediaQuery.of(context).size.width,