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.
TableView style header and footer
-
I have a settings dialog I am making using formdialog. I would like to style (font and text color) the header (and footer) for sections in the tableview. I believe I need to handle something like tableView_viewForHeaderInSection_.
I don’t see that method in the classes provided in pythonista. It seems I need to make my own tableview using the objc facility and handle it there.
I wonder if there’s an easier way either built in that I am missing or by bolting on a handler to the existing class.
Thanks in advance
-
@jgoalby Really not perfect but if you want to try it
import ui import dialogs def myform_dialog(title='', fields=None,sections=None, done_button_title='ok'): global c if not sections: sections = [('',fields)] headers_footers = [] i_s = 0 for section in sections: if section[0] != '': headers_footers.append((section[0],section[2])) # comment next line if you want to see where the standard text falls sections[i_s] = (' ',section[1],' ') i_s = i_s + 1 c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title) w,h = 500,600 c.container_view.frame = (0, 0, w, h) # next dimensions are ok for my ipad mini 4 dx = 15 h_header = 36 h_footer = 30 d_footer_header = 12 y = 20 i_s = 0 for headert,footert in headers_footers: if headert != '': header = ui.Label() header.text = headert header.frame = (dx,y,w-dx,h_header) header.font = ('<System-Bold>',24) header.text_color = 'blue' # uncomment next line of you want to see room of label #header.border_width = 1 # only for tests c.container_view.add_subview(header) y = y + h_header for cell in c.cells[i_s]: y = y + cell.height if footert != '': footer = ui.Label() footer.text = footert footer.frame = (dx,y,w-dx,h_footer) footer.font = ('<System-Bold>',16) footer.text_color = 'red' # uncomment next line of you want to see room of label #footer.border_width = 1 # only for tests c.container_view.add_subview(footer) y = y + h_footer + d_footer_header i_s = i_s + 1 c.container_view.present('sheet') c.container_view.wait_modal() # Get rid of the view to avoid a retain cycle: c.container_view = None if c.was_canceled: return None return c.values sections = [] fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header1',fields,'footer1') sections.append(section) fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header2',fields,'footer2') sections.append(section) fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header3',fields,'footer3') sections.append(section) f = myform_dialog(title='dialog title', done_button_title='ok', sections=sections) #f = myform_dialog(title='dialog title', done_button_title='ok', fields=fields)
-
More general, with objectivec instance of ui.TableView
tblo = ObjCInstance(c.view) #print(dir(tblo)) dx = 15 y = 0 i_s = 0 for headert,footert in headers_footers: h_header = tblo._heightForHeaderInSection_(i_s) h_footer = tblo._heightForFooterInSection_(i_s) if headert != '': header = ui.Label() header.text = headert header.frame = (dx,y,w-dx,h_header) header.font = ('<System-Bold>',24) header.text_color = 'blue' # uncomment next line of you want to see room of label #header.border_width = 1 # only for tests c.container_view.add_subview(header) y = y + h_header for cell in c.cells[i_s]: y = y + cell.height if footert != '': footer = ui.Label() footer.text = footert footer.frame = (dx,y,w-dx,h_footer) footer.font = ('<System-Bold>',16) footer.text_color = 'red' # uncomment next line of you want to see room of label #footer.border_width = 1 # only for tests c.container_view.add_subview(footer) y = y + h_footer i_s = i_s + 1
-
Thank you for the responses. I’ll check them out tonight.
-
I’m still trying to wrap my head around this!
it seems like the header and footer labels can be added to the table view after it was created by the controller? And it looks like the controller is fed empty strings. Clever.
Not a deal breaker for me but I tried making font bigger for the header. Say 80. And then set h_header larger as well. I fiddled with other values, but it seemed the existing rows in the table view did not move. Is that expected or something I am missing?
Thanks again. This will be way easier than what I thought I was facing.
-
@jgoalby yes, header and footer are set as blanks to have their row, if they are empty, no header and footer row will be created.
The header and footer rows height is fixed, changing the font will not change this height, but perhaps we could change it via objectivecEdit: the labels are created after the controller view but before it is presented
-
@jgoalby if you insert
tblo.sectionHeaderHeight = 100
You will get
But my code has a bug if you scroll the TableView.
The header and footer labels should be sub_view of the header or footer view, not of the entire container view -
@jgoalby solved by sub_viewing c.view instead of c.container_view
import ui import dialogs from objc_util import * def myform_dialog(title='', fields=None,sections=None, done_button_title='ok'): global c if not sections: sections = [('',fields)] headers_footers = [] i_s = 0 for section in sections: if section[0] != '': headers_footers.append((section[0],section[2])) # comment next line if you want to see where the standard text falls sections[i_s] = (' ',section[1],' ') i_s = i_s + 1 c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title) w,h = 500,600 c.container_view.frame = (0, 0, w, h) tblo = ObjCInstance(c.view) #print(dir(tblo)) h_header = 100 h_footer = 40 tblo.sectionHeaderHeight = h_header tblo.sectionFooterHeight = h_footer dx = 15 y = 0 i_s = 0 for headert,footert in headers_footers: if headert != '': header = ui.Label() header.text = headert header.frame = (dx,y,w-dx,h_header) header.font = ('<System-Bold>',80) header.text_color = 'blue' # uncomment next line of you want to see room of label #header.border_width = 1 # only for tests c.view.add_subview(header) y = y + h_header + 1 for cell in c.cells[i_s]: y = y + cell.height if footert != '': footer = ui.Label() footer.text = footert footer.frame = (dx,y,w-dx,h_footer) footer.font = ('<System-Bold>',32) footer.text_color = 'red' # uncomment next line of you want to see room of label #footer.border_width = 1 # only for tests c.view.add_subview(footer) y = y + h_footer i_s = i_s + 1 c.container_view.present('sheet') c.container_view.wait_modal() # Get rid of the view to avoid a retain cycle: c.container_view = None if c.was_canceled: return None return c.values sections = [] fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header1',fields,'footer1') sections.append(section) fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header2',fields,'footer2') sections.append(section) fields = [] field = {'title':'field1','type':'text','value':''} fields.append(field) field = {'title':'field2','type':'text','value':''} fields.append(field) section = ('header3',fields,'footer3') sections.append(section) f = myform_dialog(title='dialog title', done_button_title='ok', sections=sections) #f = myform_dialog(title='dialog title', done_button_title='ok', fields=fields)