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.
Change color/style of ui.TableView section headers?
-
It's not hard to modify the appearance of table cells in a ui.TableView, by changing how the tableview_cell_for_row() method in the delegate for the table creates table cells. But I'm not seeing an easy way to modify the section headers you get when you implement a data source which provides sections as well as rows.
The data source provider has a tableview_title_for_header() method which works fine to provide the text for the header, but I want to modify the background color and font size for the headers as well...is there any easy way to do that?
-
@shinyformica I'm sure you've seen https://forum.omz-software.com/topic/5080/tableview-style-header-and-footer
There is not an easy way to implement with then UI module, unless you treat sections as regular cells, and just format them yourself. I think they won't behave quite the same.
The alternative is to go full objc.. I vaguely recall someone, maybe me, implementing a wrapper for tableview that implements all of the relevant delegate methods. Or maybe I recall planning to do that.
As an alternative, it would be possible to swizzle the pythonista tableview delegate, that includes some extra methods.
-
@shinyformica see https://github.com/jsbain/objc_hacks/blob/master/tableview_rowheight.py
This was more about rowheight, but this would also work for implementing your own custom delegate calls. I think the one you need is
tableView_willDisplayHeaderView_forSection_
Which will pass you the header view, then you can mess with the contentView.background, etc.
I can play around with it this later. Swizzling isn't the ideal solution, but is probably the easiest way without re-implementing all of ui.TableView.
-
Yeah...I saw that post, but as you pointed out I really would prefer not to completely override and reimplement the way the tableview handles sections just to change the font/color under specific circumstances.
I was actually just investigating the idea of swizzling the delegate to just implement one additional method, which appears to do exactly what I want:
willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
But I'm not clear on exactly how best to safely swizzle that delegate in python/objc...so any pointers there would be appreciated.
-
Ha @JonB!
Nice, you posted exactly what I wanted just as I was asking for it.
You rock, sir. -
i update tableview_rowheight in the repo above to include an example changing the headerview background.
in short
@on_main_thread def tableView_willDisplayHeaderView_forSection_(_self,_sel,tv, v,section): tv_o=objc_util.ObjCInstance(_self) pyo=tv_o.pyObject(restype=c_void_p,argtypes=[]) tv_py=ctypes.cast(pyo.value,ctypes.py_object).value if tv_py.delegate and hasattr(tv_py.delegate,'will_display_header'): tv_py.delegate.will_display_header(v,section)
this checks for tv.delegate.will_display_header(v,section), and calls it with the headerview.
Setting up the swizzle needs to only happen once -- could do it in main of an imported module for instance. multiple times wont hurt, in theory.
def setup_tableview_swizzle(override=False): t=ui.TableView() t_o=ObjCInstance(t) encoding=b'v@:@@i' swizzle.swizzle(ObjCClass(t_o._get_objc_classname()), ('tableView:willDisplayHeaderView:forSection:'), tableView_willDisplayHeaderView_forSection_,encoding)
to change the color you would then define said delegate method, for example
def will_display_header(v,section): ObjCInstance(v).contentView().backgroundColor=UIColor.redColor()
-
Just so anyone who needs to know, knows: this worked great.
You don't actually need to provide the encoding if you are swizzling the delegate on a ui.TableView object, since it already has that method in the protocol it implements. Those encoding strings can be frightening things...in this case there is some danger in encoding an NSInteger as 'i' instead of 'q', since 64bit devices will expect 'q' for NSInteger (not really an issue in this case).
It also nice to stick a weakref to the actual pythonista ui.TableView object, or to the data source, into the objc_instance of the ui.TableView, so that when you have your new delegate function called, you can access the python table or data source objects.
This is just more evidence that basically anything is possible in pythonista with objc_util.
-
@shinyformica said:
This is just more evidence that basically anything is possible in pythonista with objc_util.
👍
-
I probably should have pulled out the pyObject and passed that as the tableview object, to be consistent with other delegate methods.