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.
UI view and touch [slidemenu]
-
So...I wanted to try make a view that has a 'master' (tableview) and 'detail' view. The trick is to be able to do a finger swipe (left/right) to hide/unhide the master view. This is somewhat just for myself to see if I could do it without trying to conjure up some weird objc. Anyway, I think this may be impossible. The reason is because
self.detail
is required to have touch disabled in order for it to work. But if touch is disabled then you essentially can't do anything except display something. So it's a bit useless....It's so close...
I wanted to post this on the off chance that I'm wrong (quite possible) about how to approach this and handling touch events.
So the question is: is it possible to have touch enabled for the
self.detail
view and be able to swipe and getself.master
to hide/unhide?(Side thought....are multitasking gestures even possible with the UI module?)
# coding: utf-8 import ui class SideMenuSlideView(ui.View): def __init__(self, master_view, detail_view): #need to instantiate with master and detail subviews as args. self.master = ui.View() self.master.frame = (0,0,250,200) self.master.flex = 'H' self.master.background_color = 0.3 self.master.touch_enabled = False master_view.width = self.master.width #otherwise it's at the default 100. self.master.add_subview(master_view) self.detail = ui.View() self.detail.frame = (0,0,200,200) self.detail.flex = 'WH' self.detail.background_color = 0.8 self.detail.touch_enabled = False self.detail.add_subview(detail_view) self.add_subview(self.master) self.add_subview(self.detail) self.background_color = 0.8 self.present() def touch_began(self, touch): self.touch_start = touch.location def touch_moved(self, touch): if touch.location[0] > touch.prev_location[0]: self.x_movement = 'right' elif touch.location[0] < touch.prev_location[0]: self.x_movement = 'left' if touch.location[0] > self.touch_start[0]: diff = int(touch.location[0] - self.touch_start[0]) if diff < self.master.width and self.detail.x != self.master.width: self.detail.x = diff slide_percent = self.detail.x / self.master.width self.master.alpha = slide_percent elif touch.location[0] < self.touch_start[0]: diff = int(self.touch_start[0] - touch.location[0]) if self.detail.x > 0 and diff < self.master.width: self.detail.x = self.master.width - diff slide_percent = self.detail.x / self.master.width self.master.alpha = slide_percent def touch_ended(self, touch): def slide_left(): self.detail.x = 0 self.master.alpha = 0 def slide_right(): self.detail.x = self.master.width self.master.alpha = 1 if self.x_movement == 'right': ui.animate(slide_right, duration=0.4) elif self.x_movement == 'left': ui.animate(slide_left, duration=0.4) master = ui.WebView() master.load_html('master') master.flex = 'WH' master.scales_page_to_fit = False detail = ui.WebView() detail.load_url('http://www.google.com/') detail.flex = 'WH' detail.scales_page_to_fit = False a = SideMenuSlideView(master, detail)
-
part of the problem i think is webviews are very greedy when it comes to touches, and i think you cannot exactly do what you want with webviews, without a little objc.
You might be able to run some javascript which lives inside the webview to capture touches.
For views that you dont need to interact with, consider a shield view that goes on top, but it is almost clear (alpha= small, but non zero).
i.e your view heirarchy would look like
main +-- master_container | +- master_shield | +- master +-- detail_container +- detail_shield +- detail
-
@jonb thanks!
I think ideally I would use this as a tableview for master and then a webview for the detail. It would be nice for something like an RSS feed etc. I had a news reader in mind for this project (something I'm using now but wondered how I could get a swipe in/out menu working). But, I think it's also a bit useful practice to build some nice views where the UI takes advantage of swiping etc. Did you ever make something with swiping?I think of course the best way would be to do some objc. Scary stuff...
I found this article ...is that basically what you mean? -
I will take a look around my archives. I vaguely recall something which captured left swipes inside a tableview, probably using a scrollview to simulate touch gestures.
Also...
I have not tried this for a tableviewcell, but in theory should work:https://github.com/mikaelho/pythonista-gestures
this handles all of the ugly objc for you. This might not be the best way to handle objects that are created/destroyed frequently like tableviewcells, due to the way references are retained, but that is an easy thing to fix... i will play around to see if i can mock something up.
-
@cook I misunderstood what you were doing. I see this is a nice DetailViewController implementation. Very clean.
I have made a very slight modification using @mikael's gestures, and the result is here:
https://gist.github.com/4c76a5ee2953403bcc8e7f61bc8dfa8c
Much cleaner than my original attempts at this, and your version now works with tableviews, webviews, etc. @Phuket2 , this will be interest.
-
@jonb that's awesome. At the moment I don't have the time to look. I'll check it later. But thanks so much for your help and input. As I keep coding UI I realize more and more tricks are available - similar to @phuket2. But, it's also not always so straightforward how to do certain things. I have ideas in my brain and making it work isn't so easy. I was a bit excited just to get this slidemenu working nice but of course hit a wall. @jonb is a wall breaker.
-
@jonb it's also not quite complete yet. need to add a button to access the menu etc. but that's the easy bit.
I also need to integrate the necessary parts so rotation works. I learned that from another project and I don't think it's too hard.I also noticed that vertical swiping can also hide/unhide the menu (if your finger goes slightly right/left while going up/down) - so I will need to add some other conditions.
Also....different outcome for small screen.
I'll share once I've got it better.
-
Consider requiring a minimum distance for both initial motion before moving anything.
Also, with the Gestures add_pan, the touch object gets a
translation
attribute, which you can use instead of location minus prev_location, so would simplify things a little. It also has a velocity which may be useful in some cases. -
@jonb was able to work on it more. Thanks so much again for your help. There's not much else to do. I did try the touch.translation but for some reason it was a little glitchy. I don't have time now to fiddle more (I really need to sleep!!!). So I may leave that for another time.
- I added more effect for the master view as it's being swiped (comes in gradually from a -60 X value)
- added screen size variation
- rotation should be okay (had to add draw/etc functions for different screen size)
- changed some code, tried to condense a bit
Again - I really appreciate your help and comments!
I put it on github. I don't really use github and I don't know how to so much. I know people can request changes etc, but I'm not really sure how to do all that! Here is the link