通过网盘分享的文件:flutter1.zip
链接: https://pan.baidu.com/s/1jkLZ9mZXjNm0LgP6FTVRzw 提取码: 2t97

关于页面是App的"名片",展示应用的基本信息、功能特性、数据来源和联系方式。虽然用户不常打开,但它能传递专业感和信任感。

这篇文章会实现一个完整的关于页面,涉及渐变装饰、图标展示、url_launcher 外部链接跳转等技术点。


请添加图片描述

关于页面的内容规划

一个完整的关于页面通常包含:

应用标识:Logo、名称、版本号,让用户一眼认出这是什么App。

应用介绍:简短描述App的定位和用途。

功能特性:列出主要功能,让用户了解App能做什么。

数据来源:说明数据从哪来,增加透明度和信任感。

联系方式:提供反馈渠道,方便用户联系开发者。


页面基础结构

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

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('关于应用')),
      body: SingleChildScrollView(
        child: Column(
          children: [
            // 页面内容
          ],
        ),
      ),
    );
  }
}

引入 url_launcher 包,用于打开外部链接和邮件客户端。

SingleChildScrollView 包裹内容,当内容超出屏幕时可以滚动。Column 垂直排列各个区块。


应用标识区域

页面顶部展示App的Logo和基本信息:

Container(
  padding: const EdgeInsets.all(32),
  child: Column(
    children: [
      Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          gradient: LinearGradient(
            colors: [
              Theme.of(context).primaryColor,
              Theme.of(context).colorScheme.secondary,
            ],
          ),
        ),
        child: const Icon(
          Icons.movie,
          size: 50,
          color: Colors.white,
        ),
      ),

外层 Container 设置 32 像素的内边距,让内容不会贴边。

Logo 用一个圆形容器实现。BoxShape.circle 让容器变成圆形,LinearGradient 创建从主色到次色的渐变背景。

Theme.of(context).primaryColor 获取当前主题的主色,这样Logo颜色会跟随主题变化。


应用名称和版本

      const SizedBox(height: 16),
      const Text(
        '微动漫',
        style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
      ),
      const SizedBox(height: 8),
      const Text(
        '版本 1.0.0',
        style: TextStyle(color: Colors.grey),
      ),
    ],
  ),
),

应用名称用大号粗体,版本号用灰色小字。SizedBox 控制元素之间的间距。

这个区域是视觉焦点,用户第一眼就能看到App的身份信息。


分隔线

const Divider(),

Divider 是一条水平分隔线,把标识区域和详细信息区域分开。默认样式就很好看,不需要额外配置。


应用介绍区域

Padding(
  padding: const EdgeInsets.all(16),
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      const Text(
        '应用介绍',
        style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
      ),
      const SizedBox(height: 12),
      const Text(
        '微动漫是一个免费的动漫信息应用,提供最新的动漫资讯、排行榜、角色信息等内容。',
        style: TextStyle(height: 1.6),
      ),

crossAxisAlignment: CrossAxisAlignment.start 让所有子元素左对齐。

介绍文本设置 height: 1.6 增加行高,阅读起来更舒服。内容要简洁,一两句话说清楚App是干什么的。


功能特性列表

      const SizedBox(height: 24),
      const Text(
        '功能特性',
        style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
      ),
      const SizedBox(height: 12),
      _buildFeature('🎬', '浏览热门和当季动漫'),
      _buildFeature('🔍', '搜索和发现新动漫'),
      _buildFeature('❤️', '收藏喜欢的动漫'),
      _buildFeature('👥', '查看角色信息'),
      _buildFeature('📰', '阅读动漫新闻'),
      _buildFeature('💬', '浏览动漫名言'),
      _buildFeature('🌙', '深色/浅色主题切换'),

用 emoji 作为图标,比 Icon 更生动有趣。每个功能一行,简短明了。


功能项构建方法

Widget _buildFeature(String emoji, String text) {
  return Padding(
    padding: const EdgeInsets.only(bottom: 8),
    child: Row(
      children: [
        Text(emoji, style: const TextStyle(fontSize: 18)),
        const SizedBox(width: 12),
        Text(text),
      ],
    ),
  );
}

Row 水平排列 emoji 和文本。emoji 字号设为 18,比默认大一点,更醒目。

Padding 只设置底部间距,让每个功能项之间有适当的距离。

这个方法可以复用,添加新功能只需要调用一次。


数据来源区域

      const SizedBox(height: 24),
      const Text(
        '数据来源',
        style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
      ),
      const SizedBox(height: 12),
      _buildDataSource('Jikan API', '动漫数据、角色、推荐等'),
      _buildDataSource('AnimeChan', '动漫名言'),
      _buildDataSource('Catboy API', '可爱图片'),

列出App使用的所有API,让用户知道数据从哪来。这是对数据提供方的尊重,也增加了透明度。


数据来源项构建方法

Widget _buildDataSource(String name, String description) {
  return Padding(
    padding: const EdgeInsets.only(bottom: 12),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          name,
          style: const TextStyle(fontWeight: FontWeight.w600),
        ),
        const SizedBox(height: 2),
        Text(
          description,
          style: const TextStyle(fontSize: 12, color: Colors.grey),
        ),
      ],
    ),
  );
}

