Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MDTopAppBar - Trailing Items positioning and hover behaviour #1746

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

chillibasket
Copy link

@chillibasket chillibasket commented Oct 26, 2024

Description of the problem

All of these problems only occur when using the "small" type of the TopAppBar:

  1. The hover behaviour of the trailing container items does not work.
    Is there a way to get hover behavior on Top App Bar's action items? #1550

  2. Incorrect positioning of the trailing container items, especially while resizing the window.
    Layout of MDTopAppBar does not take effect (MDTopAppBarTrailingButtonContainer should locate to the far right but not work) #1708
    Positioning of MDTopAppBar elements #2 #1700
    MDFileManager cancel button goes past the right border of window #1678
    Positioning of MDTopAppBar elements #1660

  3. The alignment of the TopAppBar title cannot be changed from "left" to "center" or "right",
    Positioning of MDTopAppBar elements #2 #1700

Here is a video of the first two issues, using the "examples\appbar.py" test program:
https://github.com/user-attachments/assets/1a8da5d3-7e5f-4097-9dc2-4198f86b397e


Describe the cause of the issue

1. Hover Behaviour

The hover behaviour of the trailing container is being blocked by the title_box widget, which in "small" mode is positioned in front of the right-half of the app bar. The hover detection sees that the items are being covered, so it does not activate. Here is an image of the title_box widget highlighted using the Kivy Inspector tool:
image

2. Incorrect Positioning, 3. Title Alignment

The positioning of the trailing items container is controlled by changing the padding of the title text. For example, if the window size in increased, the right padding of the title would also need to be increased. While this implementation might be able to work, it is prone to errors, does not allow the title alignment to be changed, and does not work if there is no title. For example, currently while resizing the window, the padding is not being updated correctly and is set to 0, meaning the trailing items move to the left:
image



Reproducing the problem

This code is taken from "examples\appbar.py", modified to show the "small", "medium" and "large" Top App Bar types:

from kivy.lang import Builder

from kivymd.app import MDApp

from examples.common_app import CommonApp

KV = """
MDScreen:
    md_bg_color: self.theme_cls.secondaryContainerColor

    MDIconButton:
        on_release: app.open_menu(self)
        pos_hint: {"top": .98}
        x: "12dp"
        icon: "menu"

    MDBoxLayout:
        orientation: "vertical"
        adaptive_height: True
        size_hint_x: .8
        spacing: "12dp"
        pos_hint: {"center_x": .5, "center_y": .5}

        MDTopAppBar:
            id: appbar
            type: "small"
    
            MDTopAppBarLeadingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "arrow-left"
    
            MDTopAppBarTitle:
                text: "AppBar small"
    
            MDTopAppBarTrailingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "attachment"
    
                MDActionTopAppBarButton:
                    icon: "calendar"
    
                MDActionTopAppBarButton:
                    icon: "dots-vertical"

        MDTopAppBar:
            id: appbar
            type: "medium"
    
            MDTopAppBarLeadingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "arrow-left"
    
            MDTopAppBarTitle:
                text: "AppBar small"
    
            MDTopAppBarTrailingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "attachment"
    
                MDActionTopAppBarButton:
                    icon: "calendar"
    
                MDActionTopAppBarButton:
                    icon: "dots-vertical"
        
        MDTopAppBar:
            id: appbar
            type: "large"
    
            MDTopAppBarLeadingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "arrow-left"
    
            MDTopAppBarTitle:
                text: "AppBar small"
    
            MDTopAppBarTrailingButtonContainer:
    
                MDActionTopAppBarButton:
                    icon: "attachment"
    
                MDActionTopAppBarButton:
                    icon: "calendar"
    
                MDActionTopAppBarButton:
                    icon: "dots-vertical"
"""


class Example(MDApp, CommonApp):
    def build(self):
        return Builder.load_string(KV)

    def disabled_widgets(self):
        self.root.ids.appbar.disabled = not self.root.ids.appbar.disabled
        self.root.ids.appbar_custom.disabled = self.root.ids.appbar.disabled


Example().run()

"""


class Example(MDApp, CommonApp):
    def build(self):
        return Builder.load_string(KV)

    def disabled_widgets(self):
        self.root.ids.appbar.disabled = not self.root.ids.appbar.disabled
        self.root.ids.appbar_custom.disabled = self.root.ids.appbar.disabled


Example().run()



Description of Changes

1. Hover Behaviour

The solution is to reduce the size_hint of the title_box container to 0 when in "small" mode as it is not being used. The title_box widget is only used in "medium" and "large" modes:

BoxLayout:
    id: title_box
    padding: "16dp", 0, "16dp", 0
    size_hint:
        (0, 0) \
        if self.parent.type == "small" else \
        (1, 1)

2. Incorrect Positioning

My solution is to remove this "padding" implementation entirely, and instead add an extra text_box box layout widget to the root_box container. The TopAppBarTitle gets inserted into this new widget, while the leading and trailing item containers are always inserted to the left and right of this widget, respectively. The text_box uses the default Kivy Widget behaviour to fill the window, meaning the Trailing items container is always automatically pushed to the right of the screen; all without any additional Python code! This implementation works even if any of the TopAppBar "leading", "trailing" and "title" elements are missing. Here is the new text_box widget highlighted using Kivy Inspector:
image

3. Title Alignment

With the new text_box widget, the title area now fills the full width between the leading and trailing containers. This means the "halign" property of MDTopAppBarTitle can be used to change the position of the text, as is standard expected behaviour for Kivy label alignment. Here is an image of the three title alignments:
image

Example code:

MDTopAppBarTitle:
    text: "AppBar small"
    halign: "center"



Code for testing new changes

Same code as above in the "Reproducing the problem" section.

@chillibasket
Copy link
Author

TODO - if this Pull Request is approved, update the Docs contained in "appbar.py" to show use of halign: "center" for center alignment of MDTopAppBarTitle instead of pos_hint: {"center_x": .5}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant