flet icon indicating copy to clipboard operation
flet copied to clipboard

ListView loses scroll in ResponsiveRow column view.

Open yunguangli opened this issue 1 year ago • 13 comments

Description I am testing ResposiveRow with a container on the left and container of ListView on the right. The listview is scrollable when the screen is wide. Once I shrink the screen the ResponsiveRow changes to column mode. Everything works ok except that the ListView loses its ability to scroll. I have been trying to put the listview in ft.Row, column, another container, and changing the value of "expand". But I still can't scroll the listView in narrow screen.

Code example to reproduce the issue:


def main(page: ft.Page):
    page.title = "scrolling ListView"

    lv = ft.ListView(expand=True, spacing=10, padding=20,)

    count = 1

    for i in range(0, 60):
        lv.controls.append(ft.Text(f"Line {count}"))
        count += 1

    page.add(ft.ResponsiveRow(
        [ft.Container(ft.Text("Title bar"),
                      col={"sm": 12, "md": 9}),

            ft.Container(content=lv,
                         padding=5,
                         bgcolor=ft.colors.GREEN,
                         col={"sm": 12, "md": 3},
                         border_radius=10,
                         expand=True,
                         )
         ],
        expand=True,

    ))

ft.app(target=main)

Describe the results you received:

Describe the results you expected:

Additional information you deem important (e.g. issue happens only occasionally):

Flet version (pip show flet):

0.21.1

