Outros controles de Layout: GridView e ResponsiveRow
Controle GridView
GridView, assim como ListView, é um controle apropriado para apresentar listas longas (milhares de ítens). Esses controles devem ser escolhidos ao invés de Column ou Row para se obter um rolamento suave de conteúdo. O Navegador de Ícones (Icons Brower) do Flet é construído com um GridView.
Um exemplo curto do uso do controle é mostrado abaixo. Nesse código um array (uma lista) de 8 containeres com cores de fundo escolhidas entre os valores da lista, cores. Essa lista é passada em flet.GridView.controls = array
.
import flet as ft cores = {0:"black", 1:"#1D74FF", 2:"#C51709", 3:"#FFE000", 4:"#00CB4F",5:"#A866DC", 6:"#FF6600", 7:"#145375"} def main(page: ft.Page): array = [] for i in range(0, 8): array.append( ft.Container( bgcolor=cores[i], border=ft.border.all(1, "BLACK"), border_radius=ft.border_radius.all(15), ) ) grid_imagens = ft.GridView( controls = array, expand=1, runs_count=15, max_extent=100, child_aspect_ratio=1.0, spacing=2, run_spacing=2, ) page.add(grid_imagens) ft.app(target=main)
A execução desse código resulta na tela mostrada na figura 1.
Propriedades de GridView
Propriedade | Descrição |
---|---|
auto_scroll | booleano, auto_scroll=True se a barra de rolamento se move automaticamente para a posição onde o último filho foi inserido. Essa propriedade deve ser False para que o método scroll_to() funcione. |
child_aspect_ratio | proporção entre dimensões vertical e horizontal (cross-axis e main-axis) de cada filho. |
controls | lista de controles a serem renderizados dentro do GridView. |
horizontal | booleano, horizontal=True para que a grade empilhe itens horizontalmente. |
max_extent | largura ou altura máxima de cada ítem na grade. |
on_scroll_interval | intervalo em milisegundos para o disparo do evento on_scroll. Default é 10. |
padding | espaço interno de separação entre os filhos e a grade.
Veja a propriedade Container.padding para maiores informações. |
reverse | booleano, reverse=True faz com que o rolamento se dê invertido, de baixo para cima. Default é False. |
run_spacing | espaçamento entre cada filho em pixeis, ao longo do eixo vertical. |
runs_count | o número de controles filhos a serem apresentados na vertical. |
spacing | espaçamento entre cada filho em pixeis, ao longo do eixo horizontal. |
Método de GridView
scroll_to(offset, delta, key, duration, curve) | move a barra de rolamento para a posição definida, em termos absoluto, relativo ou salto para uma chave especificada.
Veja o método Column.scroll_to() para maiores informações. |
Evento de GridView
on_scroll | Dispara quando a posição de rolamento é alterada pelo usuário.Veja o evento Column.on_scroll para maiores informações. |
Exemplo de uso de GridView
No exemplo abaixo usamos o controle flet.Image(src, fit, repeat, border_radius)
que ainda não descrevemos nessas notas. Seu objetivo é o de inserir imagens, no caso atual lidas no repositório Image Gallery localizada em picsum.photos.
import flet as ft def main(page: ft.Page): page.title = "GridView Example" page.theme_mode = ft.ThemeMode.DARK page.padding = 10 txt = ft.Text("Controle GridView com Imagens", size = 28) titulo=ft.Container(txt, data=0) def incrementa(e): titulo.data+=12 carregar_imagens() bt_mais=ft.ElevatedButton( "Carregar mais imagens", icon=ft.icons.BEACH_ACCESS, color="WHITE", bgcolor="#6E432B", width=300, height=40, on_click=incrementa ) grid_imagens = ft.GridView( expand=1, runs_count=15, max_extent=150, child_aspect_ratio=1.0, spacing=5, run_spacing=5, ) def carregar_imagens(): grid_imagens.controls=[] for i in range(titulo.data, titulo.data+12): grid_imagens.controls.append( ft.Image( src=f"https://picsum.photos/150/150?{i}", fit=ft.ImageFit.NONE, repeat=ft.ImageRepeat.NO_REPEAT, border_radius=ft.border_radius.all(10), ) ) page.update() carregar_imagens() page.add(ft.Column([ft.Row([titulo, bt_mais]), grid_imagens])) ft.app(target=main)
Nesse código o controle flet.GridView é criado com o array de controles vazio e depois populado pela função carregar_imagens()
que insere 12 imagens na propriedade GridView.controls. A propriedade titulo.data
armazena a posição das imagens baixadas e é incrementada de 12 a cada disparo do botão bt_mais.
Controle ResponsiveRow
ResponsiveRow traz para o Flet o mesmo conceito de layout de grade usado no framework Bootstrap. Com ele se pode alinhar os controles filhos em colunas virtuais que podem ser redimensionadas. Por padrão uma grade possui 12 colunas, número que pode ser modificado na propriedade ResponsiveRow.columns.
Cada coluna inserida em um ResponsiveRow possui a propriedade col especificando quantas colunas cada controle deve preencher, de modo análogo ao uso da propriedade expand. Por exemplo, para criar um layout que contém duas colunas abrangendo 6 colunas virtuais cada usamos:
import flet as ft ft.ResponsiveRow([ ft.Column(col=6, controls=[ft.Text("Coluna 1")]), ft.Column(col=6, controls=[ft.Text("Coluna 2")]) ])
O controle é dito “responsivo” porque pode ajustar o tamanho de seus filhos à geometrias variáveis de telas, que pode ser a página, a janela, etc. No exemplo acima a propriedade col é um número constante, significando que o filho ocupará 6 colunas para qualquer tamanho de tela. Se a propriedade col de um filho não for especificada ele terá o número máximo de colunas.
A propriedade col pode ser configurada para ter um valor diferente para “pontos de interrupção” (breakpoints) específicos, de acordo com o tamanho da tela. Os pontos de interrupção, como intervalos de dimensão, recebem nomes:
Por exemplo, no código abaixo o conteúdo é colapsado em apenas uma coluna em uma tela pequena (como a de um telefone celular) e assume 2 colunas em telas grandes:
import flet as ft ft.ResponsiveRow([ ft.Column(col={"sm": 6}, controls=[ft.Text("Column 1")]), ft.Column(col={"sm": 6}, controls=[ft.Text("Column 2")]) ])
Propriedades de ResponsiveRow
Propriedade | Descrição |
---|---|
alignment | alinhamento horizontal dos controles filhos. Por exemplo, MainAxisAlignment.START (que é o default) posiciona os filhos à esquerda da linha.
Os valores possíveis da propriedade estão no enum MainAxisAlignment com os valores:
|
columns | o número de colunas virtuais a usar no layout dos filhos. Default é columns=12 . |
controls | uma lista de controles a serem exibidos dentro do ResponsiveRow. |
run_spacing | espaçamento entre as linhas quando o conteúdo está quebrado em múltiplas linhas. Default run_spacing=10 . |
spacing | espaçamento entre os controles em uma linha. Default é spacing=10 (pixeis virtuais). Esse espaçamento só é aplicado quando o alinhamento (alignment) é start, end ou center. |
vertical_alignment | como os controles filhos são posicionados verticalmente.
Os valores possíveis da propriedade estão no enum CrossAxisAlignment com os valores:
|
Exemplo de uso de ResponsiveRow
No exemplo abaixo tanto as funções coluna()
como linha()
retornam containeres com um texto. Esses controles preenchem as posições de coluna do ResponsiveRow, a primeira delas especificando os pontos de quebra em
col={"sm": 6, "md": 4, "xl": 2}
, a segunda em col={"md": 4}
. Observe que Container não tem a propriedade col, exceto quando dentro de uma “linha responsiva”.
import flet as ft def main(page: ft.Page): def coluna(texto, cor): # retorna um Container com um texto return ft.Container( ft.Text(texto), padding=15, bgcolor=cor, col={"sm": 6, "md": 4, "xl": 2} ) def linha(texto, cor): # retorna um Container com um texto return ft.Container( ft.Text(texto, size=18), width=200, height=60, padding=15, border_radius=10, bgcolor=cor, col={"md": 4} ) def page_resize(e): info.value = f"{page.width} px" info.update() page.on_resize = page_resize info = ft.Text(size=28) page.overlay.append( ft.Container( info, width=200, height=70, padding=10, border_radius=15, bottom=50, right=50, bgcolor="#acdeff", ) ) page.add( ft.ResponsiveRow( [ coluna("Coluna 1", ft.colors.YELLOW), coluna("Coluna 2", ft.colors.GREEN), coluna("Coluna 3", ft.colors.BLUE), coluna("Coluna 4", ft.colors.RED), ], ), ft.ResponsiveRow( [ linha("texto 1", ft.colors.BLUE_50), linha("texto 2", ft.colors.RED_50), linha("texto 3", ft.colors.GREEN_50), ], run_spacing={"xs": 10}, ), ) page_resize(None) ft.app(target=main)
A propriedade de largura da página page.width é exibida dentro de um Container inserido na camada page.overlay para flutuar em cima dos controles da página. Esse controle está definido em espaçamento fixo bottom=50
e right=50
, podendo se sobrepor aos controles da camada abaixo. A atualização é disparada no evento page.on_resize.
Observe que a atualização realizada no redimensionamento altera info.value
e a renderização é exposta na página com info.update()
. O mesmo efeito seria obtido com page.update()
pois esse método cuida de atualizar apenas as partes modificadas da página.
O resultado da execução do código aparece nas figuras 3 e 4.