Flutter高仿微信-第26篇-新的朋友

news2024/10/6 1:40:41

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

详情请查看

效果图:

实现代码:

/**
 * Author : wangning
 * Email : maoning20080809@163.com
 * Date : 2022/8/17 15:48
 * Description : 新的朋友
 */
class NewFriends extends StatelessWidget {
  const NewFriends({super.key});

  @override
  Widget build(BuildContext context) {
    return const NewFriendsPage(title: '新的朋友');
  }
}

class NewFriendsPage extends StatefulWidget {
  const NewFriendsPage({super.key, required this.title});
  final String title;
  @override
  State<NewFriendsPage> createState() => _NewFriendsPageState();
}

class _NewFriendsPageState extends State<NewFriendsPage> {
  final ScrollController _scrollController = ScrollController(); //listview 的控制器
  List<ContactsBeanComb> _contactList = [];

  var json; //是否正在加载数据
  @override
  void initState() {
    super.initState();
    _updateStatus();
    _getData();
    //下面这个方法每次都底部都会执行,上面的代码只会执行一次
    _scrollController.addListener(() {
      if (_scrollController.position.pixels >
          _scrollController.position.maxScrollExtent - 20) {
        _getData();
      }
    });
  }

  //更改状态
  void _updateStatus() async {
    ContactsRepository.getInstance().updateContactStatusRead();
    Map<String, Object> result = HashMap<String, Object>();
    eventBus.emit(BaseEvent(BaseEvent.TYPE_READ_FRIENDS, result: result));
  }

  //加载数据
  _getData() async {
    List<ContactsBeanComb> contactList = await ContactsRepository.getInstance().findAllContactsCombNew();
    _contactList = [];
    setState(() {
      _contactList = contactList;
    });
  }

