Flutter高仿微信-第37篇-单聊-红包

news2025/8/13 3:44:30

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
                ,
              ),
          ),
        ],
      ),
    );
  }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33349.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二章:Pythonocc官方demo 案例47(获取物体的最优的包容体)

源代码&#xff1a; #!/usr/bin/env python ## ##This file is part of pythonOCC. ## ##pythonOCC is free software: you can redistribute it and/or modify ##it under the terms of the GNU Lesser General Public License as published by ##the Free Software Foundati…

Hadoop笔记-02 安装

文章目录1 VBOX安装CentOS71.1 安装VBOX软件1.2 下载CentOS7镜像文件1.3 初始化VBOX虚拟盘1.4 CentOS7网络配置1.5 CentOS7 yum源配置1.6 CentOS7 一般配置1.6.1关闭防火墙1.6.2 修改hostname1.6.3 配置DNS绑定1.6.4 关闭selinux2 JDK等基础安装配置2.1 安装JDK前检查2.2 安装t…

《Happy Birthday》游戏开发记录(送给朋友的小礼物)

游戏开发的学习记录⑦ 项目&#xff1a;Happy Birthday &#xff08;一个小小小游戏&#xff0c;基于unity给朋友做的一个生日小礼物&#x1f381;&#xff0c;之前都是礼物加信&#x1f48c;&#xff0c;今年想用自己的技能&#xff0c;把信的内容以另一种方式送给她。但在做…

STM32实战总结:HAL之modbus

什么是modbus&#xff1f; Modbus是一种串行通信协议&#xff0c;是Modicon公司&#xff08;现在的施耐德电气 Schneider Electric&#xff09;于1979年为使用可编程逻辑控制器&#xff08;PLC&#xff09;通信而发表。Modbus已经成为工业领域通信协议的业界标准&#xff08;De…

OsgEarth3基础3D图形实现

OsgEarth3基础3D图形实现主要难点Geometry能力姿态支持任意立方体 PolygonCube矩形立方体 Box圆锥体 Cone圆柱体 Cylinder四棱锥 Pyramid球体 Sphere源码示例ElementGeometry圆锥Cone这里尝试在通过OsgEarth提供的各种图形绘制方法&#xff0c;实现基础的3D图形。每个图形除了基…

推荐一个非常实用的程序员导航网站,码农必备!

这是一个非常好用的程序员导航网站&#xff0c;拥有该网站&#xff0c;就拥有一站式导航&#xff0c;再也不用为找网址而发愁了&#xff01; 先直接上网址&#xff1a;https://hao.panziye.com/ 现在来说说为什么推荐该程序员导航网站&#xff01; 1、支持自定义导航网址 该…

pytorch的安装教程

1. 官网 pytorch.org 哎呀呀呀&#xff0c;这是嘛呀哪里有download的按钮啊 别急 &#xff0c;往下拉就ok了哈哈 得看你自己电脑的配置了&#xff0c;自己选就行 、、注意哦 我们得复制一条指令 、 有anaconda的吧 在自己想要的环境里面 黏贴就行 有了 pytorch 可以干嘛呢…

Electron:BrowserView使用方法

我们知道&#xff0c;使用BrowserWindow来创建一个新的窗口&#xff0c;那么如果想在窗口中战胜斯更多的web内容&#xff0c;比如嵌入其他网站的内容&#xff0c;那就使用BrowserView了。 BrowserView的位置是相对于父窗口&#xff0c;比如&#xff1a; 代码如下&#xff1a;…

python项目使用pyinstaller打包

一、安装pyinstaller 打包要使用pyinstaller,使用pip来安装一下这个第三方库,打开命令行输入pip install pyinstaller 二、打包含有多个文件的python项目 1、首先打开电脑的cmd命令行,并切换到项目的根目录 项目路径输入cmd回车,可直接打开含有项目路径的cmd窗口 2、…

【推荐系统】行列式点过程(DPP)算法推导

一、背景 推荐系统主要解决用户和物品之间的相关性&#xff0c;以及推荐列表的多样性。相关性主要通过用户兴趣和物品之间的匹配程度来衡量&#xff0c;希望把用户感兴趣的物品推荐给用户&#xff0c;可以通过CTR预估模型来构建。多样性的衡量没有那么直观&#xff0c;一种方法…

