Forum Archive

Tableview.content_size is reseting itself

Harvs

In this code

def add_idea(sender):
global r

v['tableview2'].data_source.items.append(sender.text)
sender.center=(164,22+((r+1)*v['tableview2'].row_height))
sender.text=''
r= v['tableview2'].data_source.tableview_number_of_rows('tableview2',0)

print "before: " + str(v['tableview2'].content_size)
v['tableview2'].content_size=(0,(r+1)*44) #should allow scrolling
print 'after: ' + str(v['tableview2'].content_size)

On repeated calling of the function I get this output:

after: (0.0, 308.0)
before: (528.0, 308.0)
after: (0.0, 352.0)
before: (528.0, 352.0)
after: (0.0, 396.0)
before: (528.0, 396.0)
after: (0.0, 440.0)

For some context add_sender is an action assigned to a textfield that adds the text onto a table view list, moves the box down one to the new empty cell, however once the list of cells is as long as the scroll view the textfield moves out of the content size and cannot be scrolled to. However when I try and manually set the content size in order to allow scrolling it resets itself?

JonB

Generally the sender argument of delegate methods should be the View object, not a string. Not sure if that is causing your problems, some methods don't use sender...

If you are trying to scroll programatically, you want to use conset_offset, not content_size. I would have thought content_size would be set automatically by a tableview, though I don't know that for sure... I believe there is a ListDataSource method that updates the table, which would allow scrolling.

in your example, It would appear that the only thing being reset is the width, since the content_size cannot be smaller than the contents a view contains (or perhaps the View itself, I forget). The height seems to be updating as you would have expected.

JonB

Indeed, content size is updated automatically by ListDataSource. This shows how to update content offset to move last row into view.


import ui
t=ui.TableView()
items=[chr(x) for x in range(35,55)]
d=ui.ListDataSource(items=items)
t.delegate=d
t.data_source=d

def add_item(sender):
    d.items.append(chr(random.randint(36,128)))
    if t.height-t.content_size[1] < 0:
        #offset a little more than needed, so it is obvious we are at end.  omit +40 to place last row at bottom of view
       t.content_offset=(0,t.content_size[1]-t.height+40)
b=ui.ButtonItem('add',action=add_item)
t.right_button_items=[b]
t.present()
JonB

Sorry, misread what you were tying to do. The key is that you can't really set content_size on your own. Instead, define an extra empty row in your list of items, so you get the extra content size. Just throw out the last item for anything you are doing

The other issue is that conten size doesn't always get aggressively reduced when deleting rows, so it is better to use something like (len(d.items)-1)*t.row_height

import ui,console
t=ui.TableView()
items=[' '] #init with empty item
d=ui.ListDataSource(items=items)
t.delegate=d
t.data_source=d

root=ui.View()
root.add_subview(t)
t.flex='wh'
root.present('sheet')
t.height=root.height-100 # to avoid overlap of textfield on ipad. better would be to use custom view with resizing based on keyboard frame
tv=ui.TextField()
tv.width=t.width
tv.height=t.row_height
tv.x=0

tv.border_width=3
tv.border_color='red'
t.add_subview(tv)
def add_item(sender):
    d.items[-1]=sender.text
    d.items.append(' ')#force last row to be empty
    #move textview
    movetv(sender)
    #scroll
    if t.height-t.content_size[1] < 0:
        #offset a little more than needed, so it is obvious we are at end.  omit +40 to place last row at bottom of view
       t.content_offset=(0,t.content_size[1]-t.height+40)
    tv.text=''

def movetv(sender):
    tv.y=(len(d.items)-1)*t.row_height


d.edit_action=movetv #called when items rearranged
tv.action=add_item # called when tv changed

movetv(tv)