在这里插入图片描述

想了解不同猫咪品种的特点?今天我们来实现一个品种图鉴功能,展示常见猫咪品种的基本信息,包括原产地、体重、寿命、性格和护理要点。


功能设计

品种图鉴需要实现:

  • 展示多种猫咪品种
  • 每个品种可以展开查看详情
  • 显示体重、寿命、性格、护理等信息
  • 不同品种用不同颜色区分

这是一个纯展示型的页面,不涉及数据的增删改。


依赖导入

引入需要的包:

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

这个页面不需要Provider,数据是静态的。
screenutil用于屏幕适配。


无状态组件

品种图鉴是纯展示页面:

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

没有需要维护的状态,用StatelessWidget。
数据直接定义在组件内部。


品种数据定义

用List存储品种信息:

  final List<Map<String, dynamic>> _breeds = const [
    {
      'name': '中华田园猫',
      'origin': '中国',
      'weight': '3-6 kg',
      'lifespan': '12-20年',
      'personality': '聪明、独立、适应力强',
      'care': '易于照顾,抵抗力强',
      'color': Colors.orange,
    },
    {
      'name': '英国短毛猫',
      'origin': '英国',
      'weight': '4-8 kg',
      'lifespan': '12-17年',
      'personality': '温顺、安静、友善',
      'care': '需要定期梳毛,注意体重',
      'color': Colors.blue,
    },

每个品种用Map存储各项信息。
color用于区分不同品种的视觉效果。

更多品种数据:

    {
      'name': '美国短毛猫',
      'origin': '美国',
      'weight': '3-6 kg',
      'lifespan': '15-20年',
      'personality': '活泼、聪明、好奇',
      'care': '适应力强,易于照顾',
      'color': Colors.green,
    },
    {
      'name': '布偶猫',
      'origin': '美国',
      'weight': '4-9 kg',
      'lifespan': '12-17年',
      'personality': '温顺、粘人、安静',
      'care': '需要经常梳毛,注意心脏健康',
      'color': Colors.purple,
    },

布偶猫体型较大,体重可达9公斤。
每个品种的护理要点都不同。

继续添加品种:

    {
      'name': '波斯猫',
      'origin': '伊朗',
      'weight': '3-7 kg',
      'lifespan': '10-17年',
      'personality': '安静、温和、优雅',
      'care': '需要每日梳毛,注意眼睛清洁',
      'color': Colors.pink,
    },
    {
      'name': '暹罗猫',
      'origin': '泰国',
      'weight': '2.5-5 kg',
      'lifespan': '12-20年',
      'personality': '活泼、聪明、爱叫',
      'care': '需要陪伴,注意牙齿健康',
      'color': Colors.brown,
    },

波斯猫需要每日梳毛,护理要求较高。
暹罗猫比较爱叫,这是品种特点。

更多品种:

    {
      'name': '缅因猫',
      'origin': '美国',
      'weight': '5-11 kg',
      'lifespan': '10-15年',
      'personality': '友善、温和、聪明',
      'care': '需要大空间,定期梳毛',
      'color': Colors.teal,
    },
    {
      'name': '苏格兰折耳猫',
      'origin': '苏格兰',
      'weight': '2.5-6 kg',
      'lifespan': '11-15年',
      'personality': '温顺、安静、亲人',
      'care': '注意关节健康,避免繁殖',
      'color': Colors.indigo,
    },

缅因猫是大型猫,体重可达11公斤。
折耳猫有遗传性关节问题,需要特别注意。

最后两个品种:

    {
      'name': '俄罗斯蓝猫',
      'origin': '俄罗斯',
      'weight': '3-5.5 kg',
      'lifespan': '15-20年',
      'personality': '安静、害羞、忠诚',
      'care': '低过敏,易于照顾',
      'color': Colors.blueGrey,
    },
    {
      'name': '孟加拉猫',
      'origin': '美国',
      'weight': '4-7 kg',
      'lifespan': '12-16年',
      'personality': '活泼、好奇、爱玩水',
      'care': '需要大量运动和互动',
      'color': Colors.amber,
    },
  ];

俄罗斯蓝猫是低过敏品种,适合过敏体质的人。
孟加拉猫精力旺盛,需要大量运动。


页面结构

build方法构建列表:

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('品种图鉴')),
      body: ListView.builder(
        padding: EdgeInsets.all(16.w),
        itemCount: _breeds.length,
        itemBuilder: (context, index) => _buildBreedCard(_breeds[index]),
      ),
    );
  }

ListView.builder按需构建列表项,性能更好。
itemCount是列表长度,itemBuilder构建每一项。


品种卡片组件

