Outro controle de Layout
Controle Dismissible
Dismissible é um controle que pode ser arrastado em uma direção especificada. Quando arrastado ele gera eventos que podem ser capturados para efetuar ações sobre o aplicativo. O conteúdo desenhado dentro do controle permanece visível e acompanha o arrasto do controle que o contém. O controle é dispensado (eliminado) do aplicativo quando atinge um deslocamento mínimo determinado em código.
Nota: chamaremos de dispensa a ação de dismiss do controle. Antes da dispensa o controle encolhe em tamanho, gerando os eventos descritos abaixo.
Um exemplo bem reduzido de uso do dismiss é mostrado abaixo.
import flet as ft import copy def main(page): dm1=ft.Dismissible(content=ft.Text("Primeira Linha", size=20, bgcolor=ft.colors.AMBER_100)) (dm2 := copy.deepcopy(dm1)).content.value="Segunda Linha" (dm3 := copy.deepcopy(dm1)).content.value="Terceira Linha" page.add(ft.Column([dm1, dm2, dm3])) ft.app(main)
Esse código gera o seguinte aplicativo, mostrado na figura 1 em três estados:
Nesse exemplo criamos um controle dm1=ft.Dismissible() e o copiamos, usando deepcopy para dois outros controles. O método copy.deepcopy é necessário para que controles internos sejam copiados e a cópia seja feita por valor. Isso significa que dm2 e dm3 são novos objetos e não apenas uma nova referência para dm1. Com isso podemos mudar dm2.content.value="Segunda Linha"
(o valor do conteúdo interno).
Nota: O operador walrus (:=) de atribuição tem o efeito de fazer uma atribuição e já retornar o objeto para operações posteriores. Portanto:
(dm2 := copy.deepcopy(dm1)).content.value="Segunda Linha" # é o mesmo que dm2 = copy.deepcopy(dm1) dm2.content.value="Segunda Linha"
Em um caso mais elaborado podemos inserir linhas formatadas (por exemplo inserindo o texto dentro de containers), capturar outros eventos e definir outras propriedades. A figura 2 mostra um caso um pouco mais elaborado e o exemplo de uso de Dismissible no final desse texto mostra um código mais completo.
Propriedades de Dismissible
Dismissible tem as seguintes propriedades:
Propriedade | Descrição |
---|---|
background | um controle que fica por trás do controle principal que exibe conteúdo. Se secondary_background também for especificado esse controle secundário aparece como fundo quando o conteúdo é arrastado para os lados ou verticalmente. |
content | um controle filho que fica exibido dentro do Dismissible e se move com ele. |
cross_axis_end_offset | especifica um valor para deslocamento vertical quando o controle é movido horizontalmente, fazendo o controle se mover na diagonal, para baixo se o valor for positivo, para cima se negativo. |
direction | direção usada para dispensar o controle. Os valores possível estão no enum DismissDirection:
|
dismiss_thresholds | o valor mínimo de deslocamento considerado para dispensar o controle. A partir desse valor o controle é removido do aplicativo. Por exemplo, se o valor é de 0.4 (o default) a barra tem que ser movida de 40% ou mais de sua extensão para ser dispensada. Seu valor é especificado como um dicionário tendo como chaves um objeto DismissDirection e o valor um valor numérico entre 0.0 e 1.0. O bloco de código mostra isso:
ft.Dismissible( # ... dismiss_thresholds={ ft.DismissDirection.VERTICAL: 0.1, ft.DismissDirection.START_TO_END: 0.7 } ) Esse dicionário define que os valores mínimos (thresholds) são 10% na vertical e 70% na horizontal, se o movimento for do início para o final (para a direita). |
movement_duration | a duração do movimento para que o controle seja dispensado ou retorne para sua posição original. |
resize_duration | a duração do movimento de contração antes que o evento de dispensa seja acionado. |
secondary_background | um controle desenhado por tras do conteúdo principal, que é exposto quando o conteúdo é arrastado para os lados. Só pode ser especificado se o background também for definido. |
Eventos de Dismissible
Evento | Descrição |
---|---|
on_confirm_dismiss | um evento que ocorre antes que o controle seja dispensado, dando a oportunidade de se confirmar ou negar essa operação. O controle não pode ser arrastado novamente até que essa pendência seja resolvida.
Para resolver essa pendência deve ser chamado o método confirm_dismiss(dismiss) passando um booleano: True para confirmar, provocando a dispensa do controle, False para negar, o que faz com que ele volte para sua posição original. Uma possibilidade consiste em apresentar a pergunta em uma caixa como AlertDialog. |
on_dismiss | dispara quando o controle é dispensado. Antes da dispensa o controle é contraído, diminuindo de tamanho. |
on_resize | dispara quando o controle muda de tamanho, o que ocorre, por exemplo, na contração ao ser dispensado. |
on_update | dispara quando o controle é arrastado, independentemente de ser ou não dispensado. |
Método de Dismissible
Método | Descrição |
---|---|
confirm_dismiss(dismiss: bool) | resolve a pendência quando a dispensa é requerida. Esse evento pode ser chamado quando se trata do evento on_confirm_dismiss. |
Exemplo de uso de Dismissible
Um exemplo mais completo de código está listado abaixo. Para manter a simplicidade e não usar caixas de diálogo (ainda não consideradas nessas notas) o evento on_confirm_dismiss=informe_dispensa
apenas aciona a função informe_dispensa
que registra na caixa de informações as ações de remoção dos controles pela direita ou pela esquerda, sem pedir a confirmação.
import flet as ft def main(page): def informe_dispensa(e: ft.DismissibleDismissEvent): if e.direction == ft.DismissDirection.END_TO_START: msg.value += "\nSaída pela direita!" else: msg.value += "\nSaída pela esquerda!" e.control.confirm_dismiss(True) page.update() def dispensar(e): coluna.controls.remove(e.control) page.update() def atualizar(e: ft.DismissibleUpdateEvent): if e.direction == ft.DismissDirection.END_TO_START: icone.name=ft.icons.ARROW_BACK else: icone.name=ft.icons.ARROW_FORWARD texto.value=f"Progresso: {e.progress}" page.update() cor = [ft.colors.AMBER_100,ft.colors.BLUE_GREY_100, ft.colors.BLUE_50] array=[ ft.Dismissible( content=ft.Container( ft.Text(f"Esta é a linha {i+1}", size=15), height=35, width=380, border = ft.border.all(2, ft.colors.BLACK54), bgcolor= cor[i%2], padding = ft.padding.all(6), margin = ft.margin.all(2) ), dismiss_direction=ft.DismissDirection.HORIZONTAL, background=ft.Container(bgcolor=ft.colors.CYAN_100), secondary_background=ft.Container(bgcolor=ft.colors.BROWN_50), dismiss_thresholds={ ft.DismissDirection.END_TO_START: 0.2, ft.DismissDirection.START_TO_END: 0.2 }, on_dismiss=dispensar, on_update=atualizar, on_confirm_dismiss=informe_dispensa ) for i in range(10) ] coluna=ft.Column(array, spacing=1) icone=ft.Icon(name=ft.icons.KEYBOARD, color=ft.colors.BLUE, size=30) texto=ft.Text("Posição dos controles", size=18) linha_info = ft.Row([icone, texto]) msg = ft.Text(f"Eventos capturados (Dispensar):\n" , size=15) ver_acao = ft.Container( msg, height=100, width=380, expand=True, border = ft.border.all(2, ft.colors.BLACK54), bgcolor= cor[2], padding = ft.padding.all(12), margin = ft.margin.all(3) ) page.add(coluna, linha_info, ver_acao) ft.app(main)
A operação array=[(objeto(i)) for i in range(10)]
cria uma lista com 10 objetos objeto(i) passando o valor de i internamente para o objeto em cada loop.
A função informa_dispensa(e)
recebe o evento e que contém uma descrição da direção do evento de arrastar. Ela atualiza a variável msg que é exibida dentro do container ver_acao.
A função dispensar(e)
usa a referência ao controle e.control para removê-lo, usando coluna.controls.remove(e.control
).
A função atualizar(e)
escolhe um ícone de direção e insere texto mostrando a porcentagem de arrasto a cada momento, atualizando a variável texto que está em linha_lnfo.