Forum Archive

TableView style header and footer

jgoalby

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

cvp

@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)

cvp

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
jgoalby

Thank you for the responses. I’ll check them out tonight.

jgoalby

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.

cvp

@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 objectivec

Edit: the labels are created after the controller view but before it is presented

cvp

@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

cvp

@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)