数据来源用两行展示:名称用粗体,描述用小号灰色字体。Column 垂直排列,crossAxisAlignment.start 左对齐。

和功能项不同,数据来源需要更多说明,所以用两行而不是一行。


联系方式区域

      const SizedBox(height: 24),
      const Text(
        '联系我们',
        style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
      ),
      const SizedBox(height: 12),

联系方式放在最后,用户看完前面的信息后,如果有问题可以联系开发者。


发送反馈功能

ListTile(
  leading: const Icon(Icons.email),
  title: const Text('发送反馈'),
  onTap: () async {
    final Uri emailUri = Uri(
      scheme: 'mailto',
      path: 'support@microanime.com',
    );
    if (await canLaunchUrl(emailUri)) {
      await launchUrl(emailUri);
    }
  },
),

ListTile 是带图标的列表项,点击后打开邮件客户端。

Uri 构造邮件链接,scheme 是 mailto,path 是邮箱地址。canLaunchUrl 检查设备是否能处理这个链接,launchUrl 打开邮件客户端。

这两个方法都是异步的,需要用 async/await


访问网站功能

ListTile(
  leading: const Icon(Icons.language),
  title: const Text('访问网站'),
  onTap: () async {
    const url = 'https://jikan.moe';
    if (await canLaunchUrl(Uri.parse(url))) {
      await launchUrl(Uri.parse(url));
    }
  },
),

点击后打开浏览器访问网站。Uri.parse 把字符串转成 Uri 对象。

Icons.language 是地球图标,通常用来表示网站链接。


url_launcher 的配置

使用 url_launcher 需要在 pubspec.yaml 添加依赖:

dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^6.1.0

在 HarmonyOS 上还需要配置权限,让App能够打开外部链接。


url_launcher 的更多用法

除了邮件和网页,url_launcher 还支持其他类型的链接:

// 打电话
final Uri phoneUri = Uri(scheme: 'tel', path: '10086');
await launchUrl(phoneUri);

// 发短信
final Uri smsUri = Uri(scheme: 'sms', path: '10086');
await launchUrl(smsUri);

// 打开地图
final Uri mapUri = Uri.parse('geo:39.9,116.4');
await launchUrl(mapUri);

不同的 scheme 对应不同的功能。tel 是电话,sms 是短信,geo 是地图坐标。


处理链接打开失败

有时候设备可能无法处理某些链接,需要给用户提示:

onTap: () async {
  final Uri emailUri = Uri(
    scheme: 'mailto',
    path: 'support@microanime.com',
  );
  if (await canLaunchUrl(emailUri)) {
    await launchUrl(emailUri);
  } else {
    if (context.mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('无法打开邮件客户端')),
      );
    }
  }
},

canLaunchUrl 返回 false 时,用 SnackBar 提示用户。context.mounted 检查组件是否还在树中,避免异步操作后组件已销毁的问题。


添加版本检查功能

关于页面可以加上版本检查:

ListTile(
  leading: const Icon(Icons.system_update),
  title: const Text('检查更新'),
  subtitle: const Text('当前版本 1.0.0'),
  onTap: () {
    // 检查更新逻辑
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('已是最新版本')),
    );
  },
),

subtitle 显示当前版本号。点击后可以调用接口检查是否有新版本。


添加开源许可信息

