让我们终于构建我们的应用程序
#javascript #angular #android #nativescript

我们今天的工作将是建立我们决定在几天前决定建造的最终临床应用程序的布局。我们将编写助手功能和一些CSS规则。

上周,我们写了很多角文件,并且是时候让我们专注于UI。

在本文的末尾,我们应该拥有一个像下图的应用程序

mockup of our app

今天的文章将非常技术性。只需抓住您的计算机和代码即可。您可以在GitHub上找到整个代码。

打开您的home.component.html

我们应用程序的屏幕需要占用所有可用空间,并分为两个部分:

  • 零件主要显示操作(例如,数字,用户选择的当前模式)。

  • 另一部分放置我们的按钮。

让我们写我们的网格布局。

我们将第一个用作容器,代表我们的应用程序的屏幕。

另外两个将分别用作操作屏幕的容器和按钮屏幕的容器。

<GridLayout rows="300, *" columns="*" class="container" height 
="100%" backgroundColor="#303030"> 

    <GridLayout  row="0" col="0" backgroundColor="#303030" columns="20,*" rows="40, *,*,*,*"> 
    </GridLayout>


 <GridLayout row="1" col="0" backgroundColor="#303030" columns="*,10,*,10,*,10,*" rows="*,*,*,*,*">

    </GridLayout>

</GridLayout>

是时候添加按钮和屏幕了。

<GridLayout columns="*" rows="300, *" height="100%" *ngIf="currentMode != modes.fg && currentMode != modes.apgar">

    <GridLayout row="0" col="0" backgroundColor={{colors.gray}} columns="20,*" rows="40, *,*,*,*"
        *ngIf="currentMode == modes.pam">
        <TextView editable="false" col="1" row="1" class="uxText" color="aquamarine">
            __{{currentMode}}__
        </TextView>
        <FlexBoxLayout col="1" , row="2">
            <TextView editable="false" col="0" row="1" *ngIf="pamArray[0]" class="uxText">
                PAS: {{pamArray[0]}}
            </TextView>
            <TextView editable="false" col="0" row="2" *ngIf="pamArray[1]" class="uxText">
                PAD: {{pamArray[1]}}
            </TextView>

            <TextView editable="false" col="0" row="2" *ngIf="!pamArray[0] && !reponse" class="uxText">
                Valeur systole
            </TextView>
            <TextView editable="false" col="0" row="2" *ngIf="pamArray[0] && !pamArray[1]" class="uxText">
                Valeur diastole
            </TextView>
        </FlexBoxLayout>


        <TextView editable="false" col="1" row="3" class="operation" fontSize="32rem">
            {{screen}}
        </TextView>

        <TextView editable="false" col="1" row="4" class="operation">
            {{reponse}}
        </TextView>

    </GridLayout>
<GridLayout row="0" col="0" backgroundColor={{colors.gray}} columns="20,*" rows="40, *,*,*,*"
        *ngIf="currentMode == modes.imc">

        <TextView editable="false" col="1" row="1" class="uxText" color="aquamarine">
            __{{currentMode}}__
        </TextView>

        <TextView editable="false" col="1" row="3" class="operation">
            {{screen}}
        </TextView>


        <FlexBoxLayout col="1" , row="2">
            <TextView editable="false" col="0" row="1" class="active" *ngIf="imcArray[0]">
                Taille: {{imcArray[0]}}
            </TextView>
            <TextView editable="false" col="0" row="2" class="active" *ngIf="imcArray[1]">
                Poids: {{imcArray[1]}}
            </TextView>

            <TextView editable="false" col="0" row="2" *ngIf="!imcArray[0] && !reponse" class="uxText">
                Valeur taille(cm)
            </TextView>
            <TextView editable="false" col="0" row="2" *ngIf="imcArray[0] && !imcArray[1]" class="uxText">
                Valeur poids(kg)
            </TextView>
        </FlexBoxLayout>


        <TextView editable="false" col="1" row="4" class="operation ">
            {{reponse}}
        </TextView>

    </GridLayout>




    <GridLayout row="1" col="0" backgroundColor="#303030" columns="*,10,*,10,*,10,*" rows="*,*,*,*,*" paddingBottom="25"
        borderTopLeftRadius="20" borderTopRightRadius="20">
        <Button row="0" col="0" text={{currentMode}}  #ac fontSize="16px" disabled></Button>
        <Button row="0" col="2" text="AC" fontSize="20" #back (tap)="bck()"></Button>
        <Button row="0" col="4" text=">" class="nextBtn" #pour (tap)="next()" backgroundColor="#001A11" color="aquamarine"
            fontSize="32"></Button>
        <Button row="0" col="6" text={{modes.pam}} class="op" #div (tap)="changeMode(div)"></Button>

        <Button row="1" col="0" text="7" class="btn" #sept (tap)="getAnim(sept)"></Button>
        <Button row="1" col="2" text="8" class="btn" #huit (tap)="getAnim(huit)"></Button>
        <Button row="1" col="4" text="9" class="btn" #neuf (tap)="getAnim(neuf)"></Button>
        <Button row="1" col="6" text="{{modes.apgar}}" class="op" #fois [nsRouterLink]="['/apgar']"></Button>


        <Button row="2" col="0" text="4" class="btn" #quatre (tap)="getAnim(quatre)"></Button>
        <Button row="2" col="2" text="5" class="btn" #cinq (tap)="getAnim(cinq)"></Button>
        <Button row="2" col="4" text="6" class="btn" #six (tap)="getAnim(six)"></Button>
        <Button row="2" col="6" text={{modes.imc}} class="op" #mois (tap)="changeMode(mois)"></Button>


        <Button row="3" col="0" text="1" class="btn" #un (tap)="getAnim(un)"></Button>
        <Button row="3" col="2" text="2" class="btn" #deux (tap)="getAnim(deux)"></Button>
        <Button row="3" col="4" text="3" class="btn" #trois (tap)="getAnim(trois)"></Button>


        <Button row="4" col="0" text="C" class="btn" #ext (tap)="reset()"></Button>
        <Button row="4" col="2" text="0" class="btn" #zero (tap)="getAnim(zero)"></Button>
        <Button row="4" col="4" text="." class="btn" #point (tap)="getAnim(point)" value="."></Button>
        <Button row="4" col="6" text="=" class="opBtm" #egal (tap)="next()"></Button>
    </GridLayout>
