HarmonyOS 有没有可以左右上下都可以滚动的组件?

有没有可以左右上下都可以滚动的组件,要做查看大图的效果。

HarmonyOS
2024-10-18 11:03:10
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
superinsect

暂时没有同时支持上下左右滚动的组件,查看大图的demo可以参考:

// xxx.ets  
import router from '@ohos.router'  
@Entry  
@Component  
struct SharedTransitionExample {  
  @State active: boolean = false  
  @State imageNames: Resource[] = [$r('app.media.image1'), $r('app.media.image2'), $r('app.media.image3')]  
  @StorageLink('currentIndex') currentIndex: number = 0  
  build() {  
    Row() {  
      ForEach(this.imageNames, (res: Resource, index: number) => {  
        Column() {  
          Image(res)  
            .width('100%')  
            .height('100%')  
            .objectFit(ImageFit.Contain) // 在组件上绑定缩放比例,可以通过修改缩放比例来实现组件的缩小或者放大  
        }  
        .width(100)  
        .height(100)  
        .clip(true)  
        .sharedTransition('sharedImage' + res.id, {  
          duration: 200,  
          curve: Curve.Linear,  
          zIndex: this.currentIndex === index ? 10 : -10  
        })  
        .onClick(() => {  
          this.currentIndex = index  
          router.pushUrl({  
            url: 'pages/Index', params: {  
              data: this.imageNames,  
            }  
          })  
        })  
      })  
    }.width('100%')  
    .height('100%')  
  }  
  pageTransition() {  
    PageTransitionEnter({ duration: 0, curve: Curve.Linear })  
      .onEnter((type?: RouteType, progress?: number) => {  
      }) // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0% -- 100%)  
    PageTransitionExit({ duration: 0, curve: Curve.Ease })  
      .onExit((type?: RouteType, progress?: number) => {  
      }) // 退场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0% -- 100%)  
  }  
}
//Index页面  
import window from '@ohos.window';  
import router from '@ohos.router';  
interface Data {  
  data: Resource[];  
}  
enum Direction {  
  None,  
  Left,  
  Right,  
}  
@Entry  
@Component  
struct Index {  
  private swiperController: SwiperController = new SwiperController();  
  @State imageNames: Resource[] = []  
  @StorageLink('currentIndex') currentIndex: number = 0  
  @State screenWidth: number = 0;  
  @State op: number = 0  
  aboutToAppear() {  
    const data = (router.getParams() as Data)  
    this.imageNames = data.data  
    window.getLastWindow(getContext(this)).then(currentWindow => {  
  
      let property = currentWindow.getWindowProperties();  
      this.screenWidth = property.windowRect.width;  
    })  
  }  
  build() {  
    Stack({ alignContent: Alignment.Center }) {  
      Swiper(this.swiperController) {  
        ForEach(this.imageNames, (name: Resource, index: number) => {  
          Column() {  
            ImageComponent({  
              image: name,  
              viewWidth: this.screenWidth,  
              isCurrent: this.currentIndex === index,  
              onNeedGoNext: (dire: Direction) => {  
                if (dire === Direction.Right) {  
                  this.swiperController.showNext()  
                } else if (dire === Direction.Left) {  
                  this.swiperController.showPrevious()  
                }  
              }  
            }).zIndex(index == this.currentIndex ? 2 : 1)  
          }.width('100%')  
          .height('100%')  
          .justifyContent(FlexAlign.Center)  
        })  
      }  
      .index(this.currentIndex)  
      .indicator(false)  
      .disableSwipe(true)  
      .itemSpace(10)  
      .onChange((index: number) => {  
        this.currentIndex = index  
      })  
    }.width('100%').height('100%')  
    .backgroundColor(`rgba(0,0,0,${this.op})`)  
  }  
  pageTransition() {  
PageTransitionEnter({ duration: 200, curve: Curve.Linear })  
.onEnter((type?: RouteType, progress?: number) => {  
if (progress) {  
this.op = progress  
}  
}) // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0% -- 100  
@Component  
struct ImageComponent {  
private image: Resource = $r('app.media.icon')  
private preGeometryScale: number = 1  
@State geometryScale: number = 1  
private preOffsetX: number = 0  
private preOffsetY: number = 0  
@State geometryOffsetX: number = 0  
@State geometryOffsetY: number = 0  
@State imageWidth: number = 0  
@State imageHeight: number = 0  
@Prop viewWidth: number = 0  
@Prop isCurrent: boolean = false  
private dire: Direction = Direction.None  
private goNext: boolean = true  
private pinching: boolean = false  
private onNeedGoNext: (dire: Direction) => void = () => {  
}  
  
  reset(): Promise<void> | undefined {  
    this.preGeometryScale = 1  
    this.preOffsetX = 0  
    this.preOffsetY = 0  
    this.dire = Direction.None  
    this.goNext = true  
    if (this.geometryScale === 1) {  
      return  
    }  
    return new Promise<void>(res => {  
      animateTo({ duration: 200, onFinish: res }, () => {  
        this.geometryScale = 1  
        this.geometryOffsetX = 0  
        this.geometryOffsetY = 0  
      })  
    })  
  }  
  
  build() {  
    Column() {  
      Image(this.image)  
        .onComplete((e) => {  
          this.imageWidth = (e?.width || 0)  
          this.imageHeight = (e?.height || 0)  
        })  
        .objectFit(ImageFit.Cover)  
        .width(this.imageWidth + 'px')  
        .height(this.imageHeight + 'px')  
        .scale({  
          x: this.geometryScale,  
          y: this.geometryScale  
        })  
        .offset({  
          x: this.geometryOffsetX,  
          y: this.geometryOffsetY  
        })  
        .focusable(true)  
        .objectFit(ImageFit.Cover)  
        .autoResize(false)  
        .sharedTransition('sharedImage' + this.image.id, {  
          duration: 200,  
          curve: Curve.Linear,  
          zIndex: this.isCurrent ? 10 : -10  
        })  
    }  
    .clip(true)  
    .width('100%')  
    .height('100%')  
    .justifyContent(FlexAlign.Center)  
    .hitTestBehavior(HitTestMode.Default)  
    .parallelGesture( // 在组件上绑定二指触发的捏合手势  
      GestureGroup(GestureMode.Parallel,  
        PinchGesture({ fingers: 2 })  
          .onActionStart((event: GestureEvent) => {  
            this.pinching = true  
            this.goNext = false  
          })// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例  
          .onActionUpdate((event: GestureEvent) => {  
            const s = this.preGeometryScale * event.scale;  
            this.geometryScale = Math.max(0.6, Math.min(2, s))  
          })  
          .onActionEnd(async () => {  
            this.preGeometryScale = this.geometryScale  
            if (this.preGeometryScale < 1) {  
              await this.reset()  
            }  
            this.pinching = false  
          }),  
        PanGesture()  
          .onActionStart((event?: GestureEvent) => {  
          })  
          .onActionUpdate((event?: GestureEvent) => {  
            let offsetX = this.preOffsetX + (event?.offsetX || 0)  
            let offsetY = this.preOffsetY + (event?.offsetY || 0)  
            if (((this.imageWidth * this.geometryScale - this.viewWidth) / 2 - Math.abs(vp2px(offsetX))) <= 0) {  
              if (!this.pinching) {  
                this.dire = offsetX < 0 ? Direction.Right : Direction.Left  
              }  
              return;  
            }  
            this.goNext = false  
            this.geometryOffsetX = offsetX  
            this.geometryOffsetY = offsetY  
          })  
          .onActionEnd((event?: GestureEvent) => {  
            if ((this.dire !== Direction.None)) {  
              if (this.goNext) {  
                this.onNeedGoNext(this.dire)  
                this.reset()  
              }  
              this.goNext = true  
            }  
            this.preOffsetX = this.geometryOffsetX  
            this.preOffsetY = this.geometryOffsetY  
          }),  
      )  
    )  
  }  
}
分享
微博
QQ
微信
回复
2024-10-18 18:14:26
相关问题
有没有低代码相关文档可以阅读?
2647浏览 • 1回复 待解决
为何RichText组件中内容可以滚动
1932浏览 • 1回复 待解决
请问下有没有文字滚动动画组件
245浏览 • 1回复 待解决
有没有api可以杀掉当前进程
1503浏览 • 1回复 待解决