HarmonyOS NEXT滑动下一页效果应该如何做?

阅读 612
avatarAI BotBETA

回答

在 HarmonyOS NEXT 中实现滑动下一页效果,可以通过使用 PageSlider 组件来实现。PageSlider 是一个支持页面滑动的容器组件,可以用来创建左右滑动切换页面的效果。

以下是一个简单的示例代码,展示了如何使用 PageSlider 实现滑动下一页效果:

// Java 代码示例
@Entry
@Component(struct = StructComponent.class)
public class PageSliderExample {

    @State
    private int currentPage = 0;

    @Build(Component.Builder.class)
    public static class PageSliderExampleBuilder extends Component.Builder {
        @Override
        public void build(ComponentContext context) {
            super.build(context);
            PageSlider pageSlider = new PageSlider(context)
                    .setPageCount(3) // 设置总页数
                    .setCurrentPage(currentPage) // 设置当前页码
                    .setPageChangedListener(new PageSlider.PageChangedListener() {
                        @Override
                        public void onPageChanged(PageSlider source, int oldPage, int newPage) {
                            currentPage = newPage; // 更新当前页码
                        }
                    });

            // 为每个页面添加内容,这里只是简单示例,可以根据需要自定义页面内容
            for (int i = 0; i < 3; i++) {
                DirectionalLayout page = new DirectionalLayout(context)
                        .setOrientation(Component.VERTICAL)
                        .setGravity(Component.Gravity.CENTER)
                        .addComponent(new Text(context).setText("Page " + (i + 1)));

                pageSlider.addPage(page);
            }

            this.addComponent(pageSlider);
        }
    }
}

在上述代码中,我们首先定义了一个 PageSlider 组件,并设置了总页数和当前页码。然后,通过 setPageChangedListener 方法为 PageSlider 添加了一个页面改变监听器,用于在页面切换时更新当前页码。最后,我们为每个页面添加了一些简单的内容(在这里是文本),并将这些页面添加到 PageSlider 中。

通过这种方式,你就可以在 HarmonyOS NEXT 应用中实现滑动下一页的效果了。

1 个回答

具体参考代码如下:

@Entry 
@Component 
struct NovelPage { 
  @Provide('fontSize') @Watch('onFontSizeChange') fontSize: number = Constants.INIT_FONT_SIZE; 
  @Provide('bgColorIndex') @Watch('onBgColorChanged') bgColorIndex: BGColorType = BGColorType.WHITE; 
  @Provide('bgColor') bgColor: string = BG_COLOR_ARRAY[BGColorType.WHITE]; 
  @Provide('offsetX') offsetX: number = 0 
  @Provide('offsetY') offsetY: number = 0; 
  @Provide('screenH') screenH: number = 0; 
  @Provide('screenW') screenW: number = 0; 
  @Provide('sumRow') sumRow: number = 0; 
  @Provide('rowWord') rowWord: number = 0; 
  @Provide('rotateAngleOne') rotateAngleOne: number = Constants.INIT_ROTATE_ANGLE_ONE; 
  @Provide('rotateAngleTwo') rotateAngleTwo: number = 0.0; 
  @Provide('curPosition') curPosition: number = 0; 
  @Provide('turnStyle') turnStyle: FlipPageType = FlipPageType.SLIDE_FLIP_PAGE; 
  @Provide('currentPageNum') @Watch('onFlush') currentPageNum: number = 1; 
  @Provide('pageWordSum') pageWordSum: number = 0; 
  @Provide('light') light: number = Constants.INIT_SCREEN_LIGHT; 
  @Provide('isSystemLight') isSystemLight: boolean = false; 
  @Provide('rowGap') rowGap: number = Constants.INIT_ROW_GAP; 
  @State currentStartIndex: number = 0; 
  @State isShow: boolean = false; 
  @State isFontChanged: boolean = false; 
 
  aboutToAppear(): void { 
    this.screenW = px2vp(display.getDefaultDisplaySync().width); 
    this.screenH = px2vp(display.getDefaultDisplaySync().height - (AppStorage.get('avoidHeight') as number)); 
    this.sumRow = Math.floor((this.screenH) / (this.fontSize + this.rowGap)); 
    this.rowWord = Math.floor((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) / this.fontSize); 
    this.simulatePageContent(); 
    this.changeSystemBarStatue(); 
  } 
 
