HarmonyOS 项目开发练习 「钢笔单词」 #4 单词学习页 涉及弹性布局(FLEX)、用户首选项、关系型数据库

HarmonyOS | 项目开发练习 「钢笔单词」 #4 单词学习页 | 涉及弹性布局(FLEX)、用户首选项、关系型数据库

项目结构:

在这里插入图片描述

单词学习页:

​ 通过在书架里面点击词书,即可路由到这个页面,主要进行单词选择、单词背诵、拼写以及单词遮盖。可以点击左侧的滑动列表中的单词以切换单词,也可以点击蓝色的按钮进行逐词切换。点击“眼睛”可以显示或隐藏单词,点击“折叠箭头”可以将左侧的滑动列表折叠(真的是折叠)。点击拼写按钮会弹出拼写输入框,同时其它卡片会被折叠(真的是折叠)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

LearningIndex.ets 构成单词学习页面,是的,这个文件非常简短,因为我把代码都写进这里面的那个唯一的模块里了(哭)。

``

import LearningCard from '../view/Learning_page/LearningCard'
@Entry
@Component
struct LearningIndex {
  build() {
    Flex(){
      LearningCard({sum: 40})
    }
  }
}

LearningCard.ets 单词学习页面几乎在这一个文件里面完成,写的也比较粗糙,而且我没有实现数据库,所以用数组进行替代

``

import router from '@ohos.router'
import Word from '../../model/Word'
import WordModel from '../../viewModel/WordModel'
import SpellingDialog from './SpellingDialog'

@Component
export default struct LearningHeader {
  private sum: number // 需要背诵的单词数量
  @State index: number = 1 // 当前背诵的单词的序号

  words: Word[] = [
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。'),
    new Word('occupy', '英/ˈɒkjupaɪ/  \n美/ˈɑːkjupaɪ/', 'v.使用(房屋、建筑),居住;占据(空间,时间);使忙于(做某事);使一直在想;(军事)占领,占据;(尤指为表示抗议而)非法强占(建筑物);任职,位居', '', 'How much memory does the program occupy? 这个程序占用多少内存?'),
    new Word('process', '英/ˈprəʊses/  \n美/ˈprɑːses/', 'n.步骤,程序;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。')
  ]

  @State wordDisplay: string = '******'
  @State soundmarkDisplay: string = this.words[0].soundmark
  @State paraphraseDisplay: string = this.words[0].paraphrase
  @State sentenceDisplay: string = this.words[0].sentence

  @State leftCardWidth: string = '30%'
  @State rightCardWidth: string = '65%'

  @State isVisible: boolean = false // 单词可见性
  @State eyesIcon: Resource = $r('app.media.cleyes')

  controller: CustomDialogController = new CustomDialogController({
    builder: SpellingDialog({answer: this.words[this.index - 1].word, cancel: () => this.cancel()})
  })
  cancel() {
    this.leftCardWidth = '30%'
    this.rightCardWidth = '65%'
  }
   handleAddWord(word: string, soundmark: string, paraphrase: string, audioLink: string, sentence: string) {
    WordModel.addWord(word, soundmark, paraphrase, audioLink, sentence)
      .then(id => {
        console.log('新增单词')
        this.words.push(new Word(word, soundmark, paraphrase, audioLink, sentence))
      })
      .catch(e => console.error('新增单词失败-' + word))
  }

