Flutter for OpenHarmony 剧本杀组队App实战:邀请好友功能实现

引言

邀请好友是用户增长的重要功能,通过奖励机制激励用户分享App。本篇将实现邀请好友页面,包含邀请码、分享方式和邀请记录。邀请功能不仅能够扩大用户基数,还能通过社交传播提升App的知名度。在现代移动应用中,邀请功能已成为用户获取的重要渠道,通过设计合理的奖励机制和便捷的分享方式,可以显著提升用户的邀请意愿。

功能设计

邀请好友页面包含以下核心功能:

  • 邀请奖励说明卡片:展示邀请奖励规则,激励用户参与。通过清晰的奖励说明,让用户了解邀请的收益
  • 邀请码展示(可复制):提供唯一的邀请码,方便用户分享。邀请码是邀请功能的核心,需要确保其唯一性和易记性
  • 多种分享方式:支持微信、二维码、链接等多种分享渠道。不同的分享方式满足不同用户的需求
  • 邀请记录列表:展示邀请的好友及其完成状态。记录展示帮助用户追踪邀请进度和奖励获取情况

数据模型定义

dart 复制代码
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class InviteRecord {
  final String userId;
  final String userName;
  final String status;
  final String reward;
  final DateTime inviteTime;
  
  InviteRecord({
    required this.userId,
    required this.userName,
    required this.status,
    required this.reward,
    required this.inviteTime,
  });
}

InviteRecord数据模型用于表示单条邀请记录。userId是被邀请用户的唯一标识,用于后端数据关联。userName是被邀请用户的昵称,在UI中直接显示。status字段表示邀请的当前状态,包括"待完成首次组队"和"已完成首次组队"两种状态。reward字段存储该邀请对应的奖励信息,如"+50积分"或"待发放"。inviteTime记录邀请发生的时间,用于在UI中显示邀请的相对时间。这个模型设计简洁但包含了邀请功能所需的所有关键信息。

dart 复制代码
class InviteController extends GetxController {
  final inviteCode = 'INVITE2024ABC'.obs;
  final inviteRecords = <InviteRecord>[].obs;
  final totalReward = 0.obs;
  
  @override
  void onInit() {
    super.onInit();
    loadInviteRecords();
  }

InviteController继承GetxController,使用GetX框架的响应式编程模式。inviteCode是一个响应式变量,存储当前用户的邀请码。在实际项目中,这个邀请码应该从后端API获取,确保每个用户都有唯一的邀请码。inviteRecords是一个响应式列表,存储所有的邀请记录。totalReward是一个响应式变量,存储用户已获得的总奖励。onInit方法在控制器初始化时自动调用,用于加载邀请记录数据。

dart 复制代码
  void loadInviteRecords() {
    inviteRecords.value = [
      InviteRecord(
        userId: '1',
        userName: '玩家A',
        status: '已完成首次组队',
        reward: '+50积分',
        inviteTime: DateTime.now().subtract(const Duration(days: 5)),
      ),
      InviteRecord(
        userId: '2',
        userName: '玩家B',
        status: '待完成首次组队',
        reward: '待发放',
        inviteTime: DateTime.now().subtract(const Duration(days: 2)),
      ),
      InviteRecord(
        userId: '3',
        userName: '玩家C',
        status: '已完成首次组队',
        reward: '+50积分',
        inviteTime: DateTime.now().subtract(const Duration(days: 1)),
      ),
    ];
    _calculateTotalReward();
  }

loadInviteRecords方法模拟从服务器加载邀请记录。在实际项目中,这里应该调用API接口从后端获取真实的邀请数据。方法创建了三条测试数据,包括已完成和待完成的邀请记录。玩家A和玩家C已完成首次组队,因此获得了+50积分的奖励。玩家B还未完成首次组队,所以奖励显示为"待发放"。使用DateTime.now().subtract()创建不同时间的邀请记录,用于测试时间显示功能。最后调用_calculateTotalReward()计算总奖励。

dart 复制代码
  void _calculateTotalReward() {
    totalReward.value = inviteRecords
        .where((r) => r.reward.contains('+'))
        .length * 50;
  }
}

