鸿蒙NEXT开发案例:血型遗传计算

b17.gif

【引言】

血型遗传计算器是一个帮助用户根据父母的血型预测子女可能的血型的应用。通过选择父母的血型,应用程序能够快速计算出孩子可能拥有的血型以及不可能拥有的血型。这个过程不仅涉及到了简单的数据处理逻辑,还涉及到UI设计与交互体验的设计。

【环境准备】

• 操作系统:Windows 10
• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
• 目标设备:华为Mate60 Pro
• 开发语言:ArkTS
• 框架:ArkUI
• API版本:API 12

【开发步骤】

  1. 创建组件

首先,我们使用@Entry和@Component装饰器创建一个名为BloodTypeCalculator的组件。这标志着我们的组件是鸿蒙NEXT应用的一个入口点。

@Entry
@Component
struct BloodTypeCalculator {
  // 组件的状态和方法定义
}
  1. 定义状态

为了控制组件的外观和行为,我们定义了一系列的状态变量,如主题颜色、文本颜色、边框颜色等。同时,我们也定义了两个数组来存储可能和不可能的血型结果。

@State private themeColor: string | Color = Color.Orange;
@State private textColor: string = "#2e2e2e";
@State private lineColor: string = "#d5d5d5";
@State private possibleBloodTypesText: string = "";
@State private impossibleBloodTypesText: string = "";
  1. 血型逻辑实现

接下来,实现了几个关键的方法来处理血型相关的逻辑。这些方法包括根据血型获取基因组合、组合父母的基因以获得子代可能的基因组合、根据基因组合确定血型等。

getGenes(bloodType: string): string[];
combineGenes(fatherGenes: string[], motherGenes: string[]): string[];
getBloodTypesFromGenes(genes: string[]): string[];
  1. 交互逻辑

为了实现用户选择父母血型后自动计算子代血型的功能,我们使用了@Watch装饰器监听选择的变化,并在变化时调用计算方法更新结果显示。

@State @Watch('capsuleSelectedIndexesChanged') fatherBloodTypeIndex: number[] = [0];
@State @Watch('capsuleSelectedIndexesChanged') motherBloodTypeIndex: number[] = [0];

capsuleSelectedIndexesChanged() {
  // 更新血型信息
}
  1. UI设计

最后,我们构建了用户界面,包括页面标题、工具介绍、父母血型选择区域以及结果显示区域。这里使用了Column、Row、Text和SegmentButton等组件来布局和美化界面。

build() {
  Column() {
    // 页面标题
    Text('血型遗传计算');
    // 其他UI元素...
  }
  .height('100%')
  .width('100%')
  .backgroundColor("#f4f8fb");
}

总结

通过上述步骤,我们成功地开发了一个基于鸿蒙NEXT的血型遗传计算器。这个案例不仅展示了鸿蒙NEXT框架下组件化开发的基本流程,同时也体现了通过合理的状态管理和逻辑处理,可以轻松实现复杂的业务需求。对于希望深入了解鸿蒙NEXT框架的开发者来说,这是一个很好的实践案例。希望这篇文章能为你提供灵感,鼓励你在鸿蒙NEXT的开发道路上继续前行。

【完整代码】

// 导入SegmentButton及其相关类型定义
import { SegmentButton, SegmentButtonItemTuple, SegmentButtonOptions } from '@kit.ArkUI';

// 使用@Entry装饰器标记此组件为入口点
@Entry
  // 使用@Component装饰器标记此结构体为一个组件
@Component
  // 定义一个名为BloodTypeCalculator的结构体,用于实现血型遗传计算功能
struct BloodTypeCalculator {
  // 定义主题颜色,默认为橙色
  @State private themeColor: string | Color = Color.Orange;
  // 定义文本颜色,默认为深灰色
  @State private textColor: string = "#2e2e2e";
  // 定义边框颜色,默认为浅灰色
  @State private lineColor: string = "#d5d5d5";
  // 定义基础内边距大小,默认为30
  @State private basePadding: number = 30;
  // 存储可能的血型结果
  @State private possibleBloodTypesText: string = "";
  // 存储不可能的血型结果
  @State private impossibleBloodTypesText: string = "";
  // 定义血型列表,包含A、B、AB、O四种血型
  @State private bloodTypeList: object[] = [Object({ text: 'A' }), Object({ text: 'B' }), Object({ text: 'AB' }), Object({ text: 'O' })];
  // 初始化单选胶囊按钮的配置项
  @State singleSelectCapsuleOptions: SegmentButtonOptions | undefined = undefined;
  // 监听父亲血型选择变化
  @State @Watch('capsuleSelectedIndexesChanged') fatherBloodTypeIndex: number[] = [0];
  // 监听母亲血型选择变化
  @State @Watch('capsuleSelectedIndexesChanged') motherBloodTypeIndex: number[] = [0];

