Anatomy of a feline themed social media solution
This might be painstakingly obvious, but let’s go through the parts of the UI.
Green – the title bar. This contains our context sensitive element (the title). Yellow – the changing view content. Blue – a decorative frame drawn on top of the view content. Purple – the navigation bar (also context sensitive).
A word about the frame. We are drawing it here in four separate parts. If you want to implement this kind of “hole-in-the-middle” frame then please resist the temptation of just slapping a BorderImage with a completely transparent middle section on top of the view. I don’t know the guts of raster, but I’d assume it isn’t optimized for noticing that the middle section is completely transparent and it’ll just waste precious CPU time iterating through the pixels that don’t need any drawing. I’m 99,9% sure that a GPU (if you’re using
OpenGL or OpenVG backends) doesn’t check the texture for full transparency. After all what kind of an idiot asks the GPU to draw a completely transparent polygon? The right way to do it (albeit slightly more laborious) is to draw the top, left, right and bottom parts of the frame separately.
There’s two ways to handle switching views. Either you can do it with the states and transitions of QML or you can do it in a more imperative manner. We’re going for the latter. The first one is a completely viable option if your navigation is very simple, but if your app will have a complex navigation graph (possibly infinite), then I think the way I’m about to show you is better.
Our view transitions will be simple slides to left or right. If you need something else it should be fairly easy to implement. Without further ado, may I present you the ViewSwitcher:
Usage: call switchView(, ). That’s about it. The parent element of your view should naturally be Item or derived from Item. Item, Rectangle, Image, BorderImage – anything goes. When defining your views you should keep in mind not to anchor the left or right edge of your view to anything, so just define width instead. This is because the views are animated by changing the x property.
Every view is neatly tucked in a separate qml file. In addition to providing a good structure for your app, it will be needed when we implement on demand loading of views.
If you need your views to be notified when they’ve been activated or deactivated, implement activationComplete() and deactivationComplete() functions in your view. If you want do things before the view transition starts, you could easily improve the ViewSwitcher component by adding (for example activationStarting() and deactivationStarting()) function calls. The ‘if (foo. bar == undefined)’ clauses are there for convenience so that you don’t have to have empty functions in your view elements, in case the view doesn’t need to be notified.
Public service announcement: QML performance
This is already mentioned in the docs, but : always set elements which don’t need to be drawn fully transparent. QGraphicsView (which is the component responsible of orchestrating the drawing of our QML scene), is smart enough to skip completely transparent items. But the items are off the screen, aren’t they clipped anyway? Yes, but even the clipping takes precious CPU cycles and setting the elements transparent skips that part.