Controle ReorderableListView

ReorderableListView

Um controle ReorderableListView é um widget container que admite controles filhos reposicionáveis. Ele cria uma lista similar à ListView com filhos que podem ser arrastados para novas posições, mostrando uma animação durante o movimento. Ele pode ser usado para abrigar listas com elementos de prioridade ajustável, como uma lista de tarefas ou de músicas.

Exemplo Básico

O controle ReorderableListView permite a construção de linhas ou colunas que podem ser arrastadas e reposicionadas, mudando de lugar com uma animação suave. No exemplo abaixo, dois desses controles são inseridos em uma página. No primeiro, declarado como uma lista horizontal (horizontal=True) são inseridos 2 elementos do tipo ft.Container. No segundo, uma lista vertical (horizontal=False, que é o default), são inseridos 2 elementos ft.ListTile.

import flet as ft

def main(page: ft.Page):
    page.add(        
        # 2 colunas dispostas horizontalmente
        ft.ReorderableListView(
            expand=True, horizontal=True,
            controls=[
                ft.Container(width=250, content=ft.Text("Festa"), alignment=ft.alignment.center, bgcolor="#228A82"),
                ft.Container(width=250, content=ft.Text("Trabalho"), alignment=ft.alignment.center, bgcolor="#8A4F22"),
            ],
        ),
        # 2 linhas dispostas verticalmente
        ft.ReorderableListView(
            controls=[
                ft.ListTile(title=ft.Text("Comprar cerveja"), bgcolor="#6C8785"),
                ft.ListTile(title=ft.Text("Tomar a cerveja"), bgcolor="#BA733C"),
            ],
        )
    )

ft.app(main)
Figura 1

O resultado desse código está mostrado na figura 1.

Os containers Festa e Trabalho podem ser movidos e realocados horizontalmente. Na parte inferior as linhas Comprar cerveja e Tomar cerveja podem ser arrastados verticalmentes e alterados em sua posição. Em um caso mais completo, os eventos de arrastar podem ser capturados (veja abaixo) para alterar propriedades do aplicativo, alterar um banco de dados ou executar qualquer outra ação desejada.

O arrasto é feito com o mouse nas marcas de abas (traços em azul). Se existirem mais controles que que o espaço disponĩvel para exibí-los, uma barra de rolagem é disponibilizada.

Observação: No atual estado do Flet (em Abril de 2025) a atualização de qualquer controle no aplicativo, como por exemplo, uma linha de texto informando sobre o estado da página, atualiza toda a página, retornando os controles ReorderableListView ao seu estado original.

Propriedades

O controle ReorderableListView possui as seguintes propriedades. Como ele pode conter diversos outros controles filhos a formatação e coleta de eventos dos filhos pode ser feita de forma independante.

Propriedade Descrição
anchor A posição relativa do deslocamento de rolagem zero. O default é 0,0.
auto_scroller_velocity_scalar A velocidade escalar por pixel sobre rolagem. Representa como a velocidade é dimensionada com a distância de rolagem. A velocidade de rolagem automática = (distância da overscroll) * velocidade escalar.
build_controls_on_demand Booleano. Se True controles são criados de forma preguiçosa/sob demanda, ou seja, somente quando se tornarem visíveis. Isso é útil quando de lida com um número grande de controles. O default é True.
cache_extent A janela de visualização (viewport) possui uma área antes e depois da área visível onde armazena em cache itens que serão tornados visíveis quando o usuário rola a página.

Itens nessa área de cache são dispostos antes de se tornarem visíveis na tela. O cache_extent define quantos pixels a área de cache inclui antes da borda inicial e depois da borda final da janela de visualização.

controls Lista de controles que serão inseridos e reordenados.
clipe_behavior O conteúdo será recortado (ou não) de acordo com esta opção. O valor é do tipo ClipBehavior e default é ClipBehavior.HARD_EDGE.
first_item_prototype Booleano. Se True as dimensões (largura e altura) definidas para o primeiro item são usadas como “protótipo” para os demais itens. O default é False.
footer Um controle a ser usado no rodapé. Esse item é não reordenável e será exibido ao final dos controles ordenáveis. O valor é do tipo Control.
header Um controle a ser usado como cabeçalho. Esse item é não reordenável e será exibido antes dos controles ordenáveis. O valor é do tipo Control.
horizontal Booleano, se os controles devem ser dispostos horizontalmente. O default é False.
item_extent Se não nulo, força os filhos a terem a extensão fornecida na direção de rolagem.

É mais eficiente especificar um item_extent do que deixar que os filhos determinem sua própria extensão pois o mecanismo de rolagem tem informação prévia da extensão dos filhos. Isso economiza trabalho, por exemplo, quando a posição de rolagem muda drasticamente.