_calculateTotalReward方法计算用户已获得的总奖励。使用where()方法过滤出reward字段包含'+'的记录,这些是已完成的邀请。然后计算这些记录的数量,乘以50(每个邀请的奖励积分)得到总奖励。这个方法在loadInviteRecords之后调用,确保totalReward始终与inviteRecords保持同步。

邀请页面UI实现

dart 复制代码
class InvitePage extends StatelessWidget {
  InvitePage({super.key});
  final InviteController controller = Get.put(InviteController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('邀请好友'),
        backgroundColor: const Color(0xFF6B4EFF),
        foregroundColor: Colors.white,
        elevation: 0,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [

InvitePage是一个StatelessWidget,使用Get.put(InviteController())在页面加载时创建并注入控制器。Scaffold提供了基本的页面结构。AppBar使用紫色背景(0xFF6B4EFF),与应用的主题色保持一致。foregroundColor设置为白色,使标题和图标在紫色背景上清晰可见。elevation: 0移除AppBar的阴影效果,使界面更加扁平化。body使用SingleChildScrollView包装,支持页面内容的滚动,防止内容超出屏幕时被截断。

dart 复制代码
            // 邀请奖励卡片
            Container(
              padding: const EdgeInsets.all(24),
              decoration: BoxDecoration(
                gradient: const LinearGradient(
                  colors: [Color(0xFF6B4EFF), Color(0xFF9D4EDD)],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.circular(16),
                boxShadow: [
                  BoxShadow(
                    color: const Color(0xFF6B4EFF).withOpacity(0.3),
                    blurRadius: 12,
                    offset: const Offset(0, 4),
                  ),
                ],
              ),
              child: Column(
                children: [
                  const Icon(Icons.card_giftcard, size: 60, color: Colors.white),
                  const SizedBox(height: 16),
                  const Text(
                    '邀请好友 各得50积分',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  const Text(
                    '好友首次组队后双方各得奖励',
                    style: TextStyle(color: Colors.white70, fontSize: 14),
                  ),
                  const SizedBox(height: 20),

邀请奖励卡片是页面的核心视觉元素。使用LinearGradient创建从紫色到粉紫色的渐变背景,从左上到右下的方向增加了视觉的动感。borderRadius: 16创建圆角效果,使卡片看起来更加现代。boxShadow添加了阴影效果,使卡片在背景上更加突出,增强了立体感。卡片内容包括一个礼物图标(Icons.card_giftcard),大小为60像素,颜色为白色。下方是邀请奖励的标题"邀请好友 各得50积分",使用大字体(20)和加粗显示,吸引用户注意。最后是对奖励规则的说明"好友首次组队后双方各得奖励",使用较小的字体和半透明白色(Colors.white70)显示。

dart 复制代码
                  // 邀请码
                  Container(
                    padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Obx(() => Text(
                          controller.inviteCode.value,
                          style: const TextStyle(
                            color: Color(0xFF6B4EFF),
                            fontWeight: FontWeight.bold,
                            fontSize: 18,
                            letterSpacing: 2,
                          ),
                        )),
                        const SizedBox(width: 12),
                        GestureDetector(
                          onTap: () {
                            Get.snackbar('复制成功', '邀请码已复制到剪贴板');
                          },
                          child: const Icon(Icons.copy, color: Color(0xFF6B4EFF)),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),

邀请码容器使用白色背景,与渐变卡片形成强烈的对比。padding设置为水平20、垂直12,为邀请码提供充足的空间。borderRadius: 8创建轻微的圆角效果。Row布局包含邀请码文本和复制按钮。使用Obx包装邀请码文本,使其能够响应controller.inviteCode的变化,当邀请码更新时UI会自动刷新。letterSpacing: 2增加字符间距,使邀请码更加易读,特别是在用户手动输入时。复制按钮使用GestureDetector实现点击事件,点击时显示"复制成功"的Snackbar提示。在实际项目中,应该使用Clipboard.setData()将邀请码复制到系统剪贴板。

dart 复制代码
            // 分享方式
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.05),
                    blurRadius: 8,
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '分享方式',
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                  ),
                  const SizedBox(height: 16),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      _shareBtn(Icons.wechat, '微信', Colors.green),
                      _shareBtn(Icons.qr_code, '二维码', const Color(0xFF6B4EFF)),
                      _shareBtn(Icons.link, '复制链接', Colors.orange),
                    ],
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),

分享方式容器使用白色背景和轻微的阴影效果。padding: 16为容器内容提供充足的空间。boxShadow使用黑色半透明(0.05)创建细微的阴影,增加卡片的层次感。容器内包含一个标题"分享方式"和三个分享按钮。Row使用mainAxisAlignment: MainAxisAlignment.spaceEvenly均匀分布三个按钮,使它们之间的间距相等。三个分享按钮分别对应微信(绿色)、二维码(紫色)和复制链接(橙色)。每个按钮使用不同的颜色来区分,帮助用户快速识别。

dart 复制代码
            // 邀请统计
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.05),
                    blurRadius: 8,
                  ),
                ],
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  _statItem('邀请人数', Obx(() => Text(
                    '${controller.inviteRecords.length}',
                    style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Color(0xFF6B4EFF)),
                  ))),
                  _statItem('已获奖励', Obx(() => Text(
                    '${controller.totalReward.value}积分',
                    style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.green),
                  ))),
                ],
              ),
            ),
            const SizedBox(height: 24),

