Requirement Description
When using the Scroll component, subcomponents slide out of the main page during scrolling. How can we determine whether a subcomponent is currently visible?
onScrollStop(() => {
// After scrolling stops, determine whether a new video needs to play
// (not the previous index && the previous video is halfway off-screen)
if (this.scrollIndex !== this.currentPlayIndex && this.theLastIsOutScreen) {
this.currentPlayIndex = this.scrollIndex
this.theLastIsOutScreen = false
this.isShowPlay = true
}
// Requirement: Here, determine whether the Image view with index = currentPlayIndex + 1 is visible?
})
Background Knowledge
This method obtains the size and position of a subcomponent relative to the container component.
Supported components include Scroll, List, Grid, and WaterFlow.
The parameter index must be the index of a subcomponent displayed in the current visible area; otherwise, it is considered invalid.
For invalid values, both the size and position returned are 0.
Represents the size and position of a subcomponent relative to the component. It is the return object of the getItemRect method.
Implementation Steps
Use the getItemRect method to obtain a RectResult object and check whether its attributes x, y, width, and height are all non-zero; otherwise, the subcomponent is not visible.
Code Snippet
For example, using the Scroll component, the code is as follows:
- Index.ets
import { display } from '@kit.ArkUI'
import { VideoView } from './VideoView'
@Entry
@Component
struct VideoListPage {
// Image resources need to be replaced by the developer
private list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// Whether video is playing
@State isShowPlay: boolean = false
@State screenHeight: number = 0
@State screenWidth: number = 0
// Record the index of the currently playing video
@State currentPlayIndex: number = 0;
// The current scroll position of the list
@State scrollIndex: number = 0;
// Whether the previously played video is half off-screen
@State theLastIsOutScreen: boolean = false;
@State mDirection: number = 0;
playPosition: number | undefined = 0
@State videoUrl: string = ''
private listScroller: Scroller = new Scroller();
aboutToAppear(): void {
// Set log level: DEBUG, INFO, WARNING, ERROR.
// If not called, logs are not enabled.
// Start playing from the 2nd item
this.currentPlayIndex = 2
this.isShowPlay = true
this.screenWidth = this.getUIContext().px2vp(display.getDefaultDisplaySync().width)
this.screenHeight = this.getUIContext().px2vp(display.getDefaultDisplaySync().width) * 9 / 16
}
build() {
List({ scroller: this.listScroller }) {
ForEach(this.list, (item: string, index: number) => {
ListItem() {
Stack() {
if (this.isShowPlay && this.currentPlayIndex === index) {
VideoView()
.height(this.screenHeight)
.width(this.screenWidth)
.onVisibleAreaChange([0, 0.5], (isVisible: boolean, currentRatio: number) => {
if (this.currentPlayIndex === index) {
// Video is halfway off-screen
if (currentRatio <= 0.5) {
this.theLastIsOutScreen = true
} else {
this.theLastIsOutScreen = false
}
}
})
.backgroundColor(Color.Black)
} else {
Image($r('app.media.drag_and_exchange_ic_public_app3')) // Image resource must be replaced by the developer
.backgroundColor(Color.Gray)
.onClick(() => {
this.currentPlayIndex = index
this.isShowPlay = true
})
.height(this.screenHeight)
.width(this.screenWidth)
}
}
// 1. Implement full-screen feature:
// To implement full-screen, click the full-screen button.
// This will expand the video component height to 100% of the screen.
// You can also hide other list items and display only the current video item.
.visibility(this.mDirection === 1 && this.currentPlayIndex !== index ? Visibility.None : Visibility.Visible)
}
})
}.onScrollIndex((start: number, end: number, center: number) => {
// Record the last center position during scrolling
this.scrollIndex = center
})
.onScrollStop(() => {
// After scrolling stops, determine whether to play a new video
// (not the previous index && previous video is half off-screen)
if (this.scrollIndex !== this.currentPlayIndex && this.theLastIsOutScreen) {
this.currentPlayIndex = this.scrollIndex
this.theLastIsOutScreen = false
this.isShowPlay = true
}
// Requirement: Here, determine whether the Image view with index = currentPlayIndex + 1 is visible?
let rectResult = this.listScroller.getItemRect(this.currentPlayIndex + 1)
console.info('hm-->' + 'RectResult.x:' + rectResult.x, 'RectResult.y:' + rectResult.y,
'RectResult.width:' + rectResult.width, 'RectResult.height:' + rectResult.height)
})
}
}
- VideoView.ets
@Component
export struct VideoView {
// Vertical swipe gesture controls brightness and volume
private panOptionBrightAndVolume: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Vertical });
// Horizontal swipe gesture controls fast-forward and rewind
private panOptionSeek: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Horizontal });
build() {
Row()
.gesture(GestureGroup(GestureMode.Exclusive,
TapGesture({ count: 2 }).onAction((event: GestureEvent | undefined) => {
// Double tap
}),
TapGesture().onAction((event: GestureEvent | undefined) => {
// Single tap
}),
PanGesture(this.panOptionBrightAndVolume)
.onActionStart((event: GestureEvent | undefined) => {
})
.onActionUpdate((event: GestureEvent | undefined) => {
})
.onActionEnd((event: GestureEvent | undefined) => {
}),
PanGesture(this.panOptionSeek)
.onActionStart((event: GestureEvent | undefined) => {
})
.onActionUpdate((event: GestureEvent | undefined) => {
})
.onActionEnd((event: GestureEvent | undefined) => {
})
))
.onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => {
if (gestureInfo.type === GestureControl.GestureType.PAN_GESTURE) {
// Return REJECT to cancel the drag gesture
return GestureJudgeResult.REJECT;
}
return GestureJudgeResult.CONTINUE;
})
.height('100%')
.width('100%')
.backgroundColor(Color.White)
}
}
Test Results
I hm-->RectResult.x:0 RectResult.y:205.29904174804688 RectResult.width:233 RectResult.height:131.0625
I hm-->RectResult.x:0 RectResult.y:132.17404174804688 RectResult.width:233 RectResult.height:131.0625
Limitations or Considerations
This example supports API Version 19 Release and above.
This example supports HarmonyOS 5.1.1 Release SDK and above.
This example must be compiled and run using DevEco Studio 5.1.1 Release or later.

Top comments (0)