创新实训可视化展示篇6——《联系人列表功能实现》

引言

在这篇博客中,我们将详细介绍如何设计和实现联系人列表功能。这个功能是我们应用的重要组成部分,主要包括从数据库加载联系人信息,展示联系人信息,以及实现联系人信息的增删改功能。通过具体的代码示例,我们将一步步展示这个功能是如何实现的。

数据库设计

首先,我们需要设计一个数据库表来存储联系人信息。在本例中,我们设计一个名为digital_persons的表,包含以下字段:

  • id:联系人ID,主键,自增。

  • name:联系人姓名。

  • avatarUrl:联系人头像的URL。

以下是SQLite数据库的表结构设计:

CREATE TABLE digital_persons (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT,
  avatarUrl TEXT
);

我们使用sqflite库来管理SQLite数据库,并实现数据的增删改查操作。

数据模型

为了表示联系人数据,我们创建一个DigitalPerson类,包含联系人信息的各个字段。

class DigitalPerson {
  final int? id;
  final String name;
  final String avatarUrl;
​
  DigitalPerson({
    this.id,
    required this.name,
    required this.avatarUrl,
  });
​
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'avatarUrl': avatarUrl,
    };
  }
​
  factory DigitalPerson.fromMap(Map<String, dynamic> map) {
    return DigitalPerson(
      id: map['id'],
      name: map['name'],
      avatarUrl: map['avatarUrl'],
    );
  }
}
数据库助手类

为了简化数据库操作,我们创建一个DatabaseHelper类,管理数据库的初始化和数据操作。

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import '../models/digital_person.dart';
​
class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  factory DatabaseHelper() => _instance;
​
  DatabaseHelper._internal();
​
  static Database? _database;
​
  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }
​
  Future<Database> _initDatabase() async {
    final path = join(await getDatabasesPath(), 'contacts.db');
    return openDatabase(
      path,
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE digital_persons(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, avatarUrl TEXT)',
        );
      },
      version: 1,
    );
  }
​
  Future<void> insertDigitalPerson(DigitalPerson person) async {
    final db = await database;
    await db.insert('digital_persons', person.toMap());
  }
​
  Future<void> updateDigitalPerson(DigitalPerson person) async {
    final db = await database;
    await db.update('digital_persons', person.toMap(), where: 'id = ?', whereArgs: [person.id]);
  }
​
  Future<void> deleteDigitalPerson(int id) async {
    final db = await database;
    await db.delete('digital_persons', where: 'id = ?', whereArgs: [id]);
  }
​
  Future<List<DigitalPerson>> getDigitalPersons() async {
    final db = await database;
    final maps = await db.query('digital_persons');
    return List.generate(maps.length, (i) {
      return DigitalPerson.fromMap(maps[i]);
    });
  }
​
  Future<List<DigitalPerson>> getSortedDigitalPersons() async {
    final db = await database;
    final maps = await db.query('digital_persons', orderBy: 'name');
    return List.generate(maps.length, (i) {
      return DigitalPerson.fromMap(maps[i]);
    });
  }
}

在这个类中,我们实现了数据库的初始化、联系人信息的插入、更新、删除和查询操作。

实现联系人列表页面

我们从实现联系人列表页面的基本结构开始。首先,创建一个ContactsScreen类,继承自StatefulWidget,并在其中定义一个_ContactsScreenState类。

