peter_package_demo 0.0.4 copy "peter_package_demo: ^0.0.4" to clipboard
peter_package_demo: ^0.0.4 copied to clipboard

A new Flutter project.

example/main.dart

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
  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
  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: imageUrl != null ? DecorationImage(image: NetworkImage(imageUrl!)) : DecorationImage(image: AssetImage(imageAssets!)),
                  image: DecorationImage(
                      image: imageUrl != null
                          ? NetworkImage(imageUrl!) as ImageProvider
                          : AssetImage(imageAssets!,package: 'peter_package_demo')), //两种写法都可以 - 强制类型转换
                ),
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                //可以设置交叉轴(默认是center)
                children: [
                  Container(
                    // alignment: Alignment.centerLeft,                   //也可以通过设置这个属性
                    height: 54,
                    child: Text(
                      name!,
                      style: const TextStyle(fontSize: 18),
                    ),
                  ),
                  Container(
                    color: peter.weChatThemeColor,
                    width: peter.screenWidth(context) - 54,
                    height: 0.5,
                    // margin: const EdgeInsets.only(top: 10),
                  ),
                  //可以通过设置height:0 隐藏线条
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

class FriendsPage extends StatefulWidget {
  //整个页面定义为Stateful并不好,因为整个数据都会保留(正常情况下要拆分)
  const FriendsPage({Key? key}) : super(key: key);

  @override
  _FriendsPageState createState() => _FriendsPageState();
}

class _FriendsPageState extends State<FriendsPage> with AutomaticKeepAliveClientMixin {
  //字典 - 存放每一个索引所对应要滚动的距离(距离需要根据实际情况计算)
  Map _groupOffsetMap = {
    peter.INDEX_WORDS[0]: 0.0, //🔍
    peter.INDEX_WORDS[1]: 0.0, //⭐️
  };
  final double _cellHeight = 54.5; //cell的高度
  final double _groupHeight = 30.0; //group头部高度

  ScrollController? _scrollController; //ListView滚动需要用到
  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
  bool get wantKeepAlive => true;

  @override
  void initState() {
    //生命周期方法,页面被渲染(载入)的时候会进来 (需要重新运行) - 从通讯录切换到发现页面,通讯录页面会被销毁
    super.initState();
    _listData.addAll(
        datas); //添加一个数组的数据到数组中   可以用:_listData..addAll(datas)..addAll(datas);
    _listData.addAll(datas);
    _listData.sort((Friends a, Friends b) {
      //排序
      return 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),
          )) //words里面装的是组件(如果不用Expanded,占不满)
      );
    }
    //在这里计算每个索引所对应的位置
    var _groupOffset = _cellHeight * _headerData.length;
    for (int i = 0; i < _listData.length; i++) {
      if (i == 0) {
        //第一个cell
        _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) {
    //显示头部的4个cell
    if (index < _headerData.length) {
      return _FriendCell(
          imageAssets: _headerData[index].imageAssets!,
          name: _headerData[index].name!);
    }
    //其它cell
    bool _needHideTitle = (index - 4 > 0 &&
        _listData[index - 4].indexLetter ==
            _listData[index - 5].indexLetter); //是否应该显示groupTitle
    return _FriendCell(
      imageUrl: _listData[index - 4].imageUrl!,
      name: _listData[index - 4].name!,
      groupTitle: _needHideTitle ? null : _listData[index - 4].indexLetter!,
    );
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: peter.weChatThemeColor, //全局定义的变量
        title: Text('通讯录页面'),
        centerTitle:
        true, //如果导航栏上设置了多个按钮,title会往左偏移,这里设置为true即可居中 (怎么设置title左边的按钮?)
      ),
      body: Stack(
        //索引条要悬浮在ListView上面
        children: [
          //Flutter中有专门的弹框视图
          Container(
              color: peter.weChatThemeColor,
              child: ListView.builder(
                controller: _scrollController, //scroll滚动需要用到这个controller
                itemBuilder: _itemForRow,
                itemCount: _listData.length + _headerData.length,
              )),
          peter.IndexBar(
            indexBarCallBack: (String str) {
              //回调
              if (_groupOffsetMap[str] != null) {
                _scrollController!.animateTo(_groupOffsetMap[str],
                    duration: Duration(microseconds: 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'
  ),

];
0
likes
130
points
25
downloads

Publisher

unverified uploader

Weekly Downloads

A new Flutter project.

Homepage

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on peter_package_demo