</GridLayout>

我们需要更新我们的组件

import { Component, OnInit } from '@angular/core'
import { Button, Color } from '@nativescript/core';
import { Page } from '@nativescript/core/ui/page';
import { checkState, clear, compute, back, scaleAnim} from '../common/functions'
@Component({
  selector: 'Home',
  templateUrl: './home.component.html',
  styleUrls: ["./home.component.css"],
})
export class HomeComponent implements OnInit {
  //members of the class
  screen = "";
  reponse = "";
  pam = true;
  apgar = false;
  fg = false;
  imc = false;

  modes = {
    imc: "IMC",
    fg: "FG",
    apgar: "AP",
    pam: "PAM"
  }
  currentMode = this.modes.pam;
  images = {
    back: "~/assets/back.svg"
  }

  pamArray = [];
  imcArray = [];
  colors = {
    gray: new Color("#383838")
  }

  //end Members of the class definition

  /************************************* Methods ******************************************/


  /**
   * getAnim - saves the buttons typed to the screen
   * @param btn : Button clicked by the user
   */
  getAnim = (btn: Button) => {
    scaleAnim(btn);
    if(checkState(this.reponse)){
      this.reponse = clear(this.reponse);
      this.pamArray = [];
      this.imcArray = [];
    }
    this.screen += btn.text;
  }
  /**
   * reset - resets the screen and all the variables
   */

  reset = ()=>{
    this.reponse = clear(this.reponse);
    this.pamArray = [];
    this.imcArray = [];
    this.screen = clear(this.screen);
  }

  /**
   * changeMode - changes the mode of the calculator
   * and updates the screen accordingly
   * @param btn : Button clicked by the user
   */
  changeMode(btn: Button) {
    const mode = btn.text;
    if (mode != this.currentMode) {
      this.screen = clear(this.screen);
      this.reponse = clear(this.reponse);
      this.imcArray = [];
      this.pamArray = [];
    };
    this.currentMode = mode;

  }

  /**
   * bck - invokes the back function
   * to delete the latest entered char in the screen
   */
  bck(){
    this.screen = back(this.screen);
  }

  /**
   * next - saves variables and do the computations
   * according to the selected mode
   */
  next() {
    //checks that the current mode is indeed "PAM"
    if (this.currentMode == this.modes.pam) {
      //computations for the "PAM" mode.
      if (!this.screen && !this.pamArray[0]){}
      if (this.pamArray[0] && this.pamArray[1]) {
        this.reponse = String(compute("PAM", this.pamArray));
        this.pamArray = [];
        this.screen = clear(this.screen);
      }
      this.pamArray.push(Number(this.screen));
      this.screen = clear(this.screen);
    }
else if(this.currentMode == this.modes.imc){
      //computationa for the "IMC" mode.
      if (!this.screen && !this.imcArray[0]){}
      if (this.imcArray[0] && this.imcArray[1]) {
        this.reponse = String(compute("IMC", this.imcArray));
        this.imcArray = [];
        this.screen = clear(this.screen);
      }
      this.imcArray.push(Number(this.screen));
      this.screen = clear(this.screen);
    }

  }

  constructor(private page: Page) {
    this.page.actionBarHidden = true;

  }

  ngOnInit(): void {


  }
}

让我们创建助手功能

我们的计算器需要计算很多东西。让我们创建一个名为 common 的文件夹和一个文件,我们将命名 functions ,其中我们将放置应用程序所需的每个辅助功能。

我对代码进行了评论,因此应该很容易理解。

