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


    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 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(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 createState() => _ReceiveRedpacketSuccessState();
    
    }
    
    class _ReceiveRedpacketSuccessState extends State{
    
      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
                    ,
                  ),
              ),
            ],
          ),
        );
      }
    
    
    }

  • 相关阅读:
    图像转换多样化图像生成在“分子优化”中的思考和Paper
    elasticsearch结构化查询(一)
    GO语言gin框架实战-03-swagger和接口文档
    Java反射详解
    进程-线程-协程
    【计算机组成原理】考研真题攻克与重点知识点剖析 - 第 2 篇:数据的表示和运算
    XAMPP的MySQL配置
    vue:find查找函数实际开发的使用
    RabbitMQ--延迟队列--使用/原理
    微信支付-商户平台
  • 原文地址:https://blog.csdn.net/maoning20080808/article/details/128020420