  // aboutToAppear(){
  //   WordModel.addWord('123', '英/4/  \n美/5/', 'n.步骤,6;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。')
  //   this.handleAddWord('123', '英/4/  \n美/5/', 'n.步骤,6;(自然或偶然的)变化过程;(为达到某目标的)过程,进程;制作方法,加工方法;<法律>传票;(生,剖)端突,突起adj.(印刷)三原色的,三色版的; 经过特殊加工的;照相板的v.(用化学物品或机器)处理,加工;审核,受理(正式文件或请求);(计算机)处理(数据);冲洗(照片);加工(食品);<正式>列队行进;把(头发)弄成直发', '', 'The process was needlessly slow. 进程过于缓慢了。')
  //   WordModel.getWordList()
  //     .then(list => {
  //     })
  // }
  build() {
    Flex({direction: FlexDirection.Column}){
      Flex({alignItems: ItemAlign.Center}){
        Image($r('app.media.leacancle')).fillColor('#ff262626').width(50)
          .onClick(() => {
            router.back()
          })
        Text(this.index.toString()).fontSize(40)
      }
      Divider()

      Flex({alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly}){
        Flex({direction: FlexDirection.Column}){
          Text('生词本').fontSize(25)
          Flex({direction: FlexDirection.Column}){
            List({space: 10}){
              ForEach(
                this.words,
                (word, idx) => {
                  ListItem() {
                    Flex({direction: FlexDirection.Column}) {
                      Divider().color(Color.White)
                      Text((idx + 1) + '  ' + word.word + '  \n' + word.soundmark).fontSize(30).fontColor(Color.White)
                    }.padding({left: 20})
                    .onClick(() => {
                      if(this.isVisible) this.wordDisplay = this.words[idx].word
                      else this.wordDisplay = '******'
                      this.soundmarkDisplay = this.words[idx].soundmark
                      this.paraphraseDisplay = this.words[idx].paraphrase
                      this.sentenceDisplay = this.words[idx].sentence
                      this.index = idx + 1
                    })
                  }
                })
            }.borderRadius(10).layoutWeight(1)
          }.backgroundColor('#ff313a4a').width('100%').borderRadius(10)

        }.width(this.leftCardWidth).height('90%').borderRadius(10)
        .shadow({radius: 5, color: $r('app.color.light_primary_color')})

        Flex({direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround}){
          Text('单词卡片').fontSize(25)
          Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}){
            Flex({alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly}){
              Text(this.wordDisplay).fontSize(80).fontColor(Color.White).margin({top: 10}).fontWeight(FontWeight.Bold)
              Text(this.soundmarkDisplay).fontSize(25).fontColor(Color.White).margin({top: 10})
            }
            List(){
              ListItem(){
                Text(this.paraphraseDisplay).fontSize(30).fontColor(Color.White).margin({top: 10})
              }
            }.height('30%').backgroundColor('#ff353535').margin({top: 20, bottom: 20}).padding(10)
            Text(this.sentenceDisplay).fontSize(30).fontColor(Color.White).margin({top: 10})
              .backgroundColor('#ff353535').padding(10)
            Flex({justifyContent: FlexAlign.SpaceEvenly, alignItems: ItemAlign.Center}){
              Button('上一个')
                .onClick(() => {
                  if(this.index <= 1) return;
                  let idx = this.index - 2
                  this.index = this.index - 1

                  if(this.isVisible) this.wordDisplay = this.words[idx].word
                  else this.wordDisplay = '******'
                  this.soundmarkDisplay = this.words[idx].soundmark
                  this.paraphraseDisplay = this.words[idx].paraphrase
                  this.sentenceDisplay = this.words[idx].sentence
                })

              Button('下一个')
                .onClick(() => {
                  if(this.index >= this.words.length) return;

                  let idx = this.index
                  this.index = this.index + 1

                  if(this.isVisible) this.wordDisplay = this.words[idx].word
                  else this.wordDisplay = '******'
                  this.soundmarkDisplay = this.words[idx].soundmark
                  this.paraphraseDisplay = this.words[idx].paraphrase
                  this.sentenceDisplay = this.words[idx].sentence
                })
              Image(this.eyesIcon).fillColor('#ffe3e3e3').width(40)
                .onClick(() => {
                  this.isVisible = !this.isVisible

                  if(this.isVisible) this.wordDisplay = this.words[this.index - 1].word
                  else this.wordDisplay = '******'
                  this.soundmarkDisplay = this.words[this.index - 1].soundmark
                  this.paraphraseDisplay = this.words[this.index - 1].paraphrase
                  this.sentenceDisplay = this.words[this.index - 1].sentence

                  if(this.isVisible) this.eyesIcon = $r('app.media.eyes')
                  else this.eyesIcon = $r('app.media.cleyes')
                })
              Image($r('app.media.spell')).fillColor('#ffe3e3e3').width(40)
                .onClick(() => {
                  this.leftCardWidth = '10'
                  this.rightCardWidth = '10'

                  this.controller.open()
                })
              Image($r('app.media.zhedie')).fillColor('#ffe3e3e3').width(40)
                .onClick(() => {
                  if(this.leftCardWidth === '30%'){
                    this.leftCardWidth = '10'
                    this.rightCardWidth = '85%'
                  }
                  else {
                    this.leftCardWidth = '30%'
                    this.rightCardWidth = '65%'
                  }
                })
            }.height('20%')


          }.backgroundColor('#ff414141').width('100%').borderRadius(10)
        }.width(this.rightCardWidth).height('90%').borderRadius(10)
        .shadow({radius: 5, color: $r('app.color.light_primary_color')})
      }.height('100%')
    }
  }
}

SpellingDialog.ets 拼写弹窗,这是一个自定义弹窗

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

``

import CommonConstants from '../../common/constants/CommonConstants'

@CustomDialog
export default struct UserPrivacyDialog {
  controller: CustomDialogController

  cancel: () => void
  private answer: string // 正确答案
  @State userInput: string = '请输入单词' // 用户输入

  confirm() {
    if (this.answer === this.userInput)
      this.userInput = '正确'
    else this.userInput = '错误'
  }
  build() {
    Column({space: CommonConstants.SPACE_10}){
      Text('拼写').fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_700) // 隐私弹窗标题
      Divider().color($r('app.color.primary_color'))
      TextInput()
        .onChange((val) => {
          this.userInput = val
        })
      Text(this.userInput).fontColor('#ff858585')
      // Text(this.answer).fontColor('#ff858585')
      Button('检验拼写').backgroundColor($r('app.color.primary_color'))
        .width('50%').onClick(() =>{
        this.confirm()
      }) // 确定按钮
      Button('关闭窗口').backgroundColor($r('app.color.lightest_primary_color'))
        .fontColor($r('app.color.light_gray')).width('50%').onClick(() => {
        this.controller.close()
        this.cancel()
      }) // 返回按钮
    }.width('100%').padding(10).border({width: 1, color: $r('app.color.primary_color'), radius: 10})
  }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JayHsu_蔚蓝审敛法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值