Wednesday, November 13, 2019

How to create sliding trays

I wrote a broader discussion on Animating PowerApps previously.  That article was a fairly broad discussion per animating in general.


This article is covering a start->finish design on setting up a sliding tray allowing users to show/hide application controls at run-time.

The main thing about this design is that you'll essentially link a bunch of controls to one control's values, then have that control's Y value (or X if you were sliding left/right) tied to a variable.

Linking the Tray Items

The first thing you'll need to do is to create "something" that will essentially be your tray where other objects will "virtually" reside on.  This is just an object that you decide will be the background below all of your other controls, icons, etc.  In my case, I:
  • created a Label (although you could use other objects)
  • changed the Fill value to be a dark grey 
  • changed the name to be trayBackground
Now, I added in my additional controls "on top" of trayBackground.
  • added an image to the upper-left 
  • uploaded an organization Logo
  • linked the image to the Logo
  • added a gear icon to the upper-right
Then I started linking items together with the trayBackground as the primary reference point and the Logo as the other one.  All items should move when the "tray" moves and all icons on the tray should get their reference point from the main logo.


Because this is a tray that will move up/down from the top of the screen, I'm using the trayBackground.Y value as the reference for all other controls, while I will link that same value to a Variable later.
  • changed image/logo Y value to be trayBackground.Y
  • changed the gear icon Y value to be trayBackground.Y 
  • added some padding around the logo by setting the PaddingLeft/Right/Top/Bottom values
    • purely aesthetic 
  • set the gear icon's padding values to reference the logo's same values
If you were doing a lot of icons here at the top, then you could even put these into a Gallery control that could even slide/expand horizontally.  However, this is probably the most common kind of tray with one or two specific controls to allow the user to change the behavior of the app in some way.

Go find your own organization's logo you idiot
At this point, the Logo and the Icon are both linked to trayBackground.  If that object moves, then the two icons move along with it (at least vertically).  

Adding an Open/Close control

Now I needed "something" for users to click to cause the tray to slide in/out.  

I've done some different controls including some that slide in/out and even appear to "roll under" other objects on-screen.  However, in this case, I was going for something simple that would work in all scenarios.  So I dropped an up-arrow icon below trayBackground.  I originally added two icon controls (up/down arrow) but then realized that you can control the Icon value of the control:

I just change a Boolean to change the icon
After just dragging the icon control out to about the height I wanted and the same width as the trayBackground control I:
  • changed the OnVisible for the Screen to set a boolean showing the tray status
    • Set(trayOpen, true)
  • changed the Icon value for the control to change based on the value of trayOpen
    • If(trayOpen, Icon.ChevronUp, Icon.ChevronDown)
  • changed the Y value for the control to be linked to trayBackground
    • trayBackground.Y+trayBackground.Height
This means that now the "Arrow" changes based on the Boolean and the entire control moves up/down with the trayBackground control.

Setting up a Timer

For any animation you're going to have to use a Timer.  I'm sorry.

I added a Timer to my application and set up the following components:
  • changed the OnVisible for the Screen to set a boolean for whether the Timer should start
    • Set(trayTimerStart, false)
  • changed the OnSelect for the trayOpenCloseIcon
    • Set(trayOpen, !trayOpen);Set(trayTimerStart, true)
  • changed the OnVisible for the Screen to initialize a "sliding" value for where the tray is supposed to be
    • Set(traySlider, 0)
  • changed the Timer's Start setting to be trayTimerStart
  • changed the Timer's Duration to 50 (this is in milliseconds)
  • changed the Timer's Repeat value (keeps repeating until our tray is done moving)
    • (!trayOpen And trayOpenCloseIcon.Y<>0) Or (trayOpen And traySlider<>0)
  • changed the Timer's Visible value to False
  • changed the Timer's OnTimerStart logic to:
If(
    !trayOpen,
    Set(
        traySlider,
        If(
            100 + traySlider > 10,
            traySlider - 10,
            100 * -1
        )
    ),
    Set(
        traySlider,
        If(
            traySlider < -10,
            traySlider + 10,
            0
        )
    )
)

Whew!

How this all works is, when the value of trayTimerStart becomes true, then the Timer starts.  It uses the value of trayOpen to see if the tray is supposed to close or open.  The logic moves the value of traySlider up or down which ultimately moves the tray in the appropriate direction.  

Or at least it will, once I made this final change:
  • changed the Y value for trayBackground to be:
    • 0 + traySlider
That now links our original "background" for the tray to our sliding value which is set by the timer, which is started when the user clicks the arrow icon.

You can of course now group all of these controls just for your own sanity so you recognize that they're all tied together.

So organized!
I will note that the values I highlighted in cyan above are actually LookUp() values in my code (vs. hard-coded #'s) that I'm pulling from a set of default variables.  I pull these from an Excel sheet that I give each person who manages the actual application once it is deployed.  That means, they can adjust these values depending upon their needs more easily w/o digging through the code.  I also do a similar LookUp() for the tray Orientation (top, right, bottom, left) as well as showing the icon to open/close and even an autoClose value that (if set) starts the tray Open when the app starts and then closes it after a few seconds.  

Why I do it this way vs. having SharePoint lookups is mainly so that people don't do stupid things w/o forethought.  And that I can easily roll back changes once they (or I) have inevitably done these stupid things.

Final Thoughts

Despite this appearing fairly complex, it is a reasonably straightforward series of steps outside of the complex logic required within the Timer control.  Everything links to the background and then you move the background with the Timer.

I will note that this is actually the far simpler version of the control which I designed.  Because i was doing this as a "standard component" for people to use, I designed it to actually also include logic of where the tray was oriented on the screen.  It also includes a Gallery of icons that appear based upon the value of an imported Collection vs. a single static icon.  Some applications might want the tray on the top, some on the left.  And since I was already doing that, I went ahead and included logic for the bottom and right-hand side as well.

Show off...


Once you've mastered the above example, you'll be able to see how you could fit similar logic to support this within your own application.

No comments:

Post a Comment

Because some d-bag is throwing 'bot posts at my blog I've turned on full Moderation. If your comment doesn't show up immediately then that's why.