Flutter插件peter_package_demo的使用方法介绍

特性

该插件旨在帮助开发者快速实现类似微信通讯录页面的功能。以下是其主要特性:

  • 支持本地图片和网络图片展示。
  • 提供按首字母索引的快速滚动功能(类似于微信的索引条)。
  • 支持动态生成联系人列表,并可根据首字母自动分组。
  • 灵活配置页面布局和样式。

使用入门

前提条件

  • 确保已安装 Flutter SDK 和相关依赖。
  • pubspec.yaml 文件中添加以下依赖:
dependencies:
  peter_package_demo: ^1.0.0

然后运行以下命令更新依赖:

flutter pub get

初始化项目

创建一个新的 Flutter 项目并导入插件:

flutter create my_wechat_contact_app
cd my_wechat_contact_app

main.dart 中引入插件并使用示例代码。


使用示例

以下是一个完整的示例代码,展示如何使用 peter_package_demo 插件来构建一个类似微信通讯录页面的应用。

示例代码

import 'package:flutter/material.dart';
import 'package:peter_package_demo/peter_package_demo.dart' as peter;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const FriendsPage(),
    );
  }
}

// 单个联系人单元格
class _FriendCell extends StatelessWidget {
  final String? imageUrl; // 网络图片
  final String? name;
  final String? groupTitle;
  final String? imageAssets; // 本地图片

