flet-dev / flet

Flet enables developers to easily build realtime web, mobile and desktop apps in Python. No frontend experience required.
https://flet.dev
Apache License 2.0
10.84k stars 416 forks source link

ResponsiveRow and NavigationRail dosn't has scroll attribute #2590

Open bambier opened 7 months ago

bambier commented 7 months ago

Description I want to use ResponsiveRow (also NavigationRail but not necessary at this moment) to create responsive row according to user windows width/height but it can not scroll when size of view gets smaller than content; Also ResponsiveRow doesn't has scroll attribute so we can not add scroll feature to it.

Code example to reproduce the issue:

import flet as ft

# Codes

class Inventory(ft.Container):

    def __init__(self, page: ft.Page, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.page = page
        self.expand = True
        self.padding = ft.Padding(10, 10, 10, 10)
        self.page.on_resize = self.on_resize

        self.data = {
            "name": None,
            "product": None,
            "price": None,
            "barcode": None,
            "off": None,
            "stock": None,
            "entry_date": None,
            "expiration_date": None,
        }

        self.category_name = ft.TextField(label="عنوان")
        self.category_show = ft.Switch(label="عنوان",)

        self.name = ft.TextField(label="عنوان")
        self.product = ft.Dropdown(label="کالا",)
        self.price = ft.TextField(label="قیمت", suffix_text="تومان")
        self.barcode = ft.TextField(label="بارکد")
        self.off = ft.TextField(label="تخفیف")
        self.stock = ft.TextField(label="موجودی")
        self.entry_date = ft.TextField(label="زمان ورود")
        self.expiration_date = ft.TextField(label="انقضا")

        self.content = ft.ResponsiveRow(
            controls=[
                ft.Column(
                    col={"md": 10, "lg": 4},
                    controls=[
                        ft.Card(
                            ft.Container(
                                ft.Column(
                                    [
                                        ft.Text("دسته‌بندی", size=40,
                                                weight=ft.FontWeight.BOLD,),
                                        self.category_name,
                                        self.category_show,
                                    ],
                                ),
                                padding=ft.Padding(20, 30, 20, 30)
                            ),
                        ),
                    ],
                    scroll=True,
                ),
                ft.Column(
                    col={"md": 10, "lg": 4},
                    controls=[
                        ft.Card(
                            ft.Container(
                                ft.Column(
                                    [
                                        self.name,
                                        self.product,
                                        self.price,
                                        self.barcode,
                                        self.off,
                                        self.stock,
                                        self.entry_date,
                                        self.expiration_date,
                                    ],
                                ),
                                padding=ft.Padding(20, 30, 20, 30)
                            ),
                        ),
                    ],
                    scroll=True,
                ),
                ft.Column(
                    col={"md": 10, "lg": 4},
                    controls=[
                        ft.Card(
                            ft.Container(
                                ft.Column(
                                    [
                                        self.name,
                                        self.product,
                                        self.price,
                                        self.barcode,
                                        self.off,
                                        self.stock,
                                        self.entry_date,
                                        self.expiration_date,
                                    ],
                                ),
                                padding=ft.Padding(20, 30, 20, 30)
                            ),
                        ),
                    ],
                    scroll=True,
                ),
            ],
            alignment=ft.MainAxisAlignment.SPACE_EVENLY,
            vertical_alignment=ft.CrossAxisAlignment.STRETCH,
            spacing=30,
        )

    def change(self, event: ft.ControlEvent):
        pass

    def close_anchor(self, event: ft.ControlEvent):
        text = f"Color {event.control.data}"
        print(f"closing view from {text}")
        self.product.close_view(text)

    def handle_change(self, event: ft.ControlEvent):
        print(f"handle_change e.data: {event.data}")

    def handle_submit(self, event: ft.ControlEvent):
        print(f"handle_submit e.data: {event.data}")

    def handle_tap(self, event: ft.ControlEvent):
        print(f"handle_tap")

Describe the results you received: It doesn't scroll automatically when contents are larger that view/page: image

Describe the results you expected: Enable scrolling by default

Flet version (pip show flet):

Name: flet
Version: 0.19.0
Summary: Flet for Python - easily build interactive multi-platform apps in Python
Home-page: 
Author: Appveyor Systems Inc.
Author-email: hello@flet.dev
License: Apache-2.0
Location: /home/nima/Desktop/python-projects/accounting/env/lib/python3.10/site-packages
Requires: cookiecutter, flet-runtime, packaging, qrcode, watchdog, websocket-client, websockets
Required-by:

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

flet

Operating system:

OS Name: Ubuntu: 22.04.3 OS Type: 64-bit GNOME Version: 42.9 Windowing System: Wayland

Additional environment details: Also you can find it in NavigationRail! When NavigationRailDestination are too many you cant access to bottom contents due to that you cant scroll. I tried to use both of them (NavigationRail and ResponsiveRow) in Row to enable scroll but it collapsed everything in top of page:

ft.Row(
    contents=[
    ResponsiveRow(...)
    ],
    expand=True,
    scroll=True
)

image

taaaf11 commented 7 months ago

Just add page.scroll = ft.ScrollMode.AUTO in main.py file

bambier commented 7 months ago

I did, but it doesn't works.


class Application(ft.UserControl):
    name = "My App"

    def __init__(self, page: ft.Page, *args, **kwargs) -> None:
        super(Application, self).__init__(*args, **kwargs)

        self.page = page
        self.page.scroll = ft.ScrollMode.AUTO

        ...

# Run App
if __name__ == "__main__":
    ft.app(
        target=Application,
        name=Application.name,
        view=ft.AppView.FLET_APP,
        assets_dir=BASE_DIR / "assets",
        use_color_emoji=True
    )

image

bambier commented 7 months ago

Just now I found out If we put everything in Column insted of Row with

horizontal_alignment=ft.CrossAxisAlignment.CENTER
expand=True
scroll=ft.ScrollMode.ADAPTIVE

we can enable scroll but It's weird! When You call something Responsive it should be responsive by it self.

NOTE: We don't need page.scroll = ft.ScrollMode.AUTO and you have not to use alignment=ft.MainAxisAlignment.CENTER otherwise it collapse everything on top of page. It fix problem temporary but now page scrolls more thatn we need. I keep this issue open perhaps you want to add this feature to ResponsiveRow and NavigationRail.

taaaf11 commented 7 months ago

But, doesn't it make sense to add scroll to the page? And for responsive, it is responsive, just the contents get "out of the page". Am I thinking according to you? If not, feel free to ask or tell

Also, for Column, the alignment property is START by default, that is, at the top of the Column

And scrolling is something you add to the page,,

bambier commented 7 months ago

Sometimes you want some part of page to be scrolled and some part not in other hand if you add scroll behavior to whole page, the whole page components beings scrollable. However as I said before it doesn't worked when I set the ‍‍‍‍page.scroll equal to the ft.ScrollMode.AUTO.

taaaf11 commented 7 months ago

I see

By the way, how did you do 😉

ft.app(
        ...
        assets_dir=BASE_DIR / "assets",
        ...

How did it even run? Did you forget to do os.path.join?

bambier commented 7 months ago

If you use pathlib, you can use / for joining pathes same as os.path.join. It's shorter and readable.

I just added necessary lines to code samples that I sent before, which can affect scroll behavior. BASE_DIR has been defined as

from pathlib import Path

BASE_DIR = Path().parrent

# Now you can use '/' operator 
assets_path = BASE_DIR / "assets" 

For more info: The os module represents paths as strings which you can not do much. The pathlib module represents paths as special objects with useful methods and attributes. More information here

taaaf11 commented 7 months ago

I did not know that. Thank you