padding Espaço de afastamento interno dos controles. O valor é do tipo Padding.

Eventos

O controle ReorderableListView responde aos seguintes eventos:

Evento Descrição
on_reorder Dispara quando um controle filho é arrastado para uma nova posicão. O aplicativo tem que ser atualizado para reordenar esses itens.
on_reorder_start Dispara quando o arrasto do controle filho é iniciado.
on_reorder_end Dispara quando termina o arrasto do controle filho.

O argumento de evento é do tipo OnReorderEvent, chamado e nos exemplos dados.

Exemplo de Uso do ReorderableListView

Um exemplo mais completo de uso do ReorderableListView está apresentado abaixo:

import flet as ft

def main(page: ft.Page):
    page.title = "Demonstração de ReorderableListView"
    page.bgcolor=ft.Colors.WHITE
    page.window.width=330
    page.window.height=620

    def move_coluna(e: ft.OnReorderEvent):
        print(f"Coluna movida da posição {e.old_index+1} para {e.new_index+1}.")

    def move_linha(e: ft.OnReorderEvent):
        print(f"Linha movida da posição {e.old_index+1} para {e.new_index+1}.")

    cor=[ft.Colors.GREEN_200, ft.Colors.GREEN_50, ft.Colors.GREEN_500, ft.Colors.GREEN]
    coluna=["A","B","C","D","E"]
    linha=["Comparar café","Tomar café","Comprar cerveja","Tomar cerveja","Dormir"]

    # Colunas dispostas horizontalmente
    lista_horizontal = ft.ReorderableListView(
        expand=True,
        horizontal=True,
        on_reorder=move_coluna,
        controls=[
            ft.Container(
                border=ft.border.all(1, ft.Colors.BLACK),
                content=ft.Text(f"{coluna[i]}", color=ft.Colors.BLACK),
                margin=ft.margin.symmetric(horizontal=1, vertical=5),
                width=60,                
                alignment=ft.alignment.center,
                bgcolor= cor[i%2],
            ) for i in range(5)
        ],
    )
    # linha_header
    linha_header=ft.Container(
        content=ft.Text("Coisas a Fazer", color=ft.Colors.WHITE),
        margin=ft.margin.symmetric(horizontal=0, vertical=5),
        padding=5,
        height=30,
        bgcolor= cor[2],
    )
    # linha_footer
    linha_footer=ft.Container(
        content=ft.Text("Fim da Página", color=ft.Colors.WHITE),
        margin=ft.margin.symmetric(horizontal=0, vertical=5),
        padding=5,
        height=30,
        bgcolor=cor[2],
    )

    # Linhas dispostas verticalmente
    lista_vertical=ft.ReorderableListView(
        expand=True,
        on_reorder=move_linha,
        header=linha_header,
        footer=linha_footer,
        controls=[
            ft.Container(
                border=ft.border.all(1, ft.Colors.BLACK),
                content=ft.Text(f"{linha[i]}", color=ft.Colors.BLACK),
                margin=ft.margin.symmetric(horizontal=1, vertical=1),
                width=330,
                height=40,
                padding=10,
                alignment=ft.alignment.center_left,
                bgcolor= cor[i%2],
            ) for i in range(5)
        ],
    )
    page.add(lista_horizontal, lista_vertical)

ft.app(main)

Após algumas operações de arrasto das linhas e colunas, as seguintes linhas são exibidas no console:

Linha movida da posição 1 para 4.
Linha movida da posição 2 para 3.
Coluna movida da posição 1 para 4.
Coluna movida da posição 2 para 3.

O resultado desse código está mostrado na figura 2 em seu estado inicial e depois dos arrastos descritos acima.

Observe que as propriedades controls de ambos os ReorderableListView, que são listas (lists ordinárias do Python), foram preenchidos com compressão de listas. Esse mecanismo está descrito em Compreensão de listas no Python e resumido abaixo:

$ lista1=[i** for i in range(10)]
$ print(lista1)
↳ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

$ lista2=[i** for i in range(10) if i%2==0]
$ print(lista2)
↳ [0, 4, 16, 36, 64]

Portanto o código preenche a lista ft.ReorderableListView.controls com 5 instâncias de ft.Container, com i=0,...,4. As propriedades internas variam com i em linha[i], definida como uma lista no início do código, e cor[i%2], que pode ser apenas cor[0] ou cor[1], de outra lista já definida.

A propriedade horizontal=True define que os controles são dispostos na horizontal.

 

 

 

 



Leave a Reply

Your email address will not be published. Required fields are marked *