Forum Archive

Removing views with ui.Transforms

Phuket2

Yeah, sorry. I know this is a stupid question. I am having a very difficult time getting my head around it though. I have a very simple slide_in func to slide in a view. The view is created but hidden. That's fine. Then with manual activation it slides in (a button press). So far so good. What I have great difficulty doing is sliding out the view, and then closing it. Below I have put test code that does the simple slide in. I didn't include my various attempts to slide it out and close the view. Embarrassing 😱Seems like it should be so simple if you can get the slide in working. Keeping in mind, I don't want the view to slide out automatically, meaning that will triggered at some other time.
Any help appreciated, hate I can't figure it out myself.

'''
    Pythonista Forum - @Phuket2
'''
import ui

def quick_button(p):
    # p is the parent view
    _inset = 60
    btn = ui.Button(name='btn')
    btn.frame = ui.Rect(0, 0, p.width, p.width ).inset(_inset, _inset)
    btn.corner_radius = btn.width / 2
    btn.center = p.bounds.center()
    btn.title = 'Push Me'
    btn.bg_color = 'cornflowerblue'
    btn.tint_color = 'white'
    btn.font = ('Arial Rounded MT Bold', 48)
    p.add_subview(btn)
    return btn

def slide_in(p, v, duration = .5, reverse = False, delay = 0 ):
    v.x = p.width if not reverse else -p.width

    def animation():
        v.x = 0

    ui.animate(animation, duration = duration ,  delay=delay)   

class MyClassB(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bg_color = 'purple'
        self.hidden = True

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        f = (0, 0, self.width, 44)
        cb = MyClassB(name = 'classb', frame = f)
        self.add_subview(cb)
        qb = quick_button(self)
        qb.action = self.my_action
        self.add_subview(qb)

    def my_action(self, sender):
        v = self['classb']
        v.hidden = False
        slide_in(self, self['classb'], reverse = False)

if __name__ == '__main__':
    w, h = 600, 800
    f = (0, 0, w, h)

    mc = MyClass(frame=f, bg_color='white')
    mc.present('sheet', animated=False)
JonB

@Phuket2 Are you trying to use ui.Transforms? Or regular frame based animation? Your example is adjusting the frame, not using a ui.Transform.

Phuket2

@JonB , ok, now you have me thinking. In this case I am just adjusting the frame. But I thought it was still a transform, just a very basic one. I was thinking that if I scale, rotate, alpha change etc, concat or not that the principle would be the same

Phuket2

Ok, I see now, I have not used Transform here. Sorry, I have done so many tries that my head is spinning.

JonB

Refer back to https://gist.github.com/jsbain/d7dbf8bfa6ace92b38430e6f8b80e995.
If you change the complicated transform to v.transform=ui.Transform.Translation(big number, 0)
then this will maybe do what you want.

Make sure that your slide in function un-hides the view before calling the animation (don't animate the hidden property). If you think of every animation having a setup, animation, and completion it might be helpful.

Phuket2

@JonB , anyway, I am still lost. I am pretty sure in the example I seen what you did, you go in and out by concat the transforms. So basically you were doing it in one operation. At least that's what I think you were doing.

Phuket2

@JonB , ok thanks, I will look now

Phuket2

@JonB , thanks. I am sort of back on track again... I will shut my big mouth for a few days and really try to understand all the permutations. For me it's not easy. For some reason these days when something moves on screen, I get it to mind it's some sort of witchcraft. Below is an almost finished example. It works, but not complete. Learning to use transforms is sort of a starting point. Then you have to incorporate into your ui without making lasagna or spaghetti. In the below, my button does not enable until the animation has completed. But at the end of the slide out animation the button should also exit left of scale to nothing or something.
This is why i added #179 to Github

'''
        Pythonista Forum - @Phuket2
'''
import ui

def quick_button(p, title = 'Push Me'):
    # p is the parent view
    _inset = 60
    btn = ui.Button(name='btn')
    btn.frame = ui.Rect(0, 0, p.width, p.width ).inset(_inset, _inset)
    btn.corner_radius = btn.width / 2
    btn.center = p.bounds.center()
    btn.title = title
    btn.bg_color = 'cornflowerblue'
    btn.tint_color = 'white'
    btn.font = ('Arial Rounded MT Bold', 24)
    p.add_subview(btn)
    return btn

def slide_in(p, v, duration = .5, reverse = False, delay = 0, compl=None):
    v.x = -p.width
    x = p.width
    y = 0   
    def a():
        v.transform=ui.Transform.translation(x, y)
        v.hidden = False

    #def compl():
        #pass

    ui.animate(a, duration = duration ,  delay=delay, completion = compl)

def slide_out(p, v, duration = .5, reverse = False, delay = 0 ):
    v.x = 0
    x = p.width
    y = 0

    def a():
        v.transform=ui.Transform()

    def compl():
        v.hidden = True
        p.remove_subview(v)

    v.transform=ui.Transform.translation(x, y)
    ui.animate(a, duration = duration ,  delay=delay, completion = compl)

class MyClassB(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bg_color = 'purple'
        self.hidden = True      

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        f = (0, 0, self.width, 44)
        cb = MyClassB(name = 'classb', frame = f)
        self.add_subview(cb)
        qb = quick_button(self, title = 'Slide out')
        qb.enabled = False
        qb.action = self.my_action


    def my_action(self, sender):
        # disable our button as the view is removed. this button is 
        # no longer relevant
        self['btn'].enabled = False
        slide_out(self, self['classb'], duration = 2)

    def slide_in_complete(self):
        # activate other parts of our ui once the slide_in is complete
        self['btn'].enabled = True

if __name__ == '__main__':
    w, h = 320, 480
    f = (0, 0, w, h)

    mc = MyClass(frame=f, bg_color='white')
    mc.present('sheet', animated=True)
    slide_in(mc, mc['classb'] , duration = 1, compl = mc.slide_in_complete)
JonB

I am not an expert here, but I think the power of transforms is that you'd leave the frame where it should end up (or even use a pyui, with the as-presented configuration), then use transforms only to move the view. I think that might save one or two lines.