Give your requirements.txt file (don't pip freeze, instead give direct packages):

(The requirements)

Operating system: Windows 11 Python 3.12.1

Additional environment details:

yunguangli avatar Mar 08 '24 10:03 yunguangli

page.title = "scrolling ListView" add below this line page.scroll = ft.ScrollMode.HIDDEN

burhansvural avatar Mar 08 '24 14:03 burhansvural

Thanks. This is a workaround. However, this will scroll the whole page. What I want is the just scroll the container that contains the listview.

yunguangli avatar Mar 08 '24 14:03 yunguangli

@yunguangli look at this code https://github.com/flet-dev/flet/discussions/2829

burhansvural avatar Mar 08 '24 19:03 burhansvural

and look at these codes:

import flet as ft
from typing import List

lst_nums:List[int]=[num for num in range(100)]

lstView1=ft.ListView(
        expand=True,
        spacing=2,        
        auto_scroll=True
    )

def __remove_item(e):
    global lst_nums
    print(e.control.data)
    if len(lst_nums)>0:
        lst_nums.pop(e.control.data)        
        listview_builder(lst=lst_nums)
        lstView1.update()
        pass
    pass

#ListView builder example       
def listview_builder(lst:List):
    item_num:int=len(lst)
    for index in range(item_num):
        lstView1.controls.append(ft.ListTile(
            leading=ft.CircleAvatar(
                bgcolor="0xff764abc",
                content= ft.Text(str(index))                   
            ),
            title=ft.Text(f"Item {lst[index]}",overflow=ft.TextOverflow.ELLIPSIS),
            subtitle=ft.Text(f"Item {index} description",overflow=ft.TextOverflow.ELLIPSIS),
            trailing=ft.Row(
                spacing=0,
                width=70,
                alignment=ft.MainAxisAlignment.END,
                controls=[
                    ft.Container(
                        content=ft.Icon(
                            ft.icons.EDIT,
                            color=ft.colors.PURPLE_500
                            ),
                        data=index,
                        on_click=lambda _:{}
                        ),
                    ft.Container(
                        content=ft.Icon(
                            ft.icons.DELETE,
                            color=ft.colors.PURPLE_500,                                
                            ),
                        data=index,
                        on_click=__remove_item
                        ),                            
                    ]
                ),
        ))

listview_builder(lst=lst_nums)

def main(page):    
    page.add(lstView1)    

if __name__=="__main__":
    ft.app(target=main)

burhansvural avatar Mar 08 '24 19:03 burhansvural

Thanks. What I meant is NOT that ListView is not scrollable. What I meant is that once I put the ListView in a ResponsiveRow and shrink the ResponsiveRow into a "column" , the listview loses its scrolling. You can try replace "page.add(lstView1)" with this code and try to shrink the width of the window until the listView moves to the bottom and you will see what I mean : you can't scroll the listview anymore. """

page.add(ft.ResponsiveRow(
    [ft.Container(ft.Text("Title bar"),
                  col={"sm": 12, "md": 9}),

        ft.Container(content=lstView1,
                     padding=5,
                     bgcolor=ft.colors.GREEN,
                     col={"sm": 12, "md": 3},
                     border_radius=10,
                     expand=True,
                     )
     ],
    expand=True,

)) 

"""

yunguangli avatar Mar 09 '24 00:03 yunguangli

@yunguangli yes, you are right about this. ListView should never be placed in a ResponsiveRow, because the listview itself is responsive. Never place the listview inside a container and always add a ListTile as controls to the listview.

burhansvural avatar Mar 09 '24 08:03 burhansvural

I tried to use other equivalent control . I replaced listview inside the ResponsiveRow with a scrollable column . Result is the same. In landscape mode, the column is scrollable whereas it loses scroll in the portrait mode.

""" ft.Column([], expand=True, scroll=ft.ScrollMode.AUTO) """

yunguangli avatar Mar 09 '24 08:03 yunguangli

@yunguangli

Actually, to solve this problem, you can assign a height value to the ListView.

import flet as ft


def main(page:ft.Page):
    page.padding=ft.padding.all(10)

    lv = ft.ListView(
    spacing=10,
    expand=True,
    height=page.window_height-60 if page.window_height!=None else 300
    )

    count = 1

    for i in range(0, 60):
        lv.controls.append(ft.Text(f"Line {count}"))
        count += 1

    
    def page_resize(e):
        pw.value = f"{page.width} px"
        pw.update()
        lv.height=page.window_height-60 if page.window_height!=None else 300
        lv.update()

    page.on_resize = page_resize

    pw = ft.Text(bottom=50, right=50, style=ft.TextThemeStyle.DISPLAY_SMALL)
    page.overlay.append(pw)

    page.add(
        ft.ResponsiveRow(
            run_spacing={"xs": 10},            
            controls=[
                
                ft.Container(
                    col={"sm": 6, "md": 4, "xl": 2},
                    content=ft.Text("Title bar"),
                    padding=5,
                    bgcolor=ft.colors.YELLOW,                                        
                ),
                ft.Container(
                    col={"sm": 6, "md": 4, "xl": 2},
                    content=lv,
                    padding=5,
                    bgcolor=ft.colors.GREEN,
                ),
                    
            ],            
        )
    )
    page_resize(None)
    
ft.app(target=main)

burhansvural avatar Mar 09 '24 09:03 burhansvural

This works perfectly well. Thank you very much! and This should be in the documentation, imo.

yunguangli avatar Mar 09 '24 12:03 yunguangli

Now that the listview is scrollable when I shrink the the ResponsiveRow to the Column mode. However, when the list is long, say more than 200 items, the last few items are always cut off (because the screen is limited) and I can't scroll to the bottom. I have tried many ways, like putting listview other controls, but no success.

yunguangli avatar Mar 12 '24 06:03 yunguangli

Please always the code with the issue.

ndonkoHenri avatar Mar 12 '24 10:03 ndonkoHenri

The code is just above posted by burhansvural (4th comment counting backwards) . If you test on Windows by narrowing the window width until the responsiveRow becomes a column, you will find that the ListView is scrollable but the last few items of the list is always not visible if the list is big. I tested it on Flet App on Android too, same problem. (BTW, the latest updated Flet App for android doesn't work)

yunguangli avatar Mar 12 '24 10:03 yunguangli

@yunguangli

sorucoz

import flet as ft


def main(page:ft.Page):
    page.padding=ft.padding.all(10)

    lv = ft.ListView(
    spacing=10,
    expand=True,
    height=page.window_height-60 if page.window_height!=None else 300,
    padding=10
    )

    count = 1

    for i in range(0, 1000):
        lv.controls.append(ft.Text(f"Line {count}"))
        count += 1

    
    def page_resize(e):
        pw.value = f"{page.width} px"
        pw.update()
        lv.height=page.window_height-60 if page.window_height!=None else 300
        lv.update()

    page.on_resize = page_resize

    pw = ft.Text(bottom=50, right=50, style=ft.TextThemeStyle.DISPLAY_SMALL)
    page.overlay.append(pw)

    page.add(
        ft.ResponsiveRow(
            run_spacing={"xs": 10},            
            controls=[
                
                ft.Container(
                    col={"sm": 6, "md": 4, "xl": 2},
                    content=ft.Text("Title bar"),
                    padding=5,
                    bgcolor=ft.colors.YELLOW,                                        
                ),
                ft.Container(
                    col={"sm": 6, "md": 4, "xl": 2},
                    content=lv,
                    padding=5,
                    bgcolor=ft.colors.GREEN,
                ),
                    
            ],            
        )
    )
    page_resize(None)
    
ft.app(target=main)

burhansvural avatar Mar 13 '24 19:03 burhansvural