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


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六毛六66

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值