HarmonyOS 控件高度随滚动变化

随着wanterflow 的滚动,改变上面播放器的高度

如果是竖向视频的话,随着下半屏的媒资滚动需要改变播放器的高度

HarmonyOS
2024-12-26 14:09:17
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Excelsior_abit

参考示例代码:

VideoResizeDemo.ets 这是用于将父组件高度和滚动容器的滑动偏移量联系起来

import { WaterFlowDataSource } from './WaterFlowDataSource'

@Entry
@Component
struct VideoResizeDemo {
  private readonly vipHeight: number = 100;
  @State minVideoHeight: number = 200; // 最小高度
  @State maxVideoHeight: number = 400; // 最大高度
  @State initVideoHeight: number = this.maxVideoHeight; // 初始高度
  @State vipComponentHeight: number = this.vipHeight;
  @State playerViewHeight: number = this.initVideoHeight;
  @State hasVip: boolean = true;
  @Provide('minScrollOffset') minScrollOffset: number = this.minVideoHeight - this.vipHeight;
  @Provide('scrollOffset') @Watch("limitedHeight") scrollOffset: number = this.initVideoHeight;
  limitedHeight() {
    if (this.scrollOffset < this.minVideoHeight) {
      this.playerViewHeight = this.minVideoHeight;
    } else {
      this.playerViewHeight = this.scrollOffset;
    }
    if (!this.hasVip) {
      return;
    }
    if (this.scrollOffset < this.minVideoHeight) {
      this.vipComponentHeight = this.vipHeight - (this.minVideoHeight - this.scrollOffset);
    } else if (this.vipComponentHeight != this.vipHeight) {
      this.vipComponentHeight = this.vipHeight;
    }
  }
  build() {
    Column() {
      Row() {
        Text('video')
          .width('100%')
          .height("100%")
          .fontSize(24)
          .textAlign(TextAlign.Center)
          .borderRadius(10)
          .backgroundColor("#f90")
          .onClick(() => {
            this.hasVip = !this.hasVip;
            this.minScrollOffset = this.hasVip ? this.minVideoHeight - this.vipHeight : this.minVideoHeight;
          })
      }
      .borderRadius(10)
      .backgroundColor("#f90")
      .height(this.playerViewHeight)
      Row() {
        Text('VIP')
          .width('100%')
          .height(this.vipHeight)
          .fontSize(24)
          .textAlign(TextAlign.Center)
          .backgroundColor('#FF4500')
          .position({ x: 0, y: 0 })
      }
      .clip(true)
      .visibility(this.hasVip ? Visibility.Visible : Visibility.None)
      .backgroundColor(Color.Blue)
      .width('100%')
      .height(this.vipComponentHeight)

      StickyNestedScroll({ maxOffsetHeight: this.maxVideoHeight })
        .width('100%')
        .layoutWeight(1)
        .backgroundColor('#fff')

    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Black).expandSafeArea([SafeAreaType.KEYBOARD, SafeAreaType.SYSTEM],
      [SafeAreaEdge.TOP])

  }
}
@Component
struct StickyNestedScroll {
  @State maxOffsetHeight: number = 0;
  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start }) {
        TabContent() {
          ListAndWaterFlowDemo({
            maxOffsetHeight: this.maxOffsetHeight
          })
            .width('100%')
            .layoutWeight(1)
            .backgroundColor("#fff")
        }.tabBar('Tab1')
        TabContent() {
        }.tabBar('Tab2')
      }
      .vertical(false)
    }
    .width('100%')
    .layoutWeight(1)

  }
}
VideoResizeDemo.ets 这是将之前list嵌套waterFlow的改造方案用于这次的场景 https://issuereporter.developer.huawei.com/detail/240521181106042/comment

@Reusable
@Component
struct ReusableFlowItem {
  @State item: number = 0;

  // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容
  aboutToReuse(params: Record<string, number>) {
    this.item = params.item;
    console.info('Reuse item:' + this.item)
  }
  aboutToAppear() {
    console.info('new item:' + this.item)
  }
  build() {
    Column() {
      Stack() {
        Image($r('app.media.startIcon'))
          .height('767px')
        Row()
          .height('169px')
      }
      Column()
        .height('191px')
    }

  }
}
@Component
struct ListAndWaterFlowDemo {
  @Consume('scrollOffset') scrollOffset: number;
  @Consume('minScrollOffset') minOffsetHeight: number;
  @State maxOffsetHeight: number = 0;
  private offsetY: number = 0;
  dataSource: WaterFlowDataSource = new WaterFlowDataSource();
  colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F];
  waterFlowScroller: Scroller = new Scroller();
  mySet: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
  @State sections: WaterFlowSections = new WaterFlowSections();
  titleSection: SectionOptions = {
    itemsCount: 1,
    crossCount: 1,
  };
  listSection: SectionOptions = {
    itemsCount: 1,
    crossCount: 1,
  };
  shortFilmSection: SectionOptions = {
    itemsCount: 1,
    crossCount: 1,
  };
  guestULikeTitleSection: SectionOptions = {
    itemsCount: 1,
    crossCount: 1,
  };
  guestULikeSection: SectionOptions = {
    itemsCount: this.dataSource.totalCount(),
    crossCount: 2,
    columnsGap: 5,
    rowsGap: 5,
  };

  aboutToAppear() {
    let sectionOptions: SectionOptions[] = []
    sectionOptions.push(this.titleSection);
    sectionOptions.push(this.listSection);
    sectionOptions.push(this.shortFilmSection);
    sectionOptions.push(this.guestULikeTitleSection);
    sectionOptions.push(this.guestULikeSection);
    this.sections.splice(0, 0, sectionOptions);
    this.offsetY = this.scrollOffset;
  }

  build() {
    Column() {
      WaterFlow({ scroller: this.waterFlowScroller, sections: this.sections }) {
        FlowItem() {
          Row() {
            Column() {
              Flex() {
                Text('鉴心')
                  .fontWeight(FontWeight.Bold)
                  .fontSize(20)
                  .layoutWeight(1)
                Row() {
                  Text('简介')
                  Image($r('app.media.startIcon'))
                    .width('49px')
                    .height('49px')
                }
              }
              .height('71px')
              List() {
                ListItem() {
                  Row() {
                    Text('微短剧')
                  }
                }

                ListItem() {
                  Row() {
                    Text('1.4亿次播放')
                  }
                }
              }.listDirection(Axis.Horizontal)
            }
          }
        }

        FlowItem() {
          Row() {
            Column() {
              Row() {
                Text('正片列表')
                  .fontWeight(FontWeight.Bold)
                  .fontSize(20)
                Flex({ direction: FlexDirection.RowReverse }) {
                  Text('24集全')
                  Image($r('app.media.startIcon'))
                    .width('49px')
                    .height('49px')
                }

              }
              .width('100%')
              .height(`130px`)

              List({ space: 5 }) {
                ForEach(this.mySet, (item: string, index: number) => {
                  ListItem() {
                    Stack() {
                      Column() {
                        Text(item)
                      }
                      .width('163px')
                      .height('163px')
                    }
                  }.backgroundColor(Color.Gray)
                })
              }.listDirection(Axis.Horizontal)
            }
          }
        }

        FlowItem() {
          Row() {
            Column() {
              Row() {
                Text('精彩短片')
                  .fontWeight(FontWeight.Bold)
                  .fontSize(20)
                Flex({ direction: FlexDirection.RowReverse }) {
                  Text('更多')
                  Image($r('app.media.startIcon'))
                    .width('49px')
                    .height('49px')
                }
              }

              List({ space: 5 }) {
                ForEach(this.mySet, (item: string, index: number) => {
                  ListItem() {
                    Column() {
                      Stack() {
                        Image($r('app.media.startIcon'))
                      }
                      .width('455px').height('549px')

                      Text('Obsover')
                        .width('455px').height('110px')
                    }
                  }
                })
              }.listDirection(Axis.Horizontal)
            }
          }
        }

        FlowItem() {
          Row() {
            Text('猜你喜欢')
            Flex({ direction: FlexDirection.RowReverse }) {
              Text("")
            }
          }
        }

        LazyForEach(this.dataSource, (item: number) => {
          FlowItem() {
            ReusableFlowItem({ item: item })
          }
          .width('100%')
          .backgroundColor(this.colors[item % 5])
        }, (item: string) => item)
      }
      .backgroundColor(0xFA33E0)
      .width('100%')
      .height('100%')
      .layoutWeight(1)
      .edgeEffect(EdgeEffect.None)
      .onScrollFrameBegin((offset: number) => {
        if ((offset > 0 && this.offsetY <= this.minOffsetHeight) ||
          (offset < 0 && this.offsetY >= this.maxOffsetHeight) ||
          this.waterFlowScroller.currentOffset().yOffset !== 0) {
          return { offsetRemain: offset };
        } else {
          this.offsetY -= offset;
        }
        if (this.offsetY < this.minOffsetHeight) {
          this.offsetY = this.minOffsetHeight;
        } else if (this.offsetY > this.maxOffsetHeight) {
          this.offsetY = this.maxOffsetHeight;
        }
        this.scrollOffset = this.offsetY;
        return { offsetRemain: 0 };
      })
    }
    .backgroundColor(Color.Brown)
    .width('100%')
    .height('100%')
  }
}
分享
微博
QQ
微信
回复
2024-12-26 16:18:17
相关问题
HarmonyOS select控件高度
171浏览 • 1回复 待解决
HarmonyOS SegmentButton控件修改高度
101浏览 • 1回复 待解决
如何设置父组件子组件宽度变化
2494浏览 • 1回复 待解决
HarmonyOS 如何按比例设置控件高度
145浏览 • 0回复 待解决
HarmonyOS 如何按比例设置控件高度
715浏览 • 1回复 待解决
HarmonyOS 页面高度发生变化
413浏览 • 1回复 待解决
HarmonyOS list嵌套tab中列表高度变化
58浏览 • 1回复 待解决