  //没有好友请求显示
  Widget _noDataWidget() {
    return Center(
      child: Padding(
        padding: EdgeInsets.all(10.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text('没有新的朋友...',style: TextStyle(fontSize: 16.0),)
          ],
        ),
      ),
    );
  }

  Future<void> _onRefresh() async {
    await Future.delayed(Duration(seconds: 3), () {
      LogUtils.d('通讯录refresh');
    });
  }

  //接受好友邀请
  void _receiveFriends(ContactsBeanComb contactsBeanComb){
    XmppManager.getInstance().createRoster(contactsBeanComb.toAccount);
    ContactsBean contactsBean = ContactsBean();
    contactsBean.id = contactsBeanComb.id;
    contactsBean.fromAccount = contactsBeanComb.fromAccount;
    contactsBean.toAccount = contactsBeanComb.toAccount;
    contactsBean.type = ContactsBean.typeReceive;
    contactsBean.addTime = contactsBeanComb.addTime;
    ContactsRepository.getInstance().updateContactLocal(contactsBean);
    ContactsRepository.getInstance().updateContactServer(contactsBean);
    ChatSendBean chatSendBean = ChatSendBean();
    chatSendBean.contentType = CommonUtils.TYPE_RECEIVE_FRIENDS;
    chatSendBean.content = contactsBeanComb.toAccount;
    String message = jsonEncode(chatSendBean);
    _sendMessage(contactsBeanComb.fromAccount, message);

    Map<String, Object> result = HashMap<String, Object>();
    eventBus.emit(BaseEvent(BaseEvent.TYPE_RECEIVE_FRIENDS, result: result));
    Navigator.pop(context);
  }

  //发送消息
  _sendMessage(String toAccount, var message){
    int id = DateTime.now().millisecondsSinceEpoch;
    String account = SpUtils.getString(CommonUtils.LOGIN_ACCOUNT);
    String toJid = toAccount + "@wangning";
    XmppManager.getInstance().sendMessage(toJid, message, "$account", id);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: WnAppBar.getAppBar(context, Text("${widget.title}")),

      body: Column(
        children: [
          Expanded(
              child:_contactList.length > 0
                  ? RefreshIndicator(
                  onRefresh: _onRefresh,
                  child: ListView.builder(
                      itemCount: _contactList.length,
                      controller: _scrollController,
                      itemBuilder: (context, index) {
                        return InkWell(
                          onLongPress: (){
                            _showDeleteDialog(_contactList[index].fromAccount, _contactList[index].toAccount);
                          },
                          onTap: (){
                          },
                          child: Container(
                            decoration: BoxDecoration(border: Border(bottom:BorderSide(color: Color(0xffd9d9d9), width: 0.3))),
                            width: double.infinity,
                            padding: EdgeInsets.only(left: 14, top: 10, bottom: 10),
                            child: Row(
                              children: [
                                CommonAvatarView.showBaseImage(_contactList[index].avatar),
                                SizedBox(width: 12,),
                                Text(_contactList[index].nickName, maxLines: 1,style: TextStyle(fontSize: 18, color: Colors.black, fontWeight: FontWeight.bold),),
                                SizedBox(width: 12,),
                                Expanded(child: SizedBox()),//自动扩展挤压
                                _getFriendsStatus(_contactList[index]),
                              ],
                            ),
                          ),
                        );

                      }))
                  : _noDataWidget()
          ),

        ],
      ),
    );
  }

  //删除对话框
  Future<void> _showDeleteDialog(String fromAccount, String toAccount) async {
    return showDialog<Null>(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('确定要删除该好友吗?', style: new TextStyle(fontSize: 17.0)),
            actions: <Widget>[
              MaterialButton(
                child: Text('取消'),
                onPressed: (){
                  LogUtils.d("确定取消");
                  Navigator.of(context).pop();
                },
              ),
              MaterialButton(
                child: Text('确定'),
                onPressed: (){
                  LogUtils.d("确定删除");
                  Navigator.pop(context);
                  _deleteContacts(fromAccount, toAccount);
                },
              )
            ],
          );
        }
    );
  }

  //删除联系人
  _deleteContacts(String fromAccount, String toAccount) async{
    bool deleteServerFlag = await ContactsRepository.getInstance().deleteContactsByAccountServer(fromAccount, toAccount);
    if(deleteServerFlag){
      bool deleteFlag = await ContactsRepository.getInstance().deleteContactsByAccount(fromAccount, toAccount);
      if(deleteFlag){
        CommonToast.show(context, "删除成功!");
        _getData();
      } else {
        CommonToast.show(context, "删除失败!");
      }
    } else {
      CommonToast.show(context, "删除失败!");
    }
  }

  Widget _getFriendsStatus(ContactsBeanComb contactsBeanComb){
    String account = SpUtils.getString(CommonUtils.LOGIN_ACCOUNT);
    LogUtils.d("新的朋友 _getFriendsStatus ${account} , ${contactsBeanComb.fromAccount}, ${contactsBeanComb.toAccount}");
    if(contactsBeanComb.fromAccount == account) {
      LogUtils.d("已发送");
      return GestureDetector(
        onLongPress: (){
          _receiveFriends(contactsBeanComb);
        },
        child: Container(
          margin: EdgeInsets.only(left: 12.0, right: 12),
          child: Text("已发送"),
        ),
      );
    } else if(contactsBeanComb.type == ContactsBean.typeRequest||contactsBeanComb.type == ContactsBean.typeRead){
      LogUtils.d("同意按钮");
      return Container(
        margin: EdgeInsets.only(left: 12.0, right: 12),
        child: MaterialButton(
          color: Colors.green,
          textColor: Colors.white,
          child: Text("同意"),
          onPressed: (){
            LogUtils.d("新的朋友点击添加");
            _receiveFriends(contactsBeanComb);
          },
        ),
      );
    }
    return Text("");
  }
}

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

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

相关文章

智慧餐厅解决方案-最新全套文件