  _FriendCell({
    this.imageUrl,
    this.name,
    this.groupTitle,
    this.imageAssets,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 分组头部
        Container(
          alignment: Alignment.centerLeft,
          margin: const EdgeInsets.only(left: 10),
          height: groupTitle != null ? 30 : 0,
          color: peter.weChatThemeColor,
          child: groupTitle != null
              ? Text(
                  groupTitle!,
                  style: TextStyle(color: Colors.grey),
                )
              : null,
        ),
        // 联系人信息
        Container(
          color: Colors.white,
          child: Row(
            children: [
              // 头像
              Container(
                margin: EdgeInsets.all(10),
                width: 34,
                height: 34,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(5.0),
                  image: DecorationImage(
                    image: imageUrl != null
                        ? NetworkImage(imageUrl!)
                        : AssetImage(imageAssets!, package: 'peter_package_demo'),
                  ),
                ),
              ),
              // 名字
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Container(
                    height: 54,
                    child: Text(
                      name!,
                      style: const TextStyle(fontSize: 18),
                    ),
                  ),
                  // 分割线
                  Container(
                    color: peter.weChatThemeColor,
                    width: peter.screenWidth(context) - 54,
                    height: 0.5,
                  ),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

// 主页面
class FriendsPage extends StatefulWidget {
  const FriendsPage({Key? key}) : super(key: key);

  [@override](/user/override)
  _FriendsPageState createState() => _FriendsPageState();
}

class _FriendsPageState extends State<FriendsPage>
    with AutomaticKeepAliveClientMixin {
  Map<String, double> _groupOffsetMap = {
    peter.INDEX_WORDS[0]: 0.0, // 🔍
    peter.INDEX_WORDS[1]: 0.0, // ⭐️
  };

  final double _cellHeight = 54.5; // 每个单元格的高度
  final double _groupHeight = 30.0; // 分组头部高度
  ScrollController? _scrollController;

  final List<Widget> words = [];
  final List<Friends> _headerData = [
    Friends(imageAssets: 'images/新的朋友.png', name: '新的朋友'),
    Friends(imageAssets: 'images/群聊.png', name: '群聊'),
    Friends(imageAssets: 'images/标签.png', name: '标签'),
    Friends(imageAssets: 'images/公众号.png', name: '公众号'),
  ];

  final List<Friends> _listData = [];

  [@override](/user/override)
  bool get wantKeepAlive => true;

  [@override](/user/override)
  void initState() {
    super.initState();
    _listData.addAll(datas);
    _listData.addAll(datas);
    _listData.sort((a, b) => a.indexLetter!.compareTo(b.indexLetter!));

    for (int i = 0; i < peter.INDEX_WORDS.length; i++) {
      words.add(
        Expanded(
          child: Text(
            peter.INDEX_WORDS[i],
            style: TextStyle(fontSize: 12, color: Colors.grey),
          ),
        ),
      );
    }

    var _groupOffset = _cellHeight * _headerData.length;
    for (int i = 0; i < _listData.length; i++) {
      if (i == 0) {
        _groupOffsetMap.addAll({_listData[i].indexLetter!: _groupOffset});
        _groupOffset += _cellHeight + _groupHeight;
      } else if (_listData[i].indexLetter! == _listData[i - 1].indexLetter!) {
        _groupOffset += _cellHeight;
      } else {
        _groupOffsetMap.addAll({_listData[i].indexLetter!: _groupOffset});
        _groupOffset += _cellHeight + _groupHeight;
      }
    }

    _scrollController = ScrollController();
  }

  Widget _itemForRow(BuildContext context, int index) {
    if (index < _headerData.length) {
      return _FriendCell(
        imageAssets: _headerData[index].imageAssets!,
        name: _headerData[index].name!,
      );
    }
    bool _needHideTitle = (index - 4 > 0 &&
        _listData[index - 4].indexLetter == _listData[index - 5].indexLetter!);
    return _FriendCell(
      imageUrl: _listData[index - 4].imageUrl!,
      name: _listData[index - 4].name!,
      groupTitle: _needHideTitle ? null : _listData[index - 4].indexLetter!,
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: peter.weChatThemeColor,
        title: Text('通讯录页面'),
        centerTitle: true,
      ),
      body: Stack(
        children: [
          Container(
            color: peter.weChatThemeColor,
            child: ListView.builder(
              controller: _scrollController,
              itemBuilder: _itemForRow,
              itemCount: _listData.length + _headerData.length,
            ),
          ),
          peter.IndexBar(
            indexBarCallBack: (String str) {
              if (_groupOffsetMap[str] != null) {
                _scrollController!.animateTo(
                  _groupOffsetMap[str]!,
                  duration: Duration(milliseconds: 100),
                  curve: Curves.easeIn,
                );
              }
            },
          ),
        ],
      ),
    );
  }
}

class Friends {
  final String? imageAssets; // 本地图片
  final String? imageUrl; // 网络图片
  final String? name; // 姓名
  final String? indexLetter; // 首字母

  Friends({this.imageUrl, this.name, this.indexLetter, this.imageAssets});
}

List<Friends> datas = [
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/27.jpg',
    name: 'Lina',
    indexLetter: 'L',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/17.jpg',
    name: '菲儿',
    indexLetter: 'F',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/16.jpg',
    name: '安莉',
    indexLetter: 'A',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/31.jpg',
    name: '阿贵',
    indexLetter: 'A',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/22.jpg',
    name: '贝拉',
    indexLetter: 'B',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/37.jpg',
    name: 'Lina',
    indexLetter: 'L',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/18.jpg',
    name: 'Nancy',
    indexLetter: 'N',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/47.jpg',
    name: '扣扣',
    indexLetter: 'K',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/3.jpg',
    name: 'Jack',
    indexLetter: 'J',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/5.jpg',
    name: 'Emma',
    indexLetter: 'E',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/24.jpg',
    name: 'Abby',
    indexLetter: 'A',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/15.jpg',
    name: 'Betty',
    indexLetter: 'B',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/13.jpg',
    name: 'Tony',
    indexLetter: 'T',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/26.jpg',
    name: 'Jerry',
    indexLetter: 'J',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/men/36.jpg',
    name: 'Colin',
    indexLetter: 'C',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/12.jpg',
    name: 'Haha',
    indexLetter: 'H',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/11.jpg',
    name: 'Ketty',
    indexLetter: 'K',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/13.jpg',
    name: 'Lina',
    indexLetter: 'L',
  ),
  Friends(
    imageUrl: 'https://randomuser.me/api/portraits/women/23.jpg',
    name: 'Lina',
    indexLetter: 'L',
  ),
];
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!