Forum Archive

Possible to change menubar/header color and font for ui.view?

Bjucha

Hello.

Is it possible to change the color for the header/menubar for ui.view

Tried finding some information but have not found any.

For example if I have:

main_view = ui.View(
frame=(0, 0, 400, 400), bg_color='Yellow', name='Test'
)

The header where Test is written will be white and the rest yellow but if would like to change it to yellow is that possible?

omz

You can change the color of the title bar when you present a view. Example:

import ui

main_view = ui.View(
    frame=(0, 0, 400, 400), bg_color='yellow', name='Test'
)

main_view.present('sheet', title_bar_color='yellow')
Bjucha

@omz Great! Thank you very much!

Bjucha

@omz

Hello agin my "Browser" code crashes when trying your tip. It works if I use it in an other program. Is it because of the navigationview or webview that makes it crash?

Here is the code:

import ui
import urllib.parse



def textfield_url(test): 

        web_view = test.superview['webview'] # superview = in front of other
        url = test.text
        if not (url.startswith('http://') or url.startswith('https://')): # needed for urls starting with http or https
            url = 'http://' + url

        web_view.load_url(url)


def searchfield_url(test2):
    web_view = test2.superview['webview']
    url = test2.text
    search_term = urllib.parse.quote(test2.text, '')
    web_view.load_url('https://www.google.com/search?q=' + search_term)


def homeButton (sender): # Working!
    web_view.load_url('http://www.google.se')
    #url = 'www.google.se'

def Back(sender2): # Working!
    web_view.go_back()  


def buttonTapped(sender3): # Working!
    def bHome(sender5):# Working!
        web_view.load_url('http://www.google.se')

    n_view = ui.View()
    n_view.name = 'Option'
    n_view.background_color = .47, .47, .47
    n_view.frame=(0,40,400,360)
    sender3.superview.navigation_view.push_view(n_view)
    b4 = ui.Button(title = 'Home', frame = (360,80,70,70))
    b4.tint_color = 'black'
    b4.action = bHome
    n_view.add_subview(b4)
    b5 = ui.Button(frame = (330,180,100,70))
    b5.title = 'bookmarks'
    b5.tint_color = 'black'
    n_view.add_subview(b5)




main_view = ui.View(
     name='Grizzly Browser'
)
main_view.background_color = 'white'

text_field = ui.TextField(
        frame=(129, 0, 50, 40),
        flex='W',
        keyboard_type=ui.KEYBOARD_URL,
        autocorrection_type=False,
        autocapitalization_type=ui.AUTOCAPITALIZE_NONE,
        action=textfield_url,

        placeholder='URL:'

)

text_field.f = .67, .07, .23    
seach_field = ui.TextField(
            frame=(520, 0, 0, 40),
            flex='w',
            keyboard_type=ui.KEYBOARD_WEB_SEARCH,
            autocorrection_type=False,
            autocapitalization_type=ui.AUTOCAPITALIZE_NONE,
            action=searchfield_url,
            placeholder = 'Search:'
)


B1 = ui.Button(frame = (4,5,30,30))
B1.image = ui.Image.named('iob:home_256')
B1.action = homeButton
B1.tint_color = 'black'


B2 = ui.Button(frame = (50,5,30,30))
B2.image = ui.Image.named('iob:reply_256')
B2.action = Back
B2.tint_color = .21, .13, .15





b3 = ui.Button(frame = (100,10,20,20))
b3.action = buttonTapped
b3.image = ui.Image.named('iob:gear_a_256')
main_view.add_subview(b3)


main_view.add_subview(text_field)
web_view = ui.WebView(name='webview', frame=(0, 40, 400, 360), flex='WH')



main_view.add_subview(web_view)
main_view.add_subview(B1)
main_view.add_subview(B2)
main_view.add_subview(seach_field)


web_view.load_url('http://www.google.se') #StartPage
main_view.present('fullscreen',title_bar_color='silver') # Crashes everytime
nav_view = ui.NavigationView(main_view)
nav_view.present() 
ccc

Three backticks (`) around your code in this forum. You get them from a long press on the ' key.

omz

Three backticks (`) around your code in this forum. You get them from a long press on the ' key.

... Or use the `` button in the post editor. I've already fixed it for you though.

Bjucha

@ccc Sorry thought I put them there...

ccc

You can comment out the third last line or the last line and things should work. I do not think that presenting two Views one after the other works.

omz

@Bjucha Back to your actual question... The fact that this code crashes Pythonista seems like a bug to me (will have to look into this in more detail), but your code is also not quite correct.

