omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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.


    Swipe TableViewCell to show multiple actions

    Pythonista
    5
    34
    5190
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • cvp
      cvp @colint last edited by cvp

      @colint strange, I don't have any freeze. I know that sometimes console.alert needs to be decorated by @ui.in_background, but here, I don't have the problem. Anyway, the challenge was to have several buttons when swiping, isn'it?

      1 Reply Last reply Reply Quote 0
      • colint
        colint last edited by colint

        Strange, it must be just a problem on my end then. When I put ui.inbackground it doesn’t freeze, but the alerts show up behind the presented view, so I can only see them once I close the window. Anyway, like you said, as long as both actions show up then this is a good alternative way to do it! The only thing I’m wondering about now is if there is a way to get the same behaviour from the original solution, where a long swipe to the left would perform one of the actions. Thanks again for the help!

        cvp 1 Reply Last reply Reply Quote 0
        • cvp
          cvp @colint last edited by cvp

          @colint said

          long swipe

          In the gestures module, the swipe function has min_distance and max_distance but they do not seem to work or you can't have two different swipes in the same direction.
          Anyway, these parameters seem to belong to a private API, I think, and so it would be not allowed to be used.

          I try to get the width of the swipe gesture and to process differently for a short or a long swipe but, actually, without success.

          Edit : I think that should be possible without using gestures but the standard touch_began/moved/ended methods where you can continuously compare finger movement from its begin to deduce if the swipe is short or long.
          I could try but not this Sunday, normally tomorrow

          colint 1 Reply Last reply Reply Quote 0
          • colint
            colint @cvp last edited by

            I could try but not this Sunday, normally tomorrow

            Of course, no rush! That’s interesting, I didn’t know you could use touch_began, etc. with the ui module. I suppose it would need a little math to calculate which cell the touch was on but that should still be doable.

            cvp 2 Replies Last reply Reply Quote 0
            • cvp
              cvp @colint last edited by cvp

              @colint said

              would need a little math to calculate which cell the touch was

              Not needed, try this draft of solution, not yet finished, very far of the end, only to let you know how it could work. I did not want to send something so early, only to show something you can try.
              Don't describe me a list of bugs, I know 😂

              import console
              import ui
              
              class cell_view(ui.View):
              	def __init__(self,w,h,tableview,row):
              		self.width = w
              		self.height = h
              		self.tv = tableview
              		self.row = row
              		if self.tv.swiped:
              			prev = self.tv.swiped
              			prev['bdel'].x = self.width
              			prev['byou'].x = prev['bdel'].x + prev['bdel'].width
              
              		self.tv.swiped = self
              		#self.border_width = 1
              		#self.border_color = 'red'
              		bdel = ui.Button(name='bdel')
              		bdel.frame = (w-0,0,w/8,self.height)
              		bdel.background_color = 'red'
              		bdel.tint_color = 'white'
              		bdel.title = 'delete'
              		bdel.action = self.but_action
              		self.add_subview(bdel)
              		byou = ui.Button(name='byou')
              		byou.frame = (bdel.x+bdel.width,0,w/8,self.height)
              		byou.background_color = 'green'
              		byou.tint_color = 'white'
              		byou.title = 'your edit'
              		byou.action = self.but_action
              		self.add_subview(byou)
              
              	def touch_began(self, touch):
              		#print('touch_began')
              		self.x0,self.y0 = touch.location
              		
              	def touch_moved(self, touch):	
              		x,y = touch.location
              		if abs(y-self.y0) < 100:
              			# swipe
              			if x < self.x0:
              				# swipe left
              				self['bdel'].x = max(self['bdel'].x + (x-touch.prev_location.x), self.width*3/4)
              				self['byou'].x = self['bdel'].x + self['bdel'].width
              				if self.tv.swiped:
              					prev = self.tv.swiped
              					if prev != self:
              						prev['bdel'].x = self.width
              						prev['byou'].x = prev['bdel'].x + prev['bdel'].width
              						self.tv.swiped = self
              				
              	def touch_ended(self, touch):	
              		pass
              		
              	def but_action(self,sender):
              		tbl = self.tv
              		row = self.row
              		self['bdel'].x = self.width
              		self['byou'].x = self['bdel'].x + self['bdel'].width
              		self.tv.swiped = None
              		if sender.title == 'delete':			
              			b = console.alert('delete row',str(row), 'confirm', 'cancel', hide_cancel_button=True)
              			if b == 1:
              				del tbl.data_source.items[row]
              				tbl.reload()
              		elif sender.title == 'your edit':
              			t = tbl.data_source.items[row]
              			t = console.input_alert('enter text of row', str(row), t, 'ok', hide_cancel_button=True)
              			tbl.data_source.items[row] = t
              		
              class MyTableView(ui.View):
              	
              	def __init__(self,w,h):
              		self.width = w
              		self.height = h
              		
              		tbl = ui.TableView()	
              		tbl.swiped = None
              		tbl.frame = (0,0,w,h)
              		tbl.row_height = 50
              		tbl.data_source = ui.ListDataSource(items=['a','b','c','d','e'])
              		tbl.delegate = self
              		tbl.data_source.tableview_cell_for_row = self.tableview_cell_for_row
              		tbl.data_source.tableview_can_delete = self.tableview_can_delete
              		tbl.background_color = (0,0,0,0)
              		self.add_subview(tbl)		
              		
              	def tableview_cell_for_row(self, tableview, section, row):
              		# Create and return a cell for the given section/row
              		cell = ui.TableViewCell()
              		cell.selectable = False
              		cell.text_label.text = tableview.data_source.items[row]
              		v = cell_view(self.width,tableview.row_height,tableview,row)
              		cell.content_view.add_subview(v)
              		return cell
              
              	def tableview_can_delete(self, tableview, section, row):
              		# Return True if the user should be able to delete the given row.
              		return False 	# to be sure that standard delete button is not displayed
              
              def main():
              			
              	# Hide script
              	w,h = ui.get_screen_size()
              	mi = min(w,h)*0.9
              	my_back = MyTableView(mi,mi)
              	my_back.background_color='white'
              	my_back.name = 'Test for @colint'	
              	
              	my_back.present('sheet',hide_title_bar=False)	
              	my_back.wait_modal()
              		
              # Protect against import	
              if __name__ == '__main__':
              	main()
              
              1 Reply Last reply Reply Quote 0
              • cvp
                cvp @colint last edited by

                @colint ok, I'll stop with this last code, surely not perfect but, I think, sufficient to show you that you can do it like you asked. Even long swipe (where delete button width is more than half screen) is foreseen and simulates the tap of the delete button. Try the code and give me some feed-back.
                I'm sure that you could ameliorate it in a better way than mine,

                import console
                import ui
                
                class cell_view(ui.View):
                	def __init__(self,w,h,tableview,row):
                		self.width = w
                		self.height = h
                		self.tv = tableview
                		self.row = row
                		if self.tv.swiped:
                			prev = self.tv.swiped
                			prev['bdel'].x = self.width
                			prev['byou'].x = prev['bdel'].x + prev['bdel'].width
                
                		self.tv.swiped = self
                		#self.border_width = 1
                		#self.border_color = 'red'
                		bdel = ui.Button(name='bdel')
                		bdel.frame = (w-0,0,w/8,self.height)
                		bdel.background_color = 'red'
                		bdel.tint_color = 'white'
                		bdel.title = 'delete'
                		bdel.action = self.but_action
                		self.add_subview(bdel)
                		byou = ui.Button(name='byou')
                		byou.frame = (bdel.x+bdel.width,0,w/8,self.height)
                		byou.background_color = 'green'
                		byou.tint_color = 'white'
                		byou.title = 'your edit'
                		byou.action = self.but_action
                		self.add_subview(byou)
                
                	def touch_began(self, touch):
                		#print('touch_began')
                		if self.tv.swiped:
                			prev = self.tv.swiped
                			if prev != self:
                				prev['bdel'].x = self.width
                				prev['byou'].x = prev['bdel'].x + prev['bdel'].width
                				self.tv.swiped = None
                
                		self.x0,self.y0 = touch.location
                		
                	def touch_moved(self, touch):	
                		x,y = touch.location
                		if abs(y-self.y0) < 100:
                			# swipe left or right
                			self['bdel'].x = min(max(self['bdel'].x + 2*(x-touch.prev_location.x), 0), self.width)
                			self['bdel'].width = max(self.width/8,self.width*7/8-self['bdel'].x)
                			#self['bdel'].x = min(max(self['bdel'].x + 2*(x-touch.prev_location.x), self.width*3/4), self.width)
                			self['byou'].x = self['bdel'].x + self['bdel'].width
                			self.tv.swiped = self
                				
                	def touch_ended(self, touch):	
                		if self['bdel'].width > self.width/2:
                			# automatic delete
                			self.but_action('simul delete button')
                		
                	def but_action(self,sender):
                		tbl = self.tv
                		row = self.row
                		self['bdel'].x = self.width
                		self['bdel'].width = self.width/8
                		self['byou'].x = self['bdel'].x + self['bdel'].width
                		self.tv.swiped = None
                		if sender.title == 'delete' or isinstance(sender, str):			
                			b = console.alert('delete row',str(row), 'confirm', 'cancel', hide_cancel_button=True)
                			if b == 1:
                				del tbl.data_source.items[row]
                				tbl.reload()
                		elif sender.title == 'your edit':
                			t = tbl.data_source.items[row]
                			t = console.input_alert('enter text of row', str(row), t, 'ok', hide_cancel_button=True)
                			tbl.data_source.items[row] = t
                		
                class MyTableView(ui.View):
                	
                	def __init__(self,w,h):
                		self.width = w
                		self.height = h
                		
                		tbl = ui.TableView()	
                		tbl.swiped = None
                		tbl.frame = (0,0,w,h)
                		tbl.row_height = 50
                		tbl.data_source = ui.ListDataSource(items=['a','b','c','d','e'])
                		tbl.delegate = self
                		tbl.data_source.tableview_cell_for_row = self.tableview_cell_for_row
                		tbl.data_source.tableview_can_delete = self.tableview_can_delete
                		tbl.background_color = (0,0,0,0)
                		self.add_subview(tbl)		
                		
                	def tableview_cell_for_row(self, tableview, section, row):
                		# Create and return a cell for the given section/row
                		cell = ui.TableViewCell()
                		cell.selectable = False
                		cell.text_label.text = tableview.data_source.items[row]
                		v = cell_view(self.width,tableview.row_height,tableview,row)
                		cell.content_view.add_subview(v)
                		return cell
                
                	def tableview_can_delete(self, tableview, section, row):
                		# Return True if the user should be able to delete the given row.
                		return False 	# to be sure that standard delete button is not displayed
                
                def main():
                			
                	# Hide script
                	w,h = ui.get_screen_size()
                	mi = min(w,h)*0.9
                	my_back = MyTableView(mi,mi)
                	my_back.background_color='white'
                	my_back.name = 'Test for @colint'	
                	
                	my_back.present('sheet',hide_title_bar=False)	
                	my_back.wait_modal()
                		
                # Protect against import	
                if __name__ == '__main__':
                	main()
                
                1 Reply Last reply Reply Quote 0
                • colint
                  colint last edited by

                  Looking good! I’m not seeing the “your edit” button sliding out all the way but I’m sure I can figure that out. Thanks so much for your help!

                  cvp 1 Reply Last reply Reply Quote 0
                  • cvp
                    cvp @colint last edited by

                    @colint said

                    I’m not seeing the “your edit” button sliding out all the way

                    Swipe left is not sufficient, obviously when you begin location is too much at left.
                    Could be done automatically by code

                    1 Reply Last reply Reply Quote 0
                    • colint
                      colint last edited by

                      Sounds good! I’ll take a look into it, thanks again!

                      1 Reply Last reply Reply Quote 0
                      • pome-ta
                        pome-ta @cvp last edited by

                        @cvp

                        This script saved me!

                        I was having trouble handling tableView_cellForRowAtIndexPath_ in UITableViewDataSource.

                        I see that the value returned is .ptr.

                        Thanks so much!

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post
                        Powered by NodeBB Forums | Contributors