フラッター模倣WeChatプロジェクトコンバット4(チャットリスト、リストポップアップレイヤー)

序文

ネットワークリクエストは以前に紹介されていますが、ここでは主にチャットリストの作成を紹介し、そこでブレットレイヤーをスキャンします。ブレットレイヤーは主にシステムコントロールを使用します。PopupMenuButton

ps:ポップアップウィンドウを自分でカスタマイズしたい場合は、Dialogのカスタマイズの概要があります。

送信元アドレス

カスタムダイアログポップアップレイヤーアドレス

チャットリスト

前回の紹介によるとListView.builder、チャットリストの実装は実際には非常に簡単です。ここでは、主にListTileクラスこれにより、少なくとも一部のコードのネストを減らすことができます。

効果を最初に見てください

image.png

コードは次のようになります。

//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フレームワークを介してリクエストされ、使用するクラスに段階的に変換されます

//这里主要简介数据获取,网络失败后的 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']);
  }
}
复制代码

爆弾レイヤーをスイープします

WeChatチャットページの右上隅にあるプラス記号をクリックすると、スキャン用のクリックインターフェイスがポップアップ表示され、最初に効果が表示されます。

image.png

まず、右側のポップアップレイヤーのデータ情報を宣言します。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()
);
复制代码

やっと

ぜひお試しください。使用すればするほど簡単になります。

おすすめ

転載: juejin.im/post/7087422451893665828