std::unique_ptr(基础和仿写)

目录 一、C参考手册说明 1、解释注释 2、 参考代码 二、对std::unique_ptr分析 1、创建一个unique_ptr 2、无法进行复制构造和赋值操作 3、可以进行移动赋值 4.可以返回unique——ptr 5、管理动态数组 6、在容器中保存指针 三、对std::unique_ptr设计 1、对于的那个…

关于生命周期的面试题vue

1.第一次进入到页面&#xff08;组件&#xff09;会执行哪些生命周期 beforeCreate 》 没有data&#xff0c;没有elcreated 》 有data&#xff0c;没有elbeforeMount 》 有data&#xff0c;没有el&#xff08;其实已经在准备了&#xff09;mounted 》 有data&#xff0c;有el …

SRM供应商管理系统有什么作用?

目前国内稍具规模的企业都导入了企业资源管理ERP系统&#xff0c;实现了内部管理数字化转型&#xff0c;提升了内部各部门之间的协同能力。但是企业供应链管理涉及大量的外部资源&#xff0c;特别是数量庞大的供应商资源&#xff0c;而大部分的ERP系统很难实现采购同供应商之间…

感恩节,感谢2022的转变,有在好好生活!

疫情之下的感恩节 原来今天是感恩节。2022年快要结束了&#xff0c;在这样一个特别的节日里&#xff0c;就不写技术类文章了&#xff0c;写一写我的2022年&#xff0c;这一年&#xff0c;我的学习、工作和生活都有发生改变&#xff0c;感谢过去的时光&#xff0c;改变让我有在…

Linux下:文件与路径、用户管理、常用命令、vim

文章目录第一章&#xff1a; Linux文件与路径1.1 文件结构1.2 基本概念1.3 基本命令信息1.3.1 查看linux 系统信息&#xff08;修改主机名&#xff09;1.3.2 ls1.3.3 cd/pwd1.3.4 pushd命令创建目录栈 第二章&#xff1a; 文件/目录的创建、删除、复制、阅读2.1 mkdir2.2 touc…

书籍Java8 实战 笔记

第5章 使用流 本章内容 1.筛选、切片和匹配 2.查找、匹配和归约 3.使用数值范围等数值流 4.从多个源创建流 5.无限流 5.1 筛选和切片 用谓词筛选&#xff0c;筛选出各不相同的元素&#xff0c;忽略流中的头几个元素&#xff0c;或将流截短至指定长度。 5.1.1 用谓词筛选 就是…

【优化分配】粒子群算法求解火车票分配优化问题【含Matlab源码 1137期】

⛄一、粒子群算法简介 1 引言 自然界中的鸟群和鱼群的群体行为一直是科学家的研究兴趣所在。生物学家Craig Reynolds在1987年提出了一个非常有影响的鸟群聚集模型&#xff0c;在他的仿真中&#xff0c;每一个个体都遵循&#xff1a;避免与邻域个体相撞&#xff1a;匹配邻域个体…

vue3+vite中使用vuex

前言&#xff1a; 在vue3vite创建的项目中使用vuex&#xff0c;要注意的是vite有部分写法和之前的webpack是不同的&#xff0c;比如&#xff0c;他不支持 require&#xff0c;想把vue2的项目直接升级到vue3的时候&#xff0c;需要改很多地方&#xff0c;如果非要使用vite也可以…

Caffeine《二》

《Caffeine&#xff08;Java顶级缓存组件&#xff09;二》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Caffeine&#xff08;Java顶级缓存组件&#xff09;》《Caffeine&#xff08;Java顶级缓存组件&#xff09;二》8. 缓存驱逐算法8.1 FIFO(First …

ThingsBoard源码解析-设备连接

整体流程 在MqttTransportHandler中进行Mqtt消息处理&#xff0c;以AccessToken认证的设备举例&#xff0c;核心处理流程如下&#xff1a; //MqttTransportHandler 132 processMqttMsg(ctx, (MqttMessage) msg); //MqttTransportHandler 154 processConnect(ctx, (MqttConne…