chat_index_bar 1.0.7 copy "chat_index_bar: ^1.0.7" to clipboard
chat_index_bar: ^1.0.7 copied to clipboard

A chat_index_bar is a package of search controls floating on the chat interface, which can expand the index list to facilitate quick search of chat records.

example/main.dart

import 'package:chat_index_bar/chat_index_bar.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

final Color WeChatThemeColor = Color.fromRGBO(220, 220, 220, 1.0);

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'use cases for chat index bar.',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.standard,
      ),
      home: const FriendsPage(),
    );
  }
}

class FriendsPage extends StatefulWidget {
  const FriendsPage({Key? key}) : super(key: key);

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

class _FriendsPageState extends State<FriendsPage> {
  // 字典里存放item和高度的对应数据
  final Map _groupOffsetMap = {
    indexWords[0]: 0.0,
    indexWords[0]: 0.0,
  };

  final ScrollController _scrollController = ScrollController();

  final List<Friends> _listDatas = [];

  @override
  void initState() {
    super.initState();

    // 方法一
    // _listDatas.addAll(datas);
    // _listDatas.addAll(datas);

    // 方法二 step1 链式 添加【增量数据】
    _listDatas
    // ..addAll(datas)
    // ..addAll(datas)
      ..addAll(datas);

    // step2 排序
    _listDatas.sort((Friends a, Friends b) {
      return a.indexLetter.compareTo(b.indexLetter);
    });

    var _groupOffset = 54.5 * 4;
    // 经过循环计算,将每一个头的位置算出来,放入字典。
    for (int i = 0; i < _listDatas.length; i++) {
      if (i < 1) {
        // 第一个Cell
        _groupOffsetMap.addAll({_listDatas[i].indexLetter: _groupOffset});
        // 保存完了再加_groupOffset偏移
        _groupOffset += 84.5;
      } else if (_listDatas[i].indexLetter == _listDatas[i - 1].indexLetter) {
        // 没有头部,只需要加偏移量
        _groupOffset += 54.5;
      } else {
        // 这部分是有头部的Cell
        _groupOffsetMap.addAll({_listDatas[i].indexLetter: _groupOffset});
        _groupOffset += 84.5;
      }
    }
  }

  final List _headerData = [
    Friends(imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png', name: '新的朋友'),
    Friends(imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png', name: '群聊'),
    Friends(imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png', name: '标签'),
    Friends(imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png', name: '公众号'),
  ];

  Widget _itemForRow(BuildContext context, int index) {
    // 显示头部 系统图标的cell
    if (index < _headerData.length) {
      // print(index);
      return _FriendCell(
        imageUrl: _headerData[index].imageUrl,
        name: _headerData[index].name,
      );
    }

    // 显示剩下的cell
    // 如果当前和上一个cell的IndexLetter一样, 就不显示
    bool _hideIndexLetter = (index - 4 > 0 &&
        (_listDatas[index - 4].indexLetter ==
            _listDatas[index - 5].indexLetter));
    return _FriendCell(
      imageUrl: _listDatas[index - 4].imageUrl,
      name: _listDatas[index - 4].name,
      groupTitle: _hideIndexLetter ? "" : _listDatas[index - 4].indexLetter,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: WeChatThemeColor,
        title: const Text('通讯录'),
        actions: <Widget>[
          GestureDetector(
            child: Container(
              margin: const EdgeInsets.only(right: 10),
              child: const Icon(Icons.add, size: 25,),
            ),
            onTap: () {},
          )
        ],
      ),
      body: Stack(
        children: <Widget>[
          ListView.builder(
            controller: _scrollController,
            itemCount: _listDatas.length + _headerData.length,
            itemBuilder: _itemForRow,
          ), // 列表
          IndexBar(
            bubbleImage: const Image(
              image: NetworkImage('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTTxO8mUQcWnFsN2aEnvdSKNyJ9Bx61N-KxrA&usqp=CAU'),
            ),
            indexBarCallBack: (String str) {
              if (kDebugMode) {
                print('我收到了$str');
              }

              if (_groupOffsetMap[str] != null) {
                _scrollController.animateTo(_groupOffsetMap[str],
                    duration: const Duration(microseconds: 1),
                    curve: Curves.easeIn);
              }
            },
          ), // 悬浮检索控件
        ],
      ),
    );
  }
}

class _FriendCell extends StatelessWidget {
  final String imageUrl;
  final String name;
  final String groupTitle;
  final String imageAssets;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          alignment: Alignment.centerLeft,
          padding: const EdgeInsets.only(left: 10),
          height: groupTitle != "" ? 30 : 0,
          color: const Color.fromRGBO(1, 1, 1, 0.0),
          child: groupTitle != ""
              ? Text(
            groupTitle,
            style: const TextStyle(color: Colors.grey),
          )
              : null,
        ), // Cell的头
        Container(
          color: Colors.white,
          child: Row(
            children: <Widget>[
              Container(
                margin: const EdgeInsets.all(10),
                width: 34,
                height: 34,
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(6.0),
                    image: DecorationImage(
                      image: imageUrl != ""
                          ? NetworkImage(imageUrl)
                          : AssetImage(imageAssets) as ImageProvider,
                    )),
              ), // 图片
              Text(
                name,
                style: const TextStyle(fontSize: 17),
              ), // 昵称
            ],
          ),
        ), // Cell的内容
        Container(
          height: 0.5,
          color: WeChatThemeColor,
          child: Row(
            children: <Widget>[
              Container(
                width: 50,
                color: Colors.white,
              ),
            ],
          ),
        ), // 分割线
      ],
    );
  }
}