export function back(screen: string){
import { ElementRef, ViewChild } from "@angular/core";
import { Button } from "@nativescript/core";
export const formulas = {
    pam: "[(PAS + (2 x PAD) )/3]",
    imc: "[Poids(Kg)/Taille^2(m)]"
}
/**
 * clear - functions to clear the screen
 * @param screen : the screen to be cleared
 */
export function clear(screen: string){
    screen = "";
    return screen;
}
/**
 * 
 * @param mode the mode chosen by the user
 * @param dest the place of the screen where 
 * the mode should be displayed
 */
export function changeMode(mode: string, dest: string){
    dest = mode;
}

/**
 * 
 * @param pas systolic arterial pressure
 * @param pad diastolic arterial pressure
 * @returns mean arterial pressure
 */
export function pam(pas: number, pad: number){
    return (2*(pad) + pas)/3
}


/**
 * imc - computes the IMC
 * @param taille: length in cm
 * @param poids: weight in Kg
 * @returns the IMC
 */
export function imc(taille: number, poids: number){
    taille = converter(taille);
    const tailleCarre = Math.pow(taille, 2);
    return poids/tailleCarre;

}
/**
 * compute - finds the right formula and computes according to
 * the mode
 * @param mode the mode chosen by the user
 * @param store the array where are stored variables
 * @returns the desired computation
 */
export function compute(mode: string, store: string[]){
    switch (mode) {
        case "PAM":
            return pam(Number(store[0]), Number(store[1]))
        case "IMC":
            return imc(Number(store[0]), Number(store[1]))
    }
}
/**
 * pusher - stores the first param in an array
 * @param screen the screen containing the first param
 * @param store the array where to store thr first param
 */
export function pusher(screen: string, store: Array<string>){
    store.push(screen);
    clear(screen);
}
/**
 * scaleAnim - animates the btn to scale 0.5 times
 * from its original state
 * @param btn : the button to be animated
 */
export function scaleAnim(btn: Button){
    btn.animate({
        scale:{x:1.5, y:1.5},
        duration: 1,
        curve: "easeOut",
        iterations: 1,
    }).then(()=>{
        btn.animate({
            scale: {x:1, y:1}
        })
    })
}
/**
 * checkState - checks the state of the screen
 * @param screen : the screen to be checked
 * @returns true if the screen is not empty
 * false otherwise
 */
export function checkState(screen: string){
    return screen?true:false;
}

/**
 * getFormula - returns the formula of the selected mode 
 * @param mode : the formula to be ruturned
 */
export function getFormula(mode: string){
    switch (mode) {
        case "PAM" || "pam":
            return formulas.pam;
        default:
            break;
    }
}
/**
 * back - delete the latest entered value in the screen
 * @param screen the screen to be sliced
 * @returns a new string
 */
export function back(screen: string){
    if (screen){
        const len = screen.length - 1;
        return screen.slice(0, len);
}
    else{
        return screen;
}
}
/**
 * converter - converts the length from cm to m
 * @params len: the length in cm
 * @returns len in m
 */
export function converter(len: number){
    return len/100;
}

/**
 * choose - helps make a choice on 3 radio btns 
 * @param vcActive : the active viewChild
 * @param vc1 : an ElementRef to reset
 * @param vc2 : an ElementRef to reset
 * @param btn : the button used to toggle the change
 */
export async function choose(vcActive: ElementRef, vc1: ElementRef, vc2: ElementRef, btn?: Button){
    vcActive.nativeElement.toggle();
    vc1.nativeElement.checked = false;
    vc2.nativeElement.checked = false;
}

让我们为我们的应用添加一些样式

打开home.component.css文件并写下这些规则

.op{
    color: aquamarine;
    background-color: transparent;
    font-size: 16em;
    margin-top: 8px;
    margin-bottom: 8px;
    z-index: 0;
  }
  .opBtm{
    border-radius:50%;
    background-color: gray;
    font-size: 25px;
    margin-bottom: 30px;
    z-index: 0;

  }
  .opBtm{
    box-shadow:  0 0 30px gray;
  }


  .uxText{
    color: white;
    font-style: italic;  
}
  .btn{
    color: #ccc;
    background-color: transparent;
    font-size: 35em;
    margin-top: 8px;
    margin-bottom: 8px;
    z-index: 0;

  }

添加图标字体

我喜欢角度材料,所以我会使用Google材料图标。

在您的应用程序的来源中,创建一个文件夹并将其命名 fonts

Download the fonts here并将它们放在 fonts 文件夹中。

在您的CSS文件中,写下这些规则

.m-icon-outlined{
     font-family: "MaterialIcons-Outlined";
     font-weight: 400;
}


请记住,字体姓氏必须匹配您字体文件夹中字体的名称。 Click here to find the code of an icon. we将使用该代码,就像建议herehere

使用here

测试您的应用程序,运行:

ns run android

如果您在运行应用程序时遇到一些问题,请参考我的github。

ps:下次我们将发布我们的应用程序,请继续关注...