用ExpansionTile实现可展开的卡片:

  Widget _buildBreedCard(Map<String, dynamic> breed) {
    return Card(
      margin: EdgeInsets.only(bottom: 12.h),
      child: ExpansionTile(
        leading: CircleAvatar(
          backgroundColor: (breed['color'] as Color).withOpacity(0.1),
          child: Icon(Icons.pets, color: breed['color'], size: 24.sp),
        ),
        title: Text(breed['name'], style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.sp)),
        subtitle: Text('原产地: ${breed['origin']}'),

ExpansionTile点击可以展开显示更多内容。
leading放品种对应颜色的图标。

展开后的详情内容:

        children: [
          Padding(
            padding: EdgeInsets.all(16.w),
            child: Column(
              children: [
                _buildInfoRow(Icons.monitor_weight, '体重', breed['weight']),
                _buildInfoRow(Icons.timer, '寿命', breed['lifespan']),
                _buildInfoRow(Icons.psychology, '性格', breed['personality']),
                _buildInfoRow(Icons.health_and_safety, '护理', breed['care']),
              ],
            ),
          ),
        ],
      ),
    );
  }

children是展开后显示的内容。
四行信息分别显示体重、寿命、性格、护理。


信息行组件

显示一行详情信息:

  Widget _buildInfoRow(IconData icon, String label, String value) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 6.h),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Icon(icon, size: 18.sp, color: Colors.grey[600]),
          SizedBox(width: 8.w),
          SizedBox(
            width: 50.w,
            child: Text(label, style: TextStyle(color: Colors.grey[600], fontSize: 13.sp)),
          ),
          Expanded(child: Text(value, style: TextStyle(fontSize: 13.sp))),
        ],
      ),
    );
  }
}

crossAxisAlignment设为start让内容顶部对齐。
Expanded让value文字可以换行。


ExpansionTile详解

可展开的列表项:

ExpansionTile(
  leading: Widget,      // 左侧图标
  title: Widget,        // 主标题
  subtitle: Widget,     // 副标题
  children: [Widget],   // 展开后的内容
)

点击标题区域可以展开或收起。
children是展开后显示的Widget列表。


ListView.builder

按需构建的列表:

ListView.builder(
  padding: EdgeInsets.all(16.w),
  itemCount: _breeds.length,
  itemBuilder: (context, index) => _buildBreedCard(_breeds[index]),
)

只有可见的列表项才会被构建。
对于长列表,性能比ListView好很多。


CircleAvatar使用

圆形头像组件:

CircleAvatar(
  backgroundColor: (breed['color'] as Color).withOpacity(0.1),
  child: Icon(Icons.pets, color: breed['color'], size: 24.sp),
)

backgroundColor设置背景色。
child可以放任何Widget,这里放图标。


颜色处理

从Map中获取颜色:

breed['color'] as Color

Map的值是dynamic类型,需要转换为Color。
as关键字进行类型转换。

设置透明度:

(breed['color'] as Color).withOpacity(0.1)

withOpacity返回一个新的颜色。
0.1是10%的不透明度。


数据结构设计

用Map存储品种信息:

{
  'name': '中华田园猫',
  'origin': '中国',
  'weight': '3-6 kg',
  'lifespan': '12-20年',
  'personality': '聪明、独立、适应力强',
  'care': '易于照顾,抵抗力强',
  'color': Colors.orange,
}

字符串作为key,值可以是任意类型。
这种结构灵活但不够类型安全。

更好的做法是定义类:

class CatBreed {
  final String name;
  final String origin;
  final String weight;
  final String lifespan;
  final String personality;
  final String care;
  final Color color;
}

类的方式更类型安全。
但对于静态数据,Map也够用了。


Row布局技巧

信息行的布局:

Row(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Icon(...),
    SizedBox(width: 8.w),
    SizedBox(width: 50.w, child: Text(label)),
    Expanded(child: Text(value)),
  ],
)

固定宽度的SizedBox让标签对齐。
Expanded让值文字占据剩余空间。


Card和ExpansionTile组合

卡片包裹可展开列表项:

Card(
  margin: EdgeInsets.only(bottom: 12.h),
  child: ExpansionTile(...),
)

Card提供阴影和圆角效果。
margin控制卡片之间的间距。


品种信息来源

这些品种信息的参考:

中华田园猫:中国本土猫,适应力强
英国短毛猫:圆脸大眼,性格温顺
美国短毛猫:虎斑花纹,活泼好动
布偶猫:蓝眼长毛,性格粘人
波斯猫:扁脸长毛,需要精心护理
暹罗猫:重点色,爱叫爱说话
缅因猫:大型猫,友善温和
折耳猫:耳朵折叠,有遗传疾病
俄罗斯蓝猫:银蓝色毛,低过敏
孟加拉猫:豹纹花色,精力旺盛

这些都是常见的猫咪品种。
每个品种都有自己的特点和护理要求。


图标选择

不同信息用不同图标:

Icons.monitor_weight  // 体重
Icons.timer           // 寿命
Icons.psychology      // 性格
Icons.health_and_safety  // 护理

图标让信息更直观。
Material Icons提供了丰富的图标选择。


小结

品种图鉴涉及的知识点:

  • ListView.builder列表构建
  • ExpansionTile可展开组件
  • Map数据结构使用
  • 颜色处理和类型转换

这个页面虽然简单,但展示了如何组织和展示静态数据。


欢迎加入OpenHarmony跨平台开发社区,一起交流Flutter开发经验:

https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