class _FriendHeaderCell extends StatelessWidget {
  final String name;
  final String imageAssets;

  const _FriendHeaderCell({this.name = '', this.imageAssets = ''});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Row(
        children: <Widget>[
          Container(
            margin: const EdgeInsets.all(10),
            width: 34,
            height: 34,
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(6.0),
                image: DecorationImage(
                  image: AssetImage(imageAssets),
                )),
          ), // 图片
          Text(
            name,
            style: const TextStyle(fontSize: 17),
          ), // 昵称
        ],
      ),
    );
  }
}

class Friends {
  final String imageUrl;
  final String name;
  final String indexLetter;

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

List<Friends> datas = [
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/22.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/women/16.jpg",
      name: "Eam",
      indexLetter: "E"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "安莉",
      indexLetter: "A"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/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/27.jpg",
      name: "Abby",
      indexLetter: "A"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "COCO",
      indexLetter: "C"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/17.jpg",
      name: "wkk",
      indexLetter: "W"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "凯蒂",
      indexLetter: "K"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "盖茨",
      indexLetter: "G"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/22.jpg",
      name: "Hank",
      indexLetter: "H"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "Yuki",
      indexLetter: "Y"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/27.jpg",
      name: "张萌",
      indexLetter: "Z"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/22.jpg",
      name: "COCO",
      indexLetter: "C"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/17.jpg",
      name: "赛琳娜",
      indexLetter: "S"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "Wangle",
      indexLetter: "W"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "西涅",
      indexLetter: "X"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/22.jpg",
      name: "Right",
      indexLetter: "R"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "Vivina",
      indexLetter: "V"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/27.jpg",
      name: "秦小君",
      indexLetter: "Q"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "Peter",
      indexLetter: "P"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/17.jpg",
      name: "欧拉琳",
      indexLetter: "O"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/22.jpg",
      name: "Python",
      indexLetter: "P"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "C++",
      indexLetter: "C"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "Java",
      indexLetter: "J"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/16.jpg",
      name: "Betty",
      indexLetter: "B"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/17.jpg",
      name: "Objective-C",
      indexLetter: "O"),
  Friends(
      imageUrl: "https://randomuser.me/api/portraits/women/31.jpg",
      name: "Swift",
      indexLetter: "S"),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/16.jpg',
      name: 'web',
      indexLetter: 'W'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/17.jpg',
      name: 'PHP',
      indexLetter: 'P'),
];
1
likes
150
pub points
0%
popularity

Publisher

unverified uploader

A chat_index_bar is a package of search controls floating on the chat interface, which can expand the index list to facilitate quick search of chat records.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on chat_index_bar