邀请统计容器显示两个关键的统计数据:邀请人数和已获奖励。使用Row布局两个统计项,mainAxisAlignment: MainAxisAlignment.spaceAround使它们均匀分布。邀请人数使用Obx包装,动态显示inviteRecords列表的长度。已获奖励也使用Obx包装,动态显示totalReward的值。邀请人数使用大字体(24)和紫色显示,强调这个数据的重要性。已获奖励使用绿色显示,绿色通常代表积极的、有益的信息。这两个统计数据帮助用户快速了解自己的邀请成果。

dart 复制代码
            // 邀请记录
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.05),
                    blurRadius: 8,
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '邀请记录',
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                  ),
                  const SizedBox(height: 16),
                  Obx(() => ListView.builder(
                    shrinkWrap: true,
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount: controller.inviteRecords.length,
                    itemBuilder: (context, index) {
                      final record = controller.inviteRecords[index];
                      return _recordItem(record);
                    },
                  )),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

邀请记录容器展示所有的邀请记录列表。使用ListView.builder动态构建邀请记录列表,这样可以高效地处理大量的邀请记录。使用Obx包装ListView,使其能够响应inviteRecords的变化。当新的邀请记录添加时,ListView会自动刷新。shrinkWrap: true使ListView只占据必要的高度,不会占据整个屏幕。physics: const NeverScrollableScrollPhysics()禁用ListView的滚动,因为整个页面已经使用SingleChildScrollView支持滚动。itemCount设置为inviteRecords的长度,itemBuilder为每条记录调用_recordItem方法构建UI。

dart 复制代码
  Widget _shareBtn(IconData icon, String label, Color color) {
    return GestureDetector(
      onTap: () {
        Get.snackbar('分享', '正在分享到$label');
      },
      child: Column(
        children: [
          Container(
            width: 56,
            height: 56,
            decoration: BoxDecoration(
              color: color.withOpacity(0.1),
              borderRadius: BorderRadius.circular(28),
            ),
            child: Icon(icon, color: color, size: 28),
          ),
          const SizedBox(height: 8),
          Text(label, style: const TextStyle(fontSize: 12)),
        ],
      ),
    );
  }

_shareBtn方法构建分享按钮。使用GestureDetector实现点击事件,点击时显示分享提示。Column布局包含一个圆形容器和标签文本。圆形容器使用color.withOpacity(0.1)创建浅色背景,使按钮看起来更加柔和。borderRadius: 28使容器成为完美的圆形(宽高都是56)。Icon使用传入的icon参数和color参数,大小为28。标签文本显示分享方式的名称,使用较小的字体(12)。这个方法的设计使得添加新的分享方式非常简单,只需要调用_shareBtn方法并传入相应的参数即可。

