omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    iOS 14 UIMenu for buttons

    Pythonista
    1
    1
    1576
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mikael
      mikael last edited by mikael

      A wrapper around the button UIMenu introduced in iOS 14.

      Installation

      pip install ui3
      

      Usage

      Simplest way to set it up is to use a list defining a title and a handler function for each menu item:

      from ui3.menu import set_menu
      
      def handler(sender, action):
          print(action.title)
      
      set_menu(button, [
          ('First', handler),
          ('Second', handler),
          ('Third', handler),
      ])
      

      First menu with 3 simple items

      Handler gets the button as sender, and the selected action.

      By default, the menu is displayed by a single tap, but you can set it to be activated with a long press, which enables you to use the regular button action for something else:

      set_menu(button, [
          ('First', handler),
          ('Second', handler),
          ('Third', handler),
      ], long_press=True)
      
      button.action = something_else
      

      For slightly more complex menus, you can define Actions:

      from ui3.menu import set_menu, Action
      from ui3.sfsymbol import SymbolImage
      
      placeholder = print
      
      set_menu(button, [
          Action(
              'Verbose menu item gets the space it needs', placeholder,
          ),
          Action(
              'Regular Pythonista icon', placeholder,
              image=ui.Image('iob:close_32'),
          ),
      
          Action(
              'SFSymbol', placeholder,
              image=SymbolImage('photo.on.rectangle'),
          ),
          Action(
              'Destructive', placeholder,
              image=SymbolImage('tornado'),
              attributes=Action.DESTRUCTIVE,
          ),
          Action(
              'Disabled', placeholder,
              attributes=Action.DISABLED,
          ),
      ])
      

      More complex menu

      Actions have the following attributes:

      • title
      • handler - function or method
      • image - if you set the destructive attribute, image is tinted system red automatically
      • attributes - summed combination of Action.HIDDEN, DESTRUCTIVE and DISABLED- by default none of these are active
      • state - either Action.REGULAR (default) or SELECTED
      • discoverability_title

      ... and some convenience boolean properties (read/write):

      • selected
      • hidden
      • disabled
      • destructive

      (Note that there is nothing inherently destructive by an action marked as destructive, it's just visuals.)

      Changing the Action's attributes automatically updates the menu that it is included in. See this example that shows both the selection visual and updating a hidden action:

      expert_action = Action(
          "Special expert action",
          print,
          attributes=Action.HIDDEN,
      )
      
      def toggle_handler(sender, action):
          action.selected = not action.selected
          expert_action.hidden = not action.selected
      
      set_menu(button2, [
          ('Expert mode', toggle_handler),
          expert_action,
      ])
      

      Toggling and hiding

      Still something to be thought about is a way to keep the menu visible as actions are selected/hidden/shown/added/removed.

      1 Reply Last reply Reply Quote 4
      • First post
        Last post
      Powered by NodeBB Forums | Contributors