Read the original article:Fixing Duplicate Exit Animations When Dismissing bindSheet in ArkUI Lists
Fixing Duplicate Exit Animations When Dismissing bindSheet in ArkUI Lists
Problem Description
When using a semi-modal sheet via bindSheet for a “Share” popup, dismissing the sheet by tapping outside or dragging triggers the exit animation twice.
Background Knowledge
bindSheet presents a modal, non-fullscreen sheet over part of the parent view.
Its first parameter controls visibility; the second parameter is a CustomBuilder that defines the sheet’s content.
Troubleshooting Process
- The UI is built with
ForEach, producing multipleListItems. -
bindSheetis applied to each item’s child component, all bound to the sameisShowstate and the sameShareBuilder. - When the user taps Share to friends,
isShowbecomestrue, effectively creating multiple stacked sheets (one per item). - On dismiss, the tapped sheet closes first; the two-way binding (
$$) then flipsisShowtofalse, causing the remaining hidden sheets to dismiss too—so visually the exit animation appears twice.
Analysis Conclusion
Multiple children were bound to bindSheet with the same state, so multiple sheets were opened and then dismissed in sequence, producing duplicate exit animations.
Solution
Bind bindSheet only on the intended child (the “Share to friends” item). For all other items, pass undefined as the second argument so they do not create a sheet.
Code Snippet / Configuration
class MenuObject {
title: string;
constructor(title: string) {
this.title = title;
}
}
@Component
struct MenuComponent {
@Prop value: MenuObject
build() {
Row() {
Text(this.value.title)
.fontSize(16)
.lineHeight(20)
.padding({ left: 16, right: 16, top: 10, bottom: 10 })
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Blank()
}
.width('100%')
}
}
@Entry
@Component
struct Index {
@State isShow: boolean = false
private listObjs: MenuObject[] = [
new MenuObject('Account Management'),
new MenuObject('My Vehicles'),
new MenuObject('Privacy Policy'),
new MenuObject('User Agreement'),
new MenuObject('Share with Friends'),
new MenuObject('About')
]
@Builder
shareTitleBuilder() {
Row() {
Text('Share To')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.padding({ left: 12, right: 12, top: 8, bottom: 8 })
}
.width('100%')
.justifyContent(FlexAlign.Start)
}
@Builder
ShareBuilder() {
Column() {
Button('Friends')
.fontSize(16)
.width('90%')
.height(36)
.margin({ top: 8, bottom: 8 })
.onClick(() => {
this.isShow = false
})
}
.width('100%')
.padding(12)
}
build() {
Column() {
List() {
ForEach(this.listObjs, (item: MenuObject, index: number) => {
ListItem() {
MenuComponent({ value: item })
.onClick(() => {
if (item.title === 'Share with Friends') {
this.isShow = true
} else {
}
})
.bindSheet(
$$this.isShow,
item.title === 'Share with Friends' ? this.ShareBuilder() : undefined,
{
detents: [SheetSize.FIT_CONTENT],
dragBar: false,
showClose: false,
title: this.shareTitleBuilder
}
)
}
.border({ width: 0 })
})
}
.edgeEffect(EdgeEffect.None)
.divider({
strokeWidth: 1,
color: '#1AFFFFFF',
startMargin: 12,
endMargin: 12
})
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}
Key Section:
.bindSheet(
$$this.isShow,
item.title === 'Share with Friends' ? this.ShareBuilder() : undefined,
{
detents: [SheetSize.FIT_CONTENT],
dragBar: false,
showClose: false,
title: this.shareTitleBuilder
}
)
Verification Result
After restricting bindSheet to the “Share to friends” item and passing undefined for others, the sheet opens once and the exit animation runs only once on dismiss.

Top comments (0)