Weekend Coder: Touching the screen

By Brian Scheirer on 23 Aug 2014 03:03 pm EDT
-
loading...
-
loading...
-
loading...

All BlackBerry devices running BlackBerry 10 have touchscreens and when a user touches things in an app they expect it do something. That means a developer has to listen for these touch events and react. Seems like a no brainer, huh? Well as a developer you need to know what code takes user screen interaction and turns it into an enjoyable and expected behavior. Obviously there is no way for me to explain every possible scenario, there are definitely major ones every developer needs to know about to successfully code a Cascades app.

Let’s start with the most basic, a Button. Button is one of the stock Cascades components. I’ve used it in many of my previous tutorials but never really focused on what makes it so it actually does something. Consider the following code:

        Button {
            text: "Next Page"
        }

This code will result in a Button labeled “Next Page” to be rendered on the screen. If a user presses this Button it will have nice animation of it appearing to be depressed and when the user lifts their finger it will return to its original state. These effects are attributed to the Cascades framework having built-in fanciness and don’t require a developer to code much. However, other than that nothing will happen. The same can be said for many other stock components in Cascades… ToggleButton (flips a switch), Slider (drag an indicator across a range), CheckBox (toggle between checked and uncheck icon), etc. Simply declaring these components will render them on the screen and allow for interaction but not actually “do” anything.

Back to our Button code, Cascades fires specific signal(s) when a user presses a particular component. So when a Button is pressed Cascades fires a clicked() signal and in QML to make that signal do something you'll code something like:

        Button {
            text: "Next Page"
            onClicked: {
                //Add JavaScript or call C++ function
            }
        }

At this point I hope I haven’t lost anyone either from complete boredom of my obvious explanation of how a simple Button works or that you are overwhelmed by five lines of code. The idea of explaining this is while a Button component has a signal called onClicked, another stock component such as a Slider has a few signals such as onValueChanged and onImmediateValueChanged. And a CheckBox’s main signal that is fired when a user touches it is onCheckedChanged. I could go on and on for all the stock components but I think you get the idea. So be sure to learn all the signals for each stock component.

Now what about custom components or components that don’t have something like onClicked such as a Container or ImageView? Surely, there are instances where you’ll want the user to be able to touch these and have your app react. These would be possible use cases for the Gesture Handler. The Gesture Handler can be added to any component and at the time of this writing can listen for four types of “user touching”: tap, double tap, pinch, and long press.

Let’s take a look at code snippet using the Gesture Handler:

        Container {
            minHeight: 100
            minWidth: 200
            background: Color.Blue
            gestureHandlers: TapHandler {
                onTapped: {
                    //Add JavaScript or call C++ function
                }
            }
        }

This code will render a blue rectangle on the screen with dimensions of 200 pixels wide and 100 pixels tall. And with the TapHandler applied to it, the onTapped signal will result in it behaving very much like a Button with an onClicked signal.

Also consider in Button code, the onClicked signal will only fire if the Button is set to enabled: true (it is true by default). But say in the scenario where your Button is disabled but you wanted to provide feedback to your user if they press the disabled Button. You could apply a TapHandler to your Button and in the onTapped signal you could have a Dialog or Toast letting your user know that Button is not active. That code would look something like this:

        Button {
            id: button1
            text: "Next Page"
            onClicked: {
                //Add JavaScript or call C++ function
            }
            gestureHandlers: TapHandler {
                onTapped: {
                    if(button1.enabled != true){
                        //disabled button action
                    }
                }
            }
        }

Another and even more versatile touch interaction is that every Cascades control inherits the touch() signal. In QML you can simply call the onTouched signal and it listens for various events such as event.isDown, event.isUp, and event.isMove. Using a combination of these events within an onTouched allows your app to respond to all sorts of user screen touches such as the swiping mechanism I illustrated a few months back in my “Custom Cascades” tutorial/example app. A simple example of the onTouch signal can be illustrated by the following code:

        Container {
            id: cont1
            minHeight: 200
            minWidth: 200
            background: Color.Blue
            onTouch: {
                if (event.isDown()) {
                    cont1.background = Color.Magenta
                } else if (event.isUp()) {
                    cont1.background = Color.Cyan
                }
            }
        }