智慧餐厅解决方案-最新全套文件一、建设背景二、建设思路1、刺激消费手段单一2、用户信息反馈量少3、商家推广覆盖面小4、生产力利用率偏低三、建设方案1 、组织人事在线管理&#xff0c;盘活内部人力资源2、多样化考勤方式&#xff0c;轻松实现多地工时管理3、数据成本分析&am…

大数据(9f)Flink状态编程

文章目录概述Managed StateOperator StateListStateBroadcastStateKeyed StateValueStateListStateMapStateReducingStateAggregatingState状态后端Appendix概述 流式计算 分为 无状态计算 和 有状态计算 流处理的状态功能&#xff1a;去重、监控…… 状态分类Managed StateR…

半诚实模型与恶意模型

原创 洪澄 开放隐私计算 开放隐私计算 开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服务区”。 178篇…

【Unity】自定义Untiy天空

3、需求&#xff1a;更改默认天空盒&#xff0c;360显示所需的内容。 实施&#xff1a; 准备材料&#xff1a;一张8K图&#xff08;更清晰&#xff09; 步骤&#xff1a; 1、更改Camera为天空盒&#xff1b; 2、制作图片&#xff0c;怎么制作不说了&#xff0c;分辨率8192…

Linux服务器安装部署最新稳定版本mongoDB社区版- Ubuntu-20.04版本

没有玩过mongoDB&#xff0c;安装一次真&#x1f92c;波折&#xff0c;再次建议大家安装之前&#xff0c;一定要确定好服务器的操作系统&#xff0c;可以参考查看linux操作系统版本&#xff1a;Ubuntu&#xff1f;Centos&#xff1f;还是其他&#xff1f; 接前面在本地自测需要…

解决jupyter下载好了库,但是无法使用的问题。以及补充jupyter如何下载新的库。

文章目录出现原因验证解决步骤补充国内常用镜像源出现原因 出现这个问题的主要原因是&#xff0c;jupyter的内核&#xff08;或者说他使用的Python环境&#xff09;与下载库的环境不一样&#xff0c;解决办法就是更改kernel。换句话说就是将jupyter下载库的环境加入到内核环境…

模拟双色球系统——Java

目录 一、内容简介 二、 基本流程 三、具体步骤 1.菜单栏 2.随机生成幸运号码 3.用户输入 4.判断中奖情况 5.打印数组 四、代码实现 五、效果展示 一、内容简介 双色球是彩票的一种玩法&#xff0c;规则如下&#xff1a; 红球一共6组&#xff0c;每组从1——33中随…

微信h5 使用jssdk支付成功后,点击完成 页面关闭了,引出微信“点金计划“

可能会迷惑 为啥我们之前没有碰见过这种情况! 这样的情况只有两种情况,就是 你只是普通商户不是微信特约商户你的支付跳转功能还未被微信回收 那么怎么才能支付成功重新跳回自己的网站页面 刚开始经历这种情况的童鞋, 可能有点懵逼 先看个微信的之前发的一个公告吧 微信支付公…

面试系列分布式事务:谈谈3PC的理解

3PC就是三阶段提交是在二阶段提交上的改进版本&#xff0c;3PC最关键要解决的就是协调者和参与者同时挂掉的问题&#xff0c;所以3PC把2PC的准备阶段再次一分为二&#xff0c;这样三阶段提交。处理流程如下 &#xff1a; 阶段一 a) 协调者向所有参与者发出包含事务内容的 canCo…

【深入浅出Java并发编程指南】「实战篇」教你如何使用AbstractQueuedSynchronizer实现自己的同步器组件

前提概要 之前的文章中会涉及到了相关AQS的原理和相关源码的分析&#xff0c;所谓实践是检验真理的唯一标准&#xff01;接下来就让我们活化一下AQS技术&#xff0c;主要针对于自己动手实现一个AQS同步器。 定义MyLock实现Lock Doug Lea大神在JDK1.5编写了一个Lock接口&#xf…