如果App使用了开源库,可以展示许可信息:

ListTile(
  leading: const Icon(Icons.description),
  title: const Text('开源许可'),
  onTap: () {
    showLicensePage(
      context: context,
      applicationName: '微动漫',
      applicationVersion: '1.0.0',
    );
  },
),

showLicensePage 是 Flutter 内置的方法,会显示所有依赖库的许可信息。这是对开源社区的尊重。


深色模式下的渐变调整

Logo 的渐变在深色模式下可能需要调整:

Container(
  width: 100,
  height: 100,
  decoration: BoxDecoration(
    shape: BoxShape.circle,
    gradient: LinearGradient(
      begin: Alignment.topLeft,
      end: Alignment.bottomRight,
      colors: [
        Theme.of(context).primaryColor,
        Theme.of(context).colorScheme.secondary,
      ],
    ),
    boxShadow: [
      BoxShadow(
        color: Theme.of(context).primaryColor.withOpacity(0.3),
        blurRadius: 20,
        offset: const Offset(0, 10),
      ),
    ],
  ),
  child: const Icon(
    Icons.movie,
    size: 50,
    color: Colors.white,
  ),
),

beginend 控制渐变方向,从左上到右下。

boxShadow 添加阴影效果,让Logo更有立体感。阴影颜色用主色的半透明版本,和Logo颜色呼应。


添加动画效果

可以给Logo添加简单的动画:

class AboutScreen extends StatefulWidget {
  const AboutScreen({super.key});

  
  State<AboutScreen> createState() => _AboutScreenState();
}

class _AboutScreenState extends State<AboutScreen>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

AnimationController 控制动画的播放。repeat(reverse: true) 让动画来回播放。

AnimatedBuilder(
  animation: _controller,
  builder: (context, child) {
    return Transform.scale(
      scale: 1.0 + _controller.value * 0.1,
      child: child,
    );
  },
  child: Container(
    width: 100,
    height: 100,
    // Logo 内容
  ),
),

AnimatedBuilder 监听动画值的变化,Transform.scale 根据动画值缩放Logo。效果是Logo轻微地放大缩小,像在"呼吸"。


社交媒体链接

可以添加社交媒体链接:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    IconButton(
      icon: const Icon(Icons.facebook),
      onPressed: () => _launchUrl('https://facebook.com'),
    ),
    IconButton(
      icon: const Icon(Icons.telegram),
      onPressed: () => _launchUrl('https://t.me/channel'),
    ),
    IconButton(
      icon: const Icon(Icons.discord),
      onPressed: () => _launchUrl('https://discord.gg/invite'),
    ),
  ],
),

Row 水平排列图标按钮,mainAxisAlignment.center 居中显示。

Future<void> _launchUrl(String url) async {
  if (await canLaunchUrl(Uri.parse(url))) {
    await launchUrl(Uri.parse(url));
  }
}

把打开链接的逻辑抽成方法,避免重复代码。


复制邮箱地址

有些用户可能想复制邮箱而不是直接发邮件:

ListTile(
  leading: const Icon(Icons.email),
  title: const Text('发送反馈'),
  subtitle: const Text('support@microanime.com'),
  onTap: () async {
    // 打开邮件客户端
  },
  onLongPress: () {
    Clipboard.setData(
      const ClipboardData(text: 'support@microanime.com'),
    );
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('邮箱已复制')),
    );
  },
),

onLongPress 处理长按事件,Clipboard.setData 复制文本到剪贴板。需要引入 package:flutter/services.dart


页面跳转

关于页面通常从设置或个人中心进入:

ListTile(
  leading: const Icon(Icons.info_outline),
  title: const Text('关于应用'),
  trailing: const Icon(Icons.chevron_right),
  onTap: () {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const AboutScreen()),
    );
  },
),

Icons.info_outline 是信息图标,常用于关于页面的入口。


小结

关于页面涉及的技术点:LinearGradient 渐变BoxDecoration 装饰url_launcher 外部链接ListTile 列表项SingleChildScrollView 滚动Divider 分隔线

内容组织上,从上到下依次是:应用标识、应用介绍、功能特性、数据来源、联系方式。层次分明,信息完整。

关于页面虽然不是核心功能,但它展示了App的专业度。花点心思把它做好,用户会感受到开发者的用心。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