This code will result in a blue rectangle rendering on the screen on initial load. Then when the user presses on that container the rectangle will be colored magenta. It will stay magenta while their finger is pressed to the screen and when they lift their finger it will change to cyan. While this is a trivial example you can see this is a different type of user interaction than say pushing a Button and something happens because in this case something happens when the user has the "button" pushed down and something else completely different happens as soon as the user lifts their finger.

The simple action of a user touching the screen is a bit more complicated than you may have previously thought, huh? And I hear things will only get more complicated with the Classic with focus areas and what not but that is a story for another day. With that said, that's it for today. As usual feel free to sound off in the comments with questions and/or remarks.

Reader comments

Weekend Coder: Touching the screen

36 Comments

Is there an easy to understand "how to code in cascades" book that explains very good how to build native apps?

With many (code-) examples?

Something like bb10 apps in 10 minutes for complete idiots?

Dreaming about the new Passport

The most trickier part is when you need to "lock" the onTouch event or else you get 10x what you wanted...

Posted via CB10

Ya when using onTouch you got to realize the signal keeps firing. Using console.log() while developing will help you debug how many times that signal is firing by seeing it in your console while testing.

Posted via CB10

The solution is to inspect the state of the event in the event handler, and act differently depending on whether its down/up/move/cancel/etc. Some of this is shown in the above example snippet.

Glad you like it. Lots of the design/function I have in that app I have shared as coding samples here on CB. Then all that's left is theming and filling with content and it that app's case zoo webcams and animal images/icons.

Posted via CB10

A few questions:

1. How do you make a button press result in a copy from a TextArea?
2. How do you make a button press result in a copy of specific text to the clipboard?
2. How do you make a button press append to what is already present in a TextArea? There doesn't appear to be an appendText function.

Posted via CB10

1)
TextArea {
id: myTextArea1
text: "Text in myTextAre1"
}
TextArea {
id: myTextArea2
}
Button {
onClicked: myTextArea2.text = myTextArea1.text
}

2)
This would need QML and C++ code and would be too long to post here, please refer to those 2 links :
http://developer.blackberry.com/native/reference/cascades/bb__system__cl...

http://supportforums.blackberry.com/t5/Native-Development/How-to-access-...

3)
TextArea {
id: myTextArea1
text: "My text "
}
TextArea {
id: myTextArea2
text: "is appended"
}
Button {
onClicked: myTextArea1.text = myTextArea1.text + myTextArea2.text
}

Thanks Rodger! Some clarification...

1. I want to create a 'Copy All' button that when pressed, copies whatever is in a specific TextArea, so it can be pasted elsewhere.

3. So...I already know what I want to append to what is in the TextArea. I want to append specific HTML characters to what is in the TextArea. This doesn't work:

onClicked: {
TextArea1.Text = TextArea1.Text + "😄"

Posted via CB10

Same here, and I will even go so far as to say that with every article read I am that much more tempted to code something.

Posted via CB10

Is there any way to 'follow' a particular post such as weekend coders? then it would be automatically updated to my account?

Posted via CB10

I for one would like to hear from a dev that codes in not only Cascades, but the competitive platform too. I am just curious as to their opinion of what is the best, most feature rich, and efficient system.

By money is on Cascades, but I am guessing.

Wished that the cascade api would extend to a richer multitouch api instead of letting us relying upon the lower level c api. At some point i was using the pinch gesture to emulate dual touch (with extrapolating the two touches coord from the middle point), but it seems that the pinch gesture doesn't trigger anymore when there is 2 distant touches. it was also uneasy coloring the text in the text area with using html span styles. Was using it for a custom keyboard dedicated to a Lua editor, hence the colored syntax (unreleased thus).
Could we encourage BlackBerry open sourcing cascades to have easier ways to extend it, including access to the redraw thread? i hardly see the point of making this a closed api.
Spoludo.com