  onFontSizeChange() { 
    this.sumRow = Math.floor((this.screenH) / (this.fontSize + this.rowGap)); 
    this.rowWord = Math.floor((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) / this.fontSize); 
    let pageWordSum = this.sumRow * this.rowWord; 
 
    if (this.currentStartIndex > pageWordSum) { 
      this.currentPageNum = Math.floor(this.currentStartIndex / (pageWordSum)) + 
        (this.currentStartIndex > 1 && this.currentStartIndex % pageWordSum > 0 ? 2 : 1); 
    } else if (this.currentStartIndex > 0) { 
      this.currentPageNum = 2; 
    } else { 
      Logger.info('currentStartIndex = ' + this.currentStartIndex); 
    } 
    this.isFontChanged = true; 
    this.simulatePageContent(); 
  } 
 
  changeSystemBarStatue(): void { 
    window.getLastWindow(getContext(this), (err, data) => { 
      const errCode = err.code; 
      if (errCode) { 
        return; 
      } 
      let SystemBarProperties: window.SystemBarProperties = { 
        statusBarColor: BG_COLOR_ARRAY[this.bgColorIndex], 
        navigationBarColor: BG_COLOR_ARRAY[this.bgColorIndex], 
        navigationBarContentColor: Constants.TRANSPARENT 
      }; 
      try { 
        data.setWindowSystemBarProperties(SystemBarProperties, (err: BusinessError) => { 
          const errCode: number = err.code; 
          if (errCode) { 
            Logger.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(err)); 
            return; 
          } 
          data.setWindowBackgroundColor(BG_COLOR_ARRAY[this.bgColorIndex]); 
        }); 
      } catch (exception) { 
        Logger.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(exception)); 
      } 
    }); 
  } 
 
  onBgColorChanged() { 
    this.changeSystemBarStatue(); 
  } 
 
  onFlush() { 
    Logger.info('currentPageNum=' + this.currentPageNum + ', isFontChanged=' + this.isFontChanged); 
    if (this.isFontChanged && this.currentPageNum === 1) { 
      this.isFontChanged = false; 
      this.currentStartIndex = 0; 
    } 
  } 
 
  simulatePageContent() { 
    this.offsetY = 0; 
    this.rotateAngleTwo = 0.0; 
    this.rotateAngleOne = Constants.INIT_ROTATE_ANGLE_ONE; 
  } 
 
  private clickAnimateTo(isLeft: Boolean) { 
    if (this.turnStyle === FlipPageType.SLIDE_FLIP_PAGE) { 
      animateTo({ 
        duration: Constants.SLIDE_DURATION, 
        curve: Curve.EaseOut, 
        onFinish: () => { 
          if (this.offsetX > 0) { 
            this.currentPageNum > 0 ? this.currentPageNum - 1 : this.currentPageNum; 
            this.currentStartIndex -= this.sumRow * this.rowWord; 
          } 
          if (this.offsetX < 0) { 
            this.currentPageNum += 1; 
            this.currentStartIndex += this.sumRow * this.rowWord; 
          } 
          Logger.info(this.currentStartIndex.toString()); 
          this.offsetX = 0; 
          this.simulatePageContent(); 
        } 
      }, () => { 
        if (isLeft) { 
          this.offsetX = this.screenW; 
        } else { 
          this.offsetX = -this.screenW; 
        } 
      }) 
    } 
  } 
 
  build() { 
    Row() { 
 
      if (this.turnStyle === FlipPageType.SLIDE_FLIP_PAGE) { 
        SlideFlipView({ 
          currentStartIndex: this.currentStartIndex 
        }) 
      } 
 
    } 
 
    .width(Constants.FULL_PERCENT) 
    .height(Constants.FULL_PERCENT) 
    .bindSheet( 
      $$this.isShow, 
      this.myBuilder(), 
      { 
        height: SheetSize.FIT_CONTENT, 
        detents: [Constants.SHEET_HEIGHT, Constants.SHEET_HEIGHT + 1], 
        showClose: true, 
        dragBar: true, 
        title: { title: Constants.SHEET_TITLE }, 
        backgroundColor: Constants.SHEET_BACKGROUND_COLOR 
      } 
    ) 
    .backgroundColor(this.bgColor) 
  } 
 
  @Builder 
  myBuilder() { 
 
 
  } 
} 
 
@Component 
export default struct Reader { 
  @Consume('bgColor') @Watch('onPageChange') bgColor: string; 
  @Consume('fontSize') @Watch('onPageChange') fontSize: number; 
  @Consume('turnStyle') turnStyle: FlipPageType; 
  @Consume('screenW') screenW: number; 
  @Consume('screenH') screenH: number; 
  @Consume('rowGap') rowGap: number; 
  @Consume('sumRow') sumRow: number 
  @Consume('rowWord') rowWord: number; 
  @Prop @Watch('onPageChange') startIndex: number = 0; 
  private settings: RenderingContextSettings = new RenderingContextSettings(true); 
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 
  private wordWidth: number = 0; 
  private wordHeight: number = 0; 
 
