Flutter高仿微信系列共59篇,从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。
详情请查看
效果图:



详情请参考 Flutter高仿微信-第29篇-单聊 , 这里只是提取红包功能的部分代码。
实现代码:
//我的红包
Widget meRedpacketWidget(){
return GestureDetector(
onTap: (){
//点击红包
Navigator.push(context, MaterialPageRoute(builder: (context) => ReceiveRedpacketSuccess(fromUser: widget.meUserBean?.account??"", toUser: widget.otherUserBean?.account??"", balance: widget.chatBean?.content??"", addTime: widget.chatBean.addTime??"",)));
},
child: Container(
child: Stack(
children: [
meRedpacketBackground(),
Positioned(
left: 20, top: 20,
child:CommonUtils.getBaseIconPng("wc_redpacket_icon", width: 40, height: 40),
),
Positioned(
left: 70, top: 30,
child: Text("恭喜发财,大吉大利", style: TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold),),
),
Positioned(
left: 70, top: 50,
child: Container(
margin: EdgeInsets.only(top:10),
width: 120,
height: 1,
color: Colors.white,
),
),
Positioned(
left: 20, bottom: 14,
child:Text("私人红包", style: TextStyle(fontSize: 12, color: Colors.white38),),
),
],
),
),
);
}
//朋友发来的红包
Widget toRedpacketWidget(){
return GestureDetector(
onTap: (){
if(widget.chatBean.isClick == 1){
Navigator.push(context, MaterialPageRoute(builder: (context) => ReceiveRedpacketSuccess(fromUser: widget.meUserBean?.account??"", toUser: widget.otherUserBean?.account??"", balance: widget.chatBean?.content??"", addTime: widget.chatBean.addTime??"",)));
} else {
showRedPacket(context, _onOpenRedpacket, widget.otherUserBean?.account, widget.chatBean?.content??"", widget.index);
}
},
child: Opacity(
opacity: widget.chatBean.isClick == 1 ? 0.6 :1,
child: Container(
child: Stack(
children: [
toRedpacketBackground(),
Positioned(
left: 38, top: 20,
child:CommonUtils.getBaseIconPng("wc_redpacket_icon", width: 40, height: 40),
),
Positioned(
left: 88, top: 30,
child: Text("恭喜发财,大吉大利", style: TextStyle(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold),),
),
Positioned(
left: 88, top: 50,
child: Container(
margin: EdgeInsets.only(top:10),
width: 120,
height: 1,
color: Colors.white,
),
),
Positioned(
left: 38, bottom: 14,
child:Text("私人红包", style: TextStyle(fontSize:12, color: Colors.white38),),
),
],
),
),
),
);
}
//红包背景
Widget toRedpacketBackground(){
return CustomPaint(
painter: RedPacketOther(
strokeColor: Color(0xFFf58220),
paintingStyle:
PaintingStyle.fill,
),
child: Container(
height: 100,
width: 280,
),
);
}
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/9/24 12:09
* Description : 点击查看红包弹出框
*/
void showRedPacket(BuildContext context, Function? onOpen, String? toUser, String balance, int position){
entry = OverlayEntry(builder: (context) => RedPacket(onFinish: _removeRedPacket, onOpen: onOpen, toUser: toUser, balance: balance, position: position,));
Overlay.of(context)?.insert(entry!);
}
void _removeRedPacket(){
entry?.remove();
entry = null;
}
class RedPacket extends StatefulWidget {
String? toUser;
String? balance;
int? position;
Function? onFinish;
Function? onOpen;
RedPacket({Key? key,this.onFinish, this.onOpen, this.toUser, this.balance, this.position}) : super(key: key);
@override
_RedPacketState createState() => _RedPacketState();
}
class _RedPacketState extends State<RedPacket> with TickerProviderStateMixin{
UserBean? _toUserBean;
late RedPacketController controller = RedPacketController(tickerProvider: this);
@override
void initState() {
super.initState();
controller.onOpen = widget.onOpen;
controller.onFinish = widget.onFinish;
_initUser();
}
_initUser() async {
_toUserBean = await UserRepository.getInstance().findUserByAccount(widget.toUser??"");
setState(() {
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Material(
color: Color(0x88000000),
child: GestureDetector(
child: ScaleTransition(
scale: Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(parent: controller.scaleController, curve: Curves.fastOutSlowIn)),
child: buildRedPacket(),
),
//onPanDown: (d) => controller.handleClick(d.globalPosition),
onPanDown: (d){
_handleClick(d);
},
),
);
}
void _handleClick(d) async {
bool isNetwork = await CommonNetwork.isNetwork();
if(!isNetwork) {
CommonUtils.showNetworkError(context);
return;
}
controller.handleClick(d.globalPosition, widget.position, widget.balance);
}
Widget buildRedPacket() {
return GestureDetector(
onTapUp: controller.clickGold,
child: CustomPaint(
size: Size(1.sw, 1.sh),
painter: RedPacketPainter(controller: controller),
child: buildChild(),
),
);
}
Widget buildChild() {
return AnimatedBuilder(
animation: controller.translateController,
builder: (context, child) => Container(
padding: EdgeInsets.only(top: 0.3.sh * (1 - controller.translateCtrl.value)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(3.w),
child: CommonAvatarView.showBaseImage(_toUserBean?.avatar??""),
),
SizedBox(width: 5.w,),
Text("${_toUserBean?.nickName}", style: TextStyle(fontSize: 16.sp, color: Color(
0xFFF8E7CB), fontWeight: FontWeight.w500),)
],
),
SizedBox(height: 15.w,),
Text("恭喜发财,大吉大利", style: TextStyle(fontSize: 18.sp, color: Color(
0xFFF8E7CB)),)
],
),
),
);
}
}
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/11/1 19:51
* Description : 领取红包成功页面
*/
class ReceiveRedpacketSuccess extends StatefulWidget{
String balance;
String toUser;
String fromUser;
String addTime;
ReceiveRedpacketSuccess({required this.fromUser, required this.toUser, required this.balance, required this.addTime});
@override
State<StatefulWidget> createState() => _ReceiveRedpacketSuccessState();
}
class _ReceiveRedpacketSuccessState extends State<ReceiveRedpacketSuccess>{
UserBean? _fromUserBean;
UserBean? _toUserBean;
@override
void initState() {
super.initState();
_initUser();
}
void _initUser() async {
_fromUserBean = await UserRepository.getInstance().findUserByAccount(widget.fromUser);
_toUserBean = await UserRepository.getInstance().findUserByAccount(widget.toUser);
LogUtils.d("账号:${widget.fromUser} , ${_fromUserBean?.toJson()}");
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: WnAppBar.getAppBar(context, Text("红包")),
body: Container(
child: Column(
children: [
nameWidget(),
SizedBox(height: 10,),
tipWidget(),
SizedBox(height: 30,),
balanceWidget(),
SizedBox(height: 80,),
meInfoWidget(),
],
),
),
);
}
//头像、昵称
Widget nameWidget(){
return Container(
margin: EdgeInsets.only(top: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CommonAvatarView.showBaseImage(_toUserBean?.avatar??""),
SizedBox(width: 10,),
Text(_toUserBean?.nickName??"", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),),
],
),
);
}
Widget tipWidget(){
return Text("恭喜发财,大吉大利", style: TextStyle(fontSize: 20, color: Colors.grey.shade600),);
}
//金额
Widget balanceWidget(){
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("${widget.balance}", style: TextStyle(fontSize: 48, color: Color(0xFFFFA500)),),
Baseline(baseline: 36.0,
//对齐字符底部水平线
baselineType: TextBaseline.alphabetic,
child: Text("元", style: TextStyle(fontSize: 18, color: Color(0xFFFFA500)),),
),
],
),
);
}
//我的个人信息
Widget meInfoWidget(){
String addTime = WnDateUtils.changeHM(widget.addTime??"");
return Container(
child: Stack(
children: [
Row(
children: [
Container(
margin: EdgeInsets.only(left: 12, top: 12, right: 12),
child: CommonAvatarView.showBaseImage(_fromUserBean?.avatar??"", 62, 62),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10,),
Text(_fromUserBean?.nickName??"", style: TextStyle(fontSize: 20),),
Text(addTime, style: TextStyle(fontSize: 20, color: Colors.grey.shade500),),
],
),
Expanded(child: Text("")),
Container(
margin: EdgeInsets.only(right: 12),
child: Text("${widget.balance}元", style: TextStyle(fontSize: 20),),
),
],
),
Positioned(
bottom: 1, right: 1,
child: Container(
margin: EdgeInsets.only(right: 12),
width: 300,
height: 1,
color: Colors.grey.shade400
,
),
),
],
),
);
}
}


