import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:flutter_sticky_header/flutter_sticky_header.dart';
import '../db/database_helper.dart';
import '../models/digital_person.dart';
import 'package:lpinyin/lpinyin.dart';
import 'chat_screen.dart';
​
class ContactsScreen extends StatefulWidget {
  @override
  _ContactsScreenState createState() => _ContactsScreenState();
}
​
class _ContactsScreenState extends State<ContactsScreen> {
  List<DigitalPerson> digitalPersons = []; // 用于存储从数据库加载的数字人信息
  final DatabaseHelper _dbHelper = DatabaseHelper.instance;
  Map<String, List<DigitalPerson>> groupedContacts = {}; // 分组联系人
​
  @override
  void initState() {
    super.initState();
    loadDigitalPersons(); // 加载并分组数字人信息
  }
​
  void loadDigitalPersons() async {
    List<DigitalPerson> persons = await _dbHelper.getSortedDigitalPersons();
    setState(() {
      digitalPersons = persons;
      groupedContacts = _groupPersonsByFirstLetter(persons);
    });
  }
​
  Map<String, List<DigitalPerson>> _groupPersonsByFirstLetter(List<DigitalPerson> persons) {
    Map<String, List<DigitalPerson>> map = {};
    for (DigitalPerson person in persons) {
      // 获取名字的首字母
      String pinyin = PinyinHelper.getPinyinE(person.name.substring(0, 1));
      String firstLetter = pinyin.substring(0, 1).toUpperCase();
      if (!RegExp(r'[A-Z]').hasMatch(firstLetter)) {
        firstLetter = '#'; // 非字母开头的名字归类到其他
      }
      if (!map.containsKey(firstLetter)) {
        map[firstLetter] = [];
      }
      map[firstLetter]!.add(person);
    }
    return map;
  }
​
  void _deleteDigitalPerson(DigitalPerson person) async {
    await _dbHelper.deleteDigitalPerson(person.id!);
    loadDigitalPersons();
  }
​
  void _showDeleteConfirmationDialog(DigitalPerson person) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('确认删除'),
        content: Text('您确定要删除 ${person.name} 吗?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('取消'),
          ),
          TextButton(
            onPressed: () {
              _deleteDigitalPerson(person);
              Navigator.of(context).pop();
            },
            child: Text('删除'),
          ),
        ],
      ),
    );
  }
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('通讯录'),
      ),
      body: CustomScrollView(
        slivers: groupedContacts.entries.map((entry) {
          return SliverStickyHeader(
            header: Container(
              height: 50.0,
              color: Colors.lightBlue,
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              alignment: Alignment.centerLeft,
              child: Text(
                entry.key,
                style: const TextStyle(color: Colors.white),
              ),
            ),
            sliver: SliverList(
              delegate: SliverChildBuilderDelegate(
                    (context, index) {
                  DigitalPerson person = entry.value[index];
                  return Slidable(
                    actionPane: SlidableDrawerActionPane(),
                    actionExtentRatio: 0.25,
                    child: ListTile(
                      leading: CircleAvatar(
                        backgroundImage: AssetImage(person.avatarUrl),
                      ),
                      title: Text(person.name),
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => ChatScreen(digitalPerson: person),
                          ),
                        );
                      },
                    ),
                    secondaryActions: <Widget>[
                      IconSlideAction(
                        caption: '删除',
                        color: Colors.red,
                        icon: Icons.delete,
                        onTap: () => _showDeleteConfirmationDialog(person),
                      ),
                    ],
                  );
                },
                childCount: entry.value.length,
              ),
            ),
          );
        }).toList(),
      ),
    );
  }
}

在上面的代码中,我们实现了联系人列表的显示、添加、编辑和删除功能。每个联系人显示在列表中,点击可以编辑联系人,右侧的删除按钮可以删除联系人。我们使用对话框来实现联系人信息的输入和编辑。

联系人信息的分组显示

为了使联系人列表更加清晰,我们按照联系人姓名的首字母对联系人进行分组显示。我们使用flutter_sticky_header库实现分组显示。

Map<String, List<DigitalPerson>> _groupPersonsByFirstLetter(List<DigitalPerson> persons) {
    Map<String, List<DigitalPerson>> map = {};
    for (DigitalPerson person in persons) {
      // 获取名字的首字母
      String pinyin = PinyinHelper.getPinyinE(person.name.substring(0, 1));
      String firstLetter = pinyin.substring(0, 1).toUpperCase();
      if (!RegExp(r'[A-Z]').hasMatch(firstLetter)) {
        firstLetter = '#'; // 非字母开头的名字归类到其他
     
​
 }
      if (!map.containsKey(firstLetter)) {
        map[firstLetter] = [];
      }
      map[firstLetter]!.add(person);
    }
    return map;
  }
结论

通过上述步骤,我们实现了联系人列表的基本功能,包括从数据库加载联系人信息,显示联系人信息,以及实现联系人信息的添加、编辑和删除功能。我们还通过分组显示使联系人列表更加清晰和易于使用。希望通过本篇博客,能帮助大家更好地理解和实现联系人列表功能。如果有任何问题或建议,欢迎在评论区交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值