  aboutToAppear(): void { 
    this.drawText(this.startIndex); 
  } 
 
  onPageChange() { 
    this.drawText(this.startIndex); 
  } 
 
  drawText(startIndex: number) { 
    this.wordWidth = this.fontSize; 
    this.wordHeight = this.fontSize; 
    this.context.fillStyle = this.bgColor; 
    this.context.fillRect(0, 0, this.screenW, this.screenH); 
    this.context.fillStyle = Color.Black; 
    this.context.font = vp2px(this.fontSize) + Constants.CANVAS_FONT_SET; 
    if (startIndex < 0) { 
      startIndex = 0; 
    } 
 
    let gap = ((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) - this.wordWidth * this.rowWord) / (this.rowWord - 1); 
    let realRowGap = (this.screenH - this.sumRow * (this.wordHeight + this.rowGap)) / (this.sumRow - 1); 
    let currentX = Constants.SCREEN_MARGIN_LEFT; 
    let currentY = this.wordHeight; 
    for (let i = startIndex;; i++) { 
      if (currentX + this.wordWidth > this.screenW - (Constants.SCREEN_MARGIN_LEFT - 1)) { 
        currentX = Constants.SCREEN_MARGIN_LEFT; 
        currentY = currentY + this.rowGap + this.wordHeight + realRowGap; 
        if (currentY > this.screenH) { 
          break; 
        } 
      } 
      this.context.fillText(Constants.TEXT.charAt(i % Constants.TEXT.length), currentX, currentY); 
      currentX += this.wordWidth + gap; 
    } 
  } 
 
  build() { 
    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 
      Column() { 
        Canvas(this.context) 
          .width(Constants.FULL_PERCENT) 
          .height(Constants.FULL_PERCENT) 
          .onReady(() => { 
            this.drawText(this.startIndex); 
          }) 
      } 
      .width(Constants.FULL_PERCENT) 
    } 
    .height(Constants.FULL_PERCENT) 
  } 
} 
 
@Component 
export struct SlideFlipView { 
  @Consume('offsetX') offsetX: number; 
  @Consume('sumRow') sumRow: number; 
  @Consume('rowWord') rowWord: number; 
  @Consume('screenW') screenW: number; 
  @Consume('currentPageNum') currentPageNum: number; 
  @Link currentStartIndex: number; 
  private isFirst: boolean = false; 
 
  build() { 
    Stack() { 
      Reader({ startIndex: this.currentStartIndex + this.sumRow * this.rowWord }) 
        .translate({ x: this.offsetX >= 0 ? this.screenW : this.screenW + this.offsetX, y: 0, z: 0 }) 
 
      Reader({ startIndex: this.currentStartIndex }) 
        .translate({ x: this.offsetX, y: 0, z: 0 }) 
        .width(this.screenW) 
 
      Reader({ startIndex: this.currentStartIndex - this.sumRow * this.rowWord }) 
        .translate({ x: this.offsetX >= 0 ? -this.screenW + this.offsetX : -this.screenW, y: 0, z: 0 }) 
    } 
    .gesture( 
      PanGesture() 
        .onActionUpdate((event?: GestureEvent) => { 
          if (!event) { 
            return; 
          } 
          if (this.currentPageNum <= 1 && event.offsetX > 0) { 
            this.isFirst = true; 
            return; 
          } 
 
          this.offsetX = event.offsetX; 
        }) 
        .onActionEnd(() => { 
          animateTo({ 
            duration: Constants.FLIP_DURATION, 
            curve: Curve.EaseOut, 
            onFinish: () => { 
              if (this.offsetX > 0) { 
                this.currentPageNum -= 1; 
                if (this.currentStartIndex !== 0) { 
                  this.currentStartIndex -= this.sumRow * this.rowWord; 
                } 
              } 
              if (this.offsetX < 0) { 
                this.currentPageNum += 1; 
                this.currentStartIndex += this.sumRow * this.rowWord; 
              } 
              if (this.isFirst) { 
                promptAction.showToast({ 
                  message: Constants.MSG_FLIP_OVER, 
                  duration: Constants.PROMPT_DURATION 
                }); 
                this.isFirst = false; 
              } 
              this.offsetX = 0; 
            } 
          }, () => { 
            if (this.offsetX > 0) { 
              this.offsetX = this.screenW; 
            } 
            if (this.offsetX < 0) { 
              this.offsetX = -this.screenW; 
            } 
          }) 
        }) 
    ) 
  } 
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
HarmonyOS
子站问答
访问
宣传栏