【C++】模拟实现STL容器:vector

目录 一、vector迭代器失效问题 1、Visual Studio和g对迭代器失效问题的表现 2、解决迭代器失效的方法 二、模拟实现构造函数调用不明确 1、问题描述 2、解决调用不明确的方法 三、reserve中的深浅拷贝问题 1、reserve中浅拷贝发生原因 2、浅拷贝发生的图解 3、解决方…

vue.js毕业设计,基于vue.js前后端分离外卖点餐系统设计与实现(H5移动项目)

功能介绍 【后台管理员功能】 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删除 录入资讯&#xff1a;录入资讯标题、内容等信息 管理资讯&#xff1a;查看已录入资讯列表&#xff0c;支持删除和修改 广告设置&#xff1a;上传图片和设置小程序首页轮播图广告地…

用Python代码画世界杯吉祥物拉伊卜(附代码)

用Python代码画世界杯吉祥物拉伊卜&#xff08;附代码&#xff09; 世界杯正在火热进行中&#xff0c;世界杯的吉祥物拉伊卜也非常火。 本文用Python代码画世界杯吉祥物。不废话&#xff0c;可以直接先看视频效果。 视频效果 用Python代码画世界杯吉祥物拉伊卜实现方法介绍 …

运用滤波反投影的方法对图像进行重建matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 直接由正弦图得到反投影图像&#xff0c;会存在严重的模糊&#xff0c;这是早期 CT 系统所存在的问题。傅立叶中心切片定理表明&#xff0c;投影的一维傅立叶变换是得到投影区域的二维傅…

360安全卫士弹窗广告怎么彻底关闭

如何关闭360广告弹窗&#xff1f;有时候我们在电脑上看一些视频或者整理一些文件时&#xff0c;经常莫名其妙会出现一些广告弹窗&#xff0c;即使是关了也还会出现&#xff0c;很是影响用户体验感&#xff0c;那么怎么彻底关闭呢&#xff1f;下面给大家介绍具体教程&#xff0c…

【单目3D目标检测】GUPNet论文精读与代码解析

文章目录PrefaceAbstractContributionsPipelineBackboneNeckHeadLossGUPIn PaperIn CodeHTLIn PaperIn CodeRefernecePreface Lu Y, Ma X, Yang L, et al. Geometry uncertainty projection network for monocular 3d object detection[C]. Proceedings of the IEEE/CVF Intern…

ActivitiListener

ActivitiListener目录概述需求&#xff1a;设计思路实现思路分析1.ActivitiListener2.Activity3.Gateway5.FieldExtensionIOSpecification参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip ha…

骨传导原理是什么?哪些骨传导耳机值得入手

​骨传导耳机是目前耳机市场比较流行耳机&#xff0c;深受年轻一族和运动达人的喜爱。但尽管这种产品受到很多人的青睐&#xff0c;相较传统耳机&#xff0c;大众对骨传导耳机的认识和程度并不高&#xff0c;也有很多小伙伴不知道骨传导耳机的原理是怎么发声的&#xff0c;骨传…

Vue子组件传自定义属性给父组件

我们知道组件之间是不能够之间进行通信的&#xff0c;都是相互独立的&#xff0c;你用不了我的状态和方法&#xff0c;我也用不了你的&#xff0c;那如何实现通信呢&#xff0c;可以间接实现&#xff1b; 实现父组件和子组件的通信&#xff1a; 子组件想用父组件的状态需要父…

Java并发之线程池

文章目录前言一、Java中线程池概览1.1 类图1.2 内部流程图二、源码探索2.1 构造参数2.2 线程池状态2.3 Worker 的添加和运行2.4 阻塞队列2.5 任务拒绝策略三、实际使用3.1 动态线程池3.2 拓展使用3.3 springboot 中线程池参考前言 在高并发的 Java 程序设计中&#xff0c;编写…