Skip to content

Dismissible

A control that can be dismissed by dragging in the indicated dismiss_direction. When dragged or flung in the specified dismiss_direction, its content smoothly slides out of view.

After completing the sliding animation, if a resize_duration is provided, this control further animates its height (or width, depending on what is perpendicular to the dismiss_direction), gradually reducing it to zero over the specified resize_duration.

Inherits: LayoutControl, AdaptiveControl

Properties

Events

Methods

Examples#

Live example

Dismissible ListTiles#

import flet as ft


def main(page: ft.Page):
    async def handle_dialog_action_click(e: ft.Event[ft.TextButton]):
        page.pop_dialog()
        await dlg.data.confirm_dismiss(e.control.data)

    dlg = ft.AlertDialog(
        modal=True,
        title=ft.Text("Please confirm"),
        content=ft.Text("Do you really want to delete this item?"),
        actions=[
            ft.TextButton("Yes", data=True, on_click=handle_dialog_action_click),
            ft.TextButton("No", data=False, on_click=handle_dialog_action_click),
        ],
        actions_alignment=ft.MainAxisAlignment.CENTER,
    )

    async def handle_confirm_dismiss(e: ft.DismissibleDismissEvent):
        if e.direction == ft.DismissDirection.END_TO_START:  # right-to-left slide
            # save current dismissible to dialog's data, for confirmation in
            # handle_dialog_action_click
            dlg.data = e.control
            page.show_dialog(dlg)
        else:  # left-to-right slide
            await e.control.confirm_dismiss(True)

    def handle_dismiss(e):
        e.control.parent.controls.remove(e.control)
        page.update()

    def handle_update(e: ft.DismissibleUpdateEvent):
        print(e)

    page.add(
        ft.ListView(
            expand=True,
            controls=[
                ft.Dismissible(
                    content=ft.ListTile(title=ft.Text(f"Item {i}")),
                    dismiss_direction=ft.DismissDirection.HORIZONTAL,
                    background=ft.Container(bgcolor=ft.Colors.GREEN),
                    secondary_background=ft.Container(bgcolor=ft.Colors.RED),
                    on_dismiss=handle_dismiss,
                    on_update=handle_update,
                    on_confirm_dismiss=handle_confirm_dismiss,
                    dismiss_thresholds={
                        ft.DismissDirection.END_TO_START: 0.2,
                        ft.DismissDirection.START_TO_END: 0.2,
                    },
                )
                for i in range(10)
            ],
        )
    )


ft.run(main)

dismissible-list-tiles

Remove Dismissible on_dismiss inside component#

Important

Always specify a key for Dismissible when using inside Flet component.

The issue you may encounter here is specific to the Dismissible control used inside Flet component (declarative UI).

When a user swipes (dismisses) an item, that widget is marked as “dismissed” on the Flutter side and effectively removed from the UI. However, when Flet recalculates the UI diff on the Python side, it may attempt to reuse widgets in the list based on their order rather than their identity.

If no key is provided, Flet’s diffing algorithm can’t tell that a particular Dismissible corresponds to a specific item — so it assumes the items have merely shifted. That leads to update commands like:

“Update text in items 0…N-1, then delete the last item (N).”

On Flutter’s side, though, the already-dismissed Dismissible widget in the middle of the list can’t be updated — it’s gone — causing runtime errors.

Always assign a stable, unique key to each Dismissible, typically based on the item’s identifier or index.

Example:

import flet as ft


@ft.component
def App():
    items, set_items = ft.use_state(list(range(5)))

    return ft.ListView(
        controls=[
            ft.Dismissible(
                key=i,
                content=ft.ListTile(title=ft.Text(f"Item {i}")),
                dismiss_direction=ft.DismissDirection.HORIZONTAL,
                background=ft.Container(bgcolor=ft.Colors.GREEN),
                secondary_background=ft.Container(bgcolor=ft.Colors.RED),
                on_dismiss=lambda e, index=i: set_items(
                    [item for item in items if item != index]
                ),
                dismiss_thresholds={
                    ft.DismissDirection.HORIZONTAL: 0.1,
                    ft.DismissDirection.START_TO_END: 0.1,
                },
            )
            for i in items
        ],
    )


ft.run(lambda page: page.render(App))

Properties#

background class-attribute instance-attribute #

background: Control | None = None

A control that is stacked behind the content.

If secondary_background is also specified, then this control only appears when the content has been dragged down or to the right.

content instance-attribute #

content: Control

The control that is being dismissed.

Must be visible.

Raises:

cross_axis_end_offset class-attribute instance-attribute #

cross_axis_end_offset: Number = 0.0

Specifies the end offset along the main axis once the content has been dismissed.

If set to a non-zero value, then this dismissible moves in cross direction depending on whether it is positive or negative.

dismiss_direction class-attribute instance-attribute #

dismiss_direction: DismissDirection = HORIZONTAL

The direction in which the control can be dismissed.

dismiss_thresholds class-attribute instance-attribute #

dismiss_thresholds: dict[
    DismissDirection, Number | None
] = field(default_factory=dict)

The offset threshold the item has to be dragged in order to be considered as dismissed. This is specified as a dictionary where the key is of type DismissDirection and the value is the threshold (a fractional/decimal value between 0.0 and 1.0, inclusive).

Example
ft.Dismissible(
    # ...
    dismiss_thresholds={
        ft.DismissDirection.VERTICAL: 0.1,
        ft.DismissDirection.START_TO_END: 0.7
    }
)

movement_duration class-attribute instance-attribute #

movement_duration: DurationValue = field(
    default_factory=lambda: Duration(milliseconds=200)
)

The duration for content to dismiss or to come back to original position if not dismissed.

resize_duration class-attribute instance-attribute #

resize_duration: DurationValue = field(
    default_factory=lambda: Duration(milliseconds=300)
)

The amount of time the control will spend contracting before on_dismiss is called.

secondary_background class-attribute instance-attribute #

secondary_background: Control | None = None

A control that is stacked behind the content and is exposed when it has been dragged up or to the left.

Raises:

Events#

on_confirm_dismiss class-attribute instance-attribute #

on_confirm_dismiss: (
    EventHandler[DismissibleDismissEvent] | None
) = None

Gives the app an opportunity to confirm or veto a pending dismissal. This dismissible cannot be dragged again until this pending dismissal is resolved.

To resolve the pending dismissal, call the confirm_dismiss() method passing it a boolean representing the decision. If True, then the control will be dismissed, otherwise it will be moved back to its original location.

on_dismiss class-attribute instance-attribute #

on_dismiss: EventHandler[DismissibleDismissEvent] | None = (
    None
)

Called when this control has been dismissed, after finishing resizing.

on_resize class-attribute instance-attribute #

on_resize: ControlEventHandler[Dismissible] | None = None

Called when this dismissible changes size, for example, when contracting before being dismissed.

on_update class-attribute instance-attribute #

on_update: EventHandler[DismissibleUpdateEvent] | None = (
    None
)

Called when this control has been dragged.

Methods#

confirm_dismiss async #

confirm_dismiss(dismiss: bool)