dart 复制代码
  Widget _statItem(String label, Widget value) {
    return Column(
      children: [
        Text(label, style: TextStyle(color: Colors.grey[600], fontSize: 12)),
        const SizedBox(height: 8),
        value,
      ],
    );
  }

  Widget _recordItem(InviteRecord record) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 12),
      child: Row(
        children: [
          const CircleAvatar(
            radius: 20,
            backgroundColor: Color(0xFF6B4EFF),
            child: Icon(Icons.person, size: 20, color: Colors.white),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  record.userName,
                  style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14),
                ),
                Text(
                  record.status,
                  style: TextStyle(color: Colors.grey[600], fontSize: 12),
                ),
              ],
            ),
          ),
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Text(
                record.reward,
                style: TextStyle(
                  color: record.reward.contains('+') ? Colors.green : Colors.grey,
                  fontWeight: FontWeight.bold,
                  fontSize: 14,
                ),
              ),
              Text(
                '${record.inviteTime.month}月${record.inviteTime.day}日',
                style: TextStyle(color: Colors.grey[500], fontSize: 11),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

_statItem方法构建统计项,包含标签和数值。标签使用灰色较小字体显示,数值使用传入的Widget参数显示,这样可以灵活地显示不同类型的数值。_recordItem方法构建邀请记录项。使用Row布局包含用户头像、用户信息和奖励信息。CircleAvatar创建圆形头像,使用紫色背景和人物图标。用户信息部分使用Column显示用户名和邀请状态。奖励信息部分显示奖励和邀请时间。已完成的邀请(reward包含'+')显示绿色奖励,待完成的邀请显示灰色。这个设计使得用户可以一目了然地了解每条邀请的状态和奖励。

技术要点

  1. 渐变背景卡片:使用LinearGradient创建吸引眼球的邀请卡片,增加视觉层次感。渐变效果从左上到右下,创建了动感的视觉效果
  2. 邀请码设计:letterSpacing增加字符间距,提升可读性,复制功能方便用户分享。邀请码是邀请功能的核心,需要确保其易读性和易复制性
  3. 分享按钮组:统一的圆形图标按钮设计,支持多种分享渠道。不同的颜色帮助用户快速识别不同的分享方式
  4. 记录状态区分:通过颜色区分已完成和待完成状态,提升用户体验。绿色表示已完成,灰色表示待完成,直观易懂
  5. 响应式更新:使用Obx实现数据的实时更新,提升应用的交互性。当数据变化时,UI会自动刷新,无需手动调用setState

小结

本篇实现了邀请好友功能,展示邀请奖励、邀请码和分享方式,记录邀请状态,激励用户分享推广App。通过多种分享渠道和清晰的邀请记录,提升用户的邀请积极性。邀请功能是用户增长的重要驱动力,合理的奖励机制和便捷的分享方式可以显著提升邀请的转化率。

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

相关推荐
JQLvopkk1 小时前
HslCommunication,一个工具测遍所有 PLC
开发语言·人工智能·c#·交互
阿狗童鞋1 小时前
Python爬虫进阶实战指南
开发语言·爬虫·python
下页、再停留1 小时前
【C#桌面客户端系列学习-7】数据查询展示
开发语言·c#·visual studio
皓月盈江1 小时前
Go读写TXT文件
开发语言·后端·golang·go·读写txt文件·bufio·go读写txt
qq_401700411 小时前
Qt Signal Mapper:一堆按钮,怎么共用一个槽函数
开发语言·qt
OpsEye1 小时前
大模型会话里的手机号、身份证,怎么自动脱敏?
javascript·ai编程
蜗牛互联网2 小时前
Java HttpClient 调用 Gemini 图像理解与金额字段校验
java·开发语言·人工智能·后端·python
蜗牛互联网2 小时前
Python Responses API视觉输入与本地金额校验最小实现
java·开发语言·人工智能·后端·python
爱喝水的小周2 小时前
实验十 Vue‑Router 王者荣耀战绩查询 APP 开发实践
前端·javascript·vue.js
yexianglunbai2 小时前
Vue 3 全面详解:从核心特性到工程化实践
前端·javascript·vue.js