You should only present the nav view, not the main view because that one is already part of the nav view, and you cannot present a view that has a parent (I think this is basically what's causing the crash).

Bjucha

@omz & @ccc Thank you so much, Will look into it later really greatful for all help

Bjucha

Hello guys.
Is there a way to have main_view.present('test_1')

And
nav_view = ui.NavigationView(main_view) nav_view.present()
Both at the sametime
Somehow?
As of now it will crash and the only way is to remove one of them.
The reason I would like both of them is that using frame = x,x,x,x for main_view makes it somehow not possible to use the header for text and icons.
Using a pyui file I can use 768x1024 format and have my title and icons on the header

zipit

It is a bit unclear to me what you are trying to do.

  • An ui.NavigationView is just a (weirdly named) StackPanel
  • You cannot present an instance of a view twice. If you do present your main_view you cannot add it to the nav_view and present it again.
  • You can however present as many views as you want alongside (views are always modal though).

edit: You can present an instance of a view multiple times as a popover (popovers behave it a bit weirdly). Also nothing should crash if you try to present a view twice. You should just get an exception informing you that the view is already being presented. So if your code is crashing for you, you should probably provide a more extensive code example.

Your code should look something like this:

import ui

some_view = ui.View()
nav_view = ui.NavigationView(some_view)
nav_view.present('popover')
dgelessus

@zipit Views aren't always modal - if you present a view as "panel", it appears as an extra tab in the console panel. You can do this for as many views as you want, without blocking the rest of Pythonista.

PS: I think Pythonista still has some crashing issues if you present a NavigationView and then close it. As a workaround, you can put the NavigationView inside a normal View and present that.

ccc

This is a great discussion because these choices can be confusing. Perhaps someone could create a repo showing several various possibilities. This could be added to the UI tutorial or could be a standalone repo. https://github.com/Pythonista-Tools/Pythonista-Tools/blob/master/UI.md

Bjucha

@zipit thanks for the answer, I will try using pop-over and see how it looks. I just like how the NavigationView covers the whole ui.view this way

Bjucha

Is there a way to load a pyui file for the main view without using Main_view.present('pyui file) this crash is really bugging me tried different options like "popover" and "panel" for NavigationView but in the end it always crashes

ccc

This should look something like: ui.load_view('My UI').present('sheet')...

You could also leave the ui.load_view() parameter blank and then make sure that my_script.py and my_script.pyui have matching names or could post a minimal example that actually crashes so that we can debug it together.

It is easier to debug Python code than it is to debug English prose.

Bjucha

@ccc thx. Gonna try your example first if it does not work. I will try to post it in a short version

Bjucha

@ccc it's not crashing anymore now thanks to you!
I also found an other issue that I could fix thanks to this
Really greatful for your help

technoway

Is it possible to dynamically change the title bar color?

I have a ui.View derived class, where initially set the title_bar_color when I present the view. Based on user input, I would like to change the color of the title bar. Is this possible?

JonB

Are you presentng full screen, sheet, or panel?

technoway

Bjucha, I am presenting a sheet.

The code is:

if __name__ == "__main__":
    v = FSButtonView()
    v.present('sheet',
              title_bar_color='#334444',
              hide_close_button=True,
              orientation=['portrait'])

The FSButtonView class derives from the ui.View class.

In the code, I add an ImageView instance as a subview of the main view to show an image that covers all the screen except the title bar. I want the title bar so the cell signal strength, the time, etc. are visible at the top of my iPhone screen. I also want the background of the title bar to match the background of the image. The image background is approximately the color '#334444'.

By tapping the screen (using Morse code) I can control various functions, including removing the subview (image) from the view, and later adding it back. When it's removed, the screen becomes black (minimum battery power), and I want the title bar to become black too. When I add the image back, I want the title bar to return to the image background color, not to the view background color).

The problem now is that the title bar is always the image background color. It do not know how to change the title bar to be black, and then how to change it back to the image color if the image (sub-view) is added back to the view.

If I hide the title bar by using a key argument (I think it was "hide_title_bar") in the "present" methods, then the image covers the entire screen, and then the cell signal strength, time, etc.., are not visible. I want those to remain visible.

I'm not sure what would happen if I hid the title bar when the image was removed, and showed the title bar when the image was put back. I also don't know how to hide/show the title bar dynamically, or if that's even possible.

JonB

So, this is not at all robust, and could change in any pythonista version.... but here is a way to get access to the title bar, to change its color, hide it, etc.

   v=ui.View()
   v.present('sheet')
   V=ObjCInstance(v)
   titlebarbkg= V.superview().superview().superview().subviews()[1].subviews()[0]
   #a more robust way might be to keep traversing up until one of subviews is a UINavigationBar, then follow that down to the UINavigationBarBackground
   titlebarbkg.backgroundColor=UIColor.redColor()
   #titlebarbkg.backgroundColor=UIColor.UIColor.colorWithHexString_('ffee22')
   #titlebarbkg.hidden=True
technoway

JonB, thank you very much! That worked. I had tried to write some code that iterated over Obective C UI items, trying to find the item that mattered and changing it's color, but I never got it to work.

Eventually, I'll try to figure out the hierarchy using your code as a guide, and match to the right names so that the code is somewhat more robust to version changes. For now, I added the following method to my ui.View-derived class, that allows me to change the title bar color dynamically.

def change_title_bar_color(self, hex_color):
    """ Change the title bar color to the passed color.
    """
    vv = ObjCInstance(self)
    bar_bckgnd = vv.superview().superview().superview().subviews()[1].subviews()[0]
    bar_bckgnd.backgroundColor = UIColor.colorWithHexString_(hex_color)
donLaden

@JonB I let’s say I have a switch that toggles light/dark modes. When I toggle the switch to dark all my view elements turn black but I don’t know how to change the clock and signal strength to white so they are visible.
I can present a full screen view using title_bar_color=‘black’ to make the clock white when the view is first presented but not while it’s already been presented. Is there anyway to do this?

Thanks