# Swiper组件实现试卷打分功能

#### 问题现象

如何实现试卷打分功能？

#### 效果预览

#### 背景知识

*   Swiper是HarmonyOS中的滑块视图容器，提供子组件滑动轮播显示的能力。
*   LazyForEach从数据源中按需迭代数据，并在每次迭代时创建相应组件。当在滚动容器中使用了LazyForEach，框架会根据滚动容器可视区域按需创建组件，当组件滑出可视区域外时，框架会销毁并回收组件以降低内存占用。
*   TextInput是一种单行文本输入框组件，可用于数据的输入，当按下输入法回车键触发该组件的onSubmit回调函数。

#### 解决方案

1.  创建分数数组scores，用于保存每道题的分数。
2.  使用LazyForEach结合Swiper组件循环渲染每个数据源中的元素，前五个页面表示试卷的题目信息，最后一个页面用于计算试卷的总分。
3.  在试卷的题目页面，通过TextInput组件实现分数输入，并在输入完成后使用onSubmit回调函数将输入数据存储到scores数组中。
4.  在试卷的总分页面，自定义calculate函数，用于计算scores数组的数组和。

```
// Index.ets
class MyDataSource implements IDataSource {
  private list: number[] = [];

  constructor(list: number[]) {
    this.list = list;
  }

  totalCount(): number {
    return this.list.length;
  }

  getData(index: number): number {
    return this.list[index];
  }

  registerDataChangeListener(): void {
  }

  unregisterDataChangeListener() {
  }
}

@Entry
@Component
struct Page {
  private swiperController: SwiperController = new SwiperController();
  private data: MyDataSource = new MyDataSource([]);
  controller: TextInputController | undefined;
  @State scores: string[] = ['0', '0', '0', '0', '0'];
  @State sum: number = 0;
  @State currentIndex: number = 0;

  calculate(): void {
    let sum = 0;
    for (let i = 0; i < 5; i++) {
      sum += parseInt(this.scores[i].toString());
    }
    this.sum = sum;
  }

  aboutToAppear(): void {
    let list: number[] = [];
    for (let i = 0; i < 6; i++) {
      list.push(i);
    }
    this.data = new MyDataSource(list);
  }

  build() {
    Column({ space: 5 }) {
      Swiper(this.swiperController) {
        LazyForEach(this.data, (index: number) => {
          Column() {
            if (index === 5) {
              Text(`总得分：${this.sum} 分`)
                .textAlign(TextAlign.Center)
                .fontSize(30);
            } else {
              Row() {
                Text(`第${index + 1}题`)
                  .backgroundColor(0xAFEEEE)
                  .textAlign(TextAlign.Center)
                  .fontSize(30);
              };

              Row() {
                Text(`本题得分：${this.scores[index]}分`)
                  .backgroundColor(0xAFEEEE)
                  .textAlign(TextAlign.Center)
                  .fontSize(30);
              };
            }
          }
          .backgroundColor(0xAFEEEE)
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center);
        }, (item: string) => item);
      }
      .displayCount(1, true)
      .interval(4000)
      .duration(1000)
      .itemSpace(10)
      .indicator(false)
      .width('100%')
      .height('80%')
      .loop(false)
      .onAnimationEnd((index: number) => {
        this.calculate();
        this.currentIndex = index;
      });

      if (this.currentIndex !== 5) {
        Row({ space: 20 }) {
          Button('上一题')
            .onClick(() => {
              this.swiperController.showPrevious();
            });
          Button('下一题')
            .onClick(() => {
              this.swiperController.showNext();
            });
        };

        Row() {
          Text('本题满分20分，请输入得分：');
        };

        Row() {
          TextInput({ text: this.scores[this.currentIndex], placeholder: '请输入0-20之间的数字' })
            .inputFilter('[\-0-9]', (val) => {
              console.error('TextInputExample ： ' + val);
              return 0;
            })
            .onChange((text) => {
              let num: number = Number(text);
              if (num < 0) {
                this.scores[this.currentIndex] = '0';
              } else if (num > 20) {
                this.scores[this.currentIndex] = '20';
              } else {
                this.scores[this.currentIndex] = num.toString();
              }
            })
            .maxLength(2)
            .padding({ left: 16 })
            .placeholderFont({ size: 14 })
            .fontSize(14)
            .onSubmit((EnterKeyType, Event) => {
              this.scores[this.currentIndex] = Event.text;
            })
            .width('80%');
        };
      }
    }.width('100%')
    .margin({ top: 5 });
  }
}
```