  // 根据血型获取其可能的基因组合
  getGenes(bloodType: string): string[] {
    console.info(`bloodType:${bloodType}`);
    switch (bloodType) {
      case 'A': return ['A', 'O']; // A型血可能的基因组合
      case 'B': return ['B', 'O']; // B型血可能的基因组合
      case 'AB': return ['A', 'B']; // AB型血可能的基因组合
      case 'O': return ['O']; // O型血可能的基因组合
      default: throw new Error('Invalid blood type'); // 非法血型抛出错误
    }
  }

  // 组合父母的基因以获得子代可能的基因组合
  combineGenes(fatherGenes: string[], motherGenes: string[]): string[] {
    const possibleGenes: string[] = []; // 用于存储可能的基因组合
    for (const fatherGene of fatherGenes) {
      for (const motherGene of motherGenes) {
        const combinedGene = [fatherGene, motherGene].sort().join(''); // 将父母的基因组合并排序后加入数组
        if (!possibleGenes.includes(combinedGene)) {
          possibleGenes.push(combinedGene); // 如果组合尚未存在,则加入数组
        }
      }
    }
    return possibleGenes; // 返回所有可能的基因组合
  }

  // 根据基因组合确定血型
  getBloodTypesFromGenes(genes: string[]): string[] {
    const bloodTypes: string[] = []; // 用于存储可能的血型
    for (const gene of genes) {
      if (gene === 'AA' || gene === 'AO' || gene === 'OA') {
        bloodTypes.push('A'); // 基因组合为AA、AO或OA时,血型为A
      } else if (gene === 'BB' || gene === 'BO' || gene === 'OB') {
        bloodTypes.push('B'); // 基因组合为BB、BO或OB时,血型为B
      } else if (gene === 'AB' || gene === 'BA') {
        bloodTypes.push('AB'); // 基因组合为AB或BA时,血型为AB
      } else if (gene === 'OO') {
        bloodTypes.push('O'); // 基因组合为OO时,血型为O
      }
    }
    // 去除重复的血型
    return bloodTypes.filter((value, index, self) => self.indexOf(value) === index);
  }

  // 计算孩子可能的血型及不可能的血型
  calculatePossibleBloodTypes(father: string, mother: string) {
    const fatherGenes = this.getGenes(father); // 获取父亲的基因组合
    const motherGenes = this.getGenes(mother); // 获取母亲的基因组合
    const possibleGenes = this.combineGenes(fatherGenes, motherGenes); // 组合父母的基因
    const possibleBloodTypes = this.getBloodTypesFromGenes(possibleGenes); // 从基因组合中获取可能的血型
    const allBloodTypes: string[] = ['A', 'B', 'AB', 'O']; // 所有可能的血型列表
    const impossibleBloodTypes = allBloodTypes.filter(bt => !possibleBloodTypes.includes(bt)); // 计算不可能的血型
    console.log(this.possibleBloodTypesText = `孩子可能血型:${possibleBloodTypes.join('、')}`); // 显示可能的血型
    console.log(this.impossibleBloodTypesText = `孩子不可能血型:${impossibleBloodTypes.join('、')}`); // 显示不可能的血型
  }

  // 当胶囊按钮的选择发生变化时调用此函数
  capsuleSelectedIndexesChanged() {
    let father: string = this.bloodTypeList[this.fatherBloodTypeIndex[0]]['text']; // 获取父亲选择的血型
    let mother: string = this.bloodTypeList[this.motherBloodTypeIndex[0]]['text']; // 获取母亲选择的血型
    this.calculatePossibleBloodTypes(father, mother); // 计算并更新血型信息
  }

  // 在组件即将出现时调用此函数
  aboutToAppear(): void {
    this.singleSelectCapsuleOptions = SegmentButtonOptions.capsule({
      buttons: this.bloodTypeList as SegmentButtonItemTuple, // 设置胶囊按钮的选项
      multiply: false, // 单选模式
      fontColor: Color.White, // 字体颜色为白色
      selectedFontColor: Color.White, // 选中时字体颜色为白色
      selectedBackgroundColor: this.themeColor, // 选中背景色为主题色
      backgroundColor: this.lineColor, // 背景色为边框颜色
      backgroundBlurStyle: BlurStyle.BACKGROUND_THICK // 背景模糊效果
    });
    this.capsuleSelectedIndexesChanged(); // 初始化时调用选择变化处理函数
  }

  // 构建用户界面
  build() {
    Column() {
      // 页面标题
      Text('血型遗传计算')
        .fontColor(this.textColor) // 文本颜色
        .fontSize(18) // 字体大小
        .width('100%') // 宽度为100%
        .height(50) // 高度为50
        .textAlign(TextAlign.Center) // 文本居中对齐
        .backgroundColor(Color.White) // 背景色为白色
        .shadow({ // 添加阴影效果
          radius: 2, // 阴影半径
          color: this.lineColor, // 阴影颜色
          offsetX: 0, // 水平偏移量
          offsetY: 5 // 垂直偏移量
        });

      // 工具介绍部分
      Column() {
        Text('工具介绍').fontSize(20).fontWeight(600).fontColor(this.textColor);
        Text('血型是以A、B、O三种遗传因子的组合而决定的,根据父母的血型,就可以判断出以后出生的孩子的血型。')
          .fontSize(18).fontColor(this.textColor).margin({ top: `${this.basePadding / 2}lpx` });
      }
      .alignItems(HorizontalAlign.Start)
      .width('650lpx')
      .padding(`${this.basePadding}lpx`)
      .margin({ top: `${this.basePadding}lpx` })
      .borderRadius(10)
      .backgroundColor(Color.White)
      .shadow({
        radius: 10,
        color: this.lineColor,
        offsetX: 0,
        offsetY: 0
      });

      // 父亲血型选择部分
      Column() {
        Row() {
          Text('父亲血型').fontColor(this.textColor).fontSize(18);
          SegmentButton({
            options: this.singleSelectCapsuleOptions, // 胶囊按钮的配置项
            selectedIndexes: this.fatherBloodTypeIndex // 当前选中的索引
          }).width('400lpx');
        }.height(45).justifyContent(FlexAlign.SpaceBetween).width('100%');

        // 母亲血型选择部分
        Row() {
          Text('母亲血型').fontColor(this.textColor).fontSize(18);
          SegmentButton({
            options: this.singleSelectCapsuleOptions, // 胶囊按钮的配置项
            selectedIndexes: this.motherBloodTypeIndex // 当前选中的索引
          }).width('400lpx');
        }.height(45).justifyContent(FlexAlign.SpaceBetween).width('100%');
      }
      .alignItems(HorizontalAlign.Start)
      .width('650lpx')
      .padding(`${this.basePadding}lpx`)
      .margin({ top: `${this.basePadding}lpx` })
      .borderRadius(10)
      .backgroundColor(Color.White)
      .shadow({
        radius: 10,
        color: this.lineColor,
        offsetX: 0,
        offsetY: 0
      });

      // 显示计算结果
      Column() {
        Row() {
          Text(this.possibleBloodTypesText).fontColor(this.textColor).fontSize(18);
        }.height(45).justifyContent(FlexAlign.SpaceBetween).width('100%');
        Row() {
          Text(this.impossibleBloodTypesText).fontColor(this.textColor).fontSize(18);
        }.height(45).justifyContent(FlexAlign.SpaceBetween).width('100%');
      }
      .alignItems(HorizontalAlign.Start)
      .width('650lpx')
      .padding(`${this.basePadding}lpx`)
      .margin({ top: `${this.basePadding}lpx` })
      .borderRadius(10)
      .backgroundColor(Color.White)
      .shadow({
        radius: 10,
        color: this.lineColor,
        offsetX: 0,
        offsetY: 0
      });
    }
    .height('100%')
    .width('100%')
    .backgroundColor("#f4f8fb"); // 页面背景色
  }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容

  • 【1】引言(完整代码在最后面) 在鸿蒙NEXT系统中,开发一个有趣且实用的转盘应用不仅可以提升用户体验,还能展示鸿...
    zhongcx阅读 53评论 0 1
  • 【引言】 简体繁体转换器是一个实用的小工具,它可以帮助用户轻松地在简体中文和繁体中文之间进行转换。对于需要频繁处理...
    zhongcx阅读 51评论 0 1
  • 【引言】 本文将介绍如何使用鸿蒙NEXT框架开发一个简单的光强仪应用,该应用能够实时监测环境光强度,并给出相应的场...
    zhongcx阅读 43评论 0 1
  • 【1】引言 “指尖轮盘”是一个简单而有趣的互动游戏(类似抓阄),这个应用通过触摸屏幕的方式,让玩家参与一个激动人心...
    zhongcx阅读 39评论 0 1
  • 【引言】(完整代码在最后面) 本文将通过一个简单的计数器应用案例,介绍如何利用鸿蒙NEXT的特性开发高效、美观的应...
    zhongcx阅读 65评论 0 1