前言

前面已经介绍过网络恳求了,这儿首要介绍谈天列表建立,还有扫一扫那里的弹层,该弹层首要选用体系控件 PopupMenuButton

ps:如果想自己定制弹窗,前面有介绍Dialog的自界说

源码地址

自界说dialog弹出层地址

谈天列表

依照之前的介绍,其实ListView.builder很容易就实现谈天列表,这儿介绍他首要是引出 ListTile 类,至少能削减一些代码嵌套

先看看作用

flutter-仿微信项目实战四(聊天列表、列表弹层)

代码如下所示:

//ListView.builder表格复用
ListView.builder(
    itemBuilder: itemForRow,
    itemCount: list.length,
)
//Row的作用如下
Widget itemForRow(BuildContext context, int index) {
  //这个便是跟微信首页谈天的相同,能够设置图片,标题内容
  final item = list[index];
  //运用ListTile组件
  return ListTile(
    //设置标题
    title: Text(item.name,
        style: const TextStyle(fontSize: 12, color: Colors.black87)),
    //设置子标题
    subtitle: Text(
      item.message,
      style: const TextStyle(fontSize: 12, color: Colors.black87),
      overflow: TextOverflow.ellipsis, //设置省掉作用
    ),
    //设置左边视图
    leading: CircleAvatar(backgroundImage: NetworkImage(item.imgUrl)),
  );
}

ListTile 默许没有下划线,如果想要下划线,外面包裹一层就能够了,如下所示

Column(
  children: [
    ListTile(
      title: Text(item.name,
          style: const TextStyle(fontSize: 12, color: Colors.black87)),
      subtitle: Text(
        item.message,
        style: const TextStyle(fontSize: 12, color: Colors.black87),
        overflow: TextOverflow.ellipsis, //设置省掉作用
      ),
      leading: CircleAvatar(backgroundImage: NetworkImage(item.imgUrl)),
    ),
    Row(
      children: [
        //两个Container都能够
        Container(width: 46, height: 1, color: Colors.white),
        //Container内容默许不会填充溢整个屏幕
        Expanded(child: Container(height: 1, color: const Color.fromRGBO(0xe1, 0xe1, 0xe1, 1))),
      ],
    )
  ],
);

谈天数据

经过 http 结构恳求,然后一步一步翻译成咱们运用的 class 类

//这儿首要简介数据获取,网络失败后的 catch 自行处理即可
Future<List<dynamic>> getData() async {
  //运用 http 结构的 get恳求网络数据,恳求的结果在body中,为 json字符串
  Response res = await get(
      Uri.parse("http://rap2api.taobao.org/app/mock/224518/api/chat/list"));
  //经过体系的 dart:convert 结构, 运用jsonDecode将json字符串转化为map
  final body = jsonDecode(res.body);
  //取出数据,转化为咱们的类
  final chatList = body["chat_list"];
  for (final item in chatList) {
    // fromJson为咱们界说的工厂结构方法,将 Map 转化为咱们的对象
    final chatData = ChatListData.formJson(item);
    list.add(chatData);
  }
  return list;
}

ChatListData 类的界说如下所示,由于没有看到 dart 反射相关,这部分内容只能自己编写了(不像JavaScript 没有class类的限制能够直接赋值与调用)

class ChatListData {
  final String imgUrl;
  final String name;
  final String message;
  ChatListData({required this.imgUrl, required this.name, required this.message});
  factory ChatListData.formJson(Map<String, dynamic> json) {
    return ChatListData(
        imgUrl: json["imageUrl"],
        name: json['name'],
        message: json['message']);
  }
}

扫一扫弹层

点击微信谈天页右上角加号,弹出扫一扫的点击界面,先看作用

flutter-仿微信项目实战四(聊天列表、列表弹层)

先声明一下右侧弹层的数据信息,这儿直接选用的 Map 处理,字节也能够放到一个类中,如下所示

List popList = [
  {'imgUrl': 'images/发起群聊.png', 'name': '发起群聊'},
  {'imgUrl': 'images/添加朋友.png', 'name': '添加朋友'},
  {'imgUrl': 'images/扫一扫1.png', 'name': '扫一扫'},
  {'imgUrl': 'images/收付款.png', 'name': '收付款'},
];

然后介绍弹层,弹层 PopupMenuButton 实际上显示默许是一个按钮组件,只是在加入了 Dialog,点击时会弹出弹窗层,多了这么一个功用而已

//导航
AppBar(
  title: const Text("谈天"),
  foregroundColor: Colors.black,
  backgroundColor: const Color.fromRGBO(0xe1, 0xe1, 0xe1, 1),
  elevation: 0, //去掉阴影
  //导航右侧按钮组
  actions: [
    //外部container能够用来调整间距,不放到里面的Container
    //是因为这个margin会添加点击区域,究竟外面包了一层TextButton相同的东西
    Container(
      margin: const EdgeInsets.only(right: 10),
      //运用 PopupMenuButton 来界说右侧点击弹层功用
      child: PopupMenuButton(
        //弹层什物位置,相对于当前组件的偏移
        offset: const Offset(0, 56),
        //咱们看到的按钮的信息,组件给其默许添加点击事情
        child: Container(
          width: 40,
          height: 40,
          alignment: Alignment.center,
          child: Image.asset("images/圆加.png", width: 20),
        ),
        //回来内部组件信息列表,单行 item 运用 PopupMenuItem
        //运用 .map<PopupMenuItem> 的原因能够动态生成多个 item
        itemBuilder: (BuildContext context) {
          return popList.map<PopupMenuItem>((item) {
            return PopupMenuItem(
              //水平布局,左边图片,右侧问题,中间间隔运用 Sizebox即可
              child: Row(
                children: [
                  Image.asset(item['imgUrl'], width: 18),
                  const SizedBox(width: 10),
                  Text(item['name'],
                      style: const TextStyle(color: Colors.white)),
                ],
              ),
            );
          }).toList();
        },
      ),
    )
  ],
),

只是这样发现,弹窗布景颜色不对,弹窗的布景咱们需要在 MaterialApp 组件的 theme 属性中加入cardColor才能够

MaterialApp(
  //去掉debug自选
  debugShowCheckedModeBanner: false,
  //Android任务管理器界面title,能够设置称自己的app姓名
  title: "Flutter Demo",
  theme: ThemeData(
    //这个便是设置默许弹层的布景颜色
    cardColor: const Color.fromRGBO(0x33, 0x33, 0x33, 0.8),
  ),
  home: const HomePage()
);

最后

快来试一下吧,越用越顺手