2021-02-02 11:21 AM
Hi,
for my app I would like to implement a feature to swipe to change a screen. That would probably contain a combination of GestureEvent, a handler, callback and a listener.
However, in 3 hours of reading TouchGFX docs, searching through the forum and browsing through TouchGFX framework source code I was not able to come up with anything. I simply did not know where to start.
So I would like to ask you to add a description to documentation how to use handlers, event listeners and other structures that are available in TouchGFX framework. I see that STM invested a lot of time and resources into TouchGFX which is great. Sadly, it has become a very large project and thus very complex and I believe that the relatively poor documentations limits a lot of users. You should also definetely add some more tutorials.
Solved! Go to Solution.
2021-02-06 07:45 AM
Tutorial how to detect swipe to change screen:
Screen1MainCuttingView.cpp
#include <gui/screen1maincutting_screen/Screen1MainCuttingView.hpp>
Screen1MainCuttingView::Screen1MainCuttingView():
swipeCallback(this, &Screen1MainCuttingView::swipeCallbackHandler)
{
swipeDetectContainerMainScreen.setAction(swipeCallback);
}
void Screen1MainCuttingView::setupScreen()
{
Screen1MainCuttingViewBase::setupScreen();
}
void Screen1MainCuttingView::tearDownScreen()
{
Screen1MainCuttingViewBase::tearDownScreen();
}
void Screen1MainCuttingView::swipeCallbackHandler(int16_t velocity){
if(velocity < 0){
application().gotoScreen2CurrLenScreenSlideTransitionEast();
}
}
Screen1MainCuttingView.hpp
#ifndef SCREEN1MAINCUTTINGVIEW_HPP
#define SCREEN1MAINCUTTINGVIEW_HPP
#include <gui_generated/screen1maincutting_screen/Screen1MainCuttingViewBase.hpp>
#include <gui/screen1maincutting_screen/Screen1MainCuttingPresenter.hpp>
class Screen1MainCuttingView : public Screen1MainCuttingViewBase
{
public:
Screen1MainCuttingView();
virtual ~Screen1MainCuttingView() {}
virtual void setupScreen();
virtual void tearDownScreen();
protected:
private:
touchgfx::Callback<Screen1MainCuttingView, int16_t> swipeCallback;
void swipeCallbackHandler(int16_t);
};
#endif // SCREEN1MAINCUTTINGVIEW_HPP
SwipeDetectContainer.cpp
#include <gui/containers/SwipeDetectContainer.hpp>
SwipeDetectContainer::SwipeDetectContainer():
SwipeDetectContainerBase(), action()
{
setTouchable(true);
setVisible(true); //handleGestureEvent is reported by HAL only to drawables that are visible and touchable only
}
void SwipeDetectContainer::initialize()
{
SwipeDetectContainerBase::initialize();
}
void SwipeDetectContainer::handleGestureEvent(const GestureEvent& event){
if(event.getType() == touchgfx::GestureEvent::SWIPE_HORIZONTAL){
if(action -> isValid()){
action->execute(event.getVelocity()); // <-- getVelocity returns int16_t
}
}
}
SwipeDetectCointainer.hpp
#ifndef SWIPEDETECTCONTAINER_HPP
#define SWIPEDETECTCONTAINER_HPP
#include <gui_generated/containers/SwipeDetectContainerBase.hpp>
#include <touchgfx/Callback.hpp>
class SwipeDetectContainer : public SwipeDetectContainerBase
{
public:
SwipeDetectContainer();
virtual ~SwipeDetectContainer() {}
virtual void initialize();
virtual void setAction(GenericCallback<int16_t> &callback){
action = &callback;
}
virtual void handleGestureEvent(const GestureEvent& event);
protected:
GenericCallback<int16_t>* action;
};
#endif // SWIPEDETECTCONTAINER_HPP
These are the Base files generated by TouchGFX and are only needed to know how SwipeContainer object is named and to get function from button handler to initiate Screen change:
/*********************************************************************************/
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
/*********************************************************************************/
#ifndef SCREEN1MAINCUTTINGVIEWBASE_HPP
#define SCREEN1MAINCUTTINGVIEWBASE_HPP
#include <gui/common/FrontendApplication.hpp>
#include <mvp/View.hpp>
#include <gui/screen1maincutting_screen/Screen1MainCuttingPresenter.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Image.hpp>
#include <gui/containers/SwipeDetectContainer.hpp>
#include <touchgfx/widgets/Button.hpp>
class Screen1MainCuttingViewBase : public touchgfx::View<Screen1MainCuttingPresenter>
{
public:
Screen1MainCuttingViewBase();
virtual ~Screen1MainCuttingViewBase() {}
virtual void setupScreen();
protected:
FrontendApplication& application() {
return *static_cast<FrontendApplication*>(touchgfx::Application::getInstance());
}
/*
* Member Declarations
*/
touchgfx::Box __background;
touchgfx::Image BCKG1;
SwipeDetectContainer swipeDetectContainerMainScreen;
touchgfx::Button buttonGoToCurrLen;
private:
/*
* Callback Declarations
*/
touchgfx::Callback<Screen1MainCuttingViewBase, const touchgfx::AbstractButton&> buttonCallback;
/*
* Callback Handler Declarations
*/
void buttonCallbackHandler(const touchgfx::AbstractButton& src);
};
#endif // SCREEN1MAINCUTTINGVIEWBASE_HPP
/*********************************************************************************/
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
/*********************************************************************************/
#include <gui_generated/screen1maincutting_screen/Screen1MainCuttingViewBase.hpp>
#include <touchgfx/Color.hpp>
#include "BitmapDatabase.hpp"
Screen1MainCuttingViewBase::Screen1MainCuttingViewBase() :
buttonCallback(this, &Screen1MainCuttingViewBase::buttonCallbackHandler)
{
__background.setPosition(0, 0, 480, 272);
__background.setColor(touchgfx::Color::getColorFrom24BitRGB(0, 0, 0));
BCKG1.setXY(0, 0);
BCKG1.setBitmap(touchgfx::Bitmap(BITMAP_BACKGROUND_ELECTRONIC_ID));
swipeDetectContainerMainScreen.setXY(0, 0);
buttonGoToCurrLen.setXY(443, 120);
buttonGoToCurrLen.setBitmaps(touchgfx::Bitmap(BITMAP_RIGHT_ARROW_ID), touchgfx::Bitmap(BITMAP_RIGHT_ARROW_PRESSED_ID));
buttonGoToCurrLen.setAction(buttonCallback);
add(__background);
add(BCKG1);
add(swipeDetectContainerMainScreen);
add(buttonGoToCurrLen);
}
void Screen1MainCuttingViewBase::setupScreen()
{
swipeDetectContainerMainScreen.initialize();
}
void Screen1MainCuttingViewBase::buttonCallbackHandler(const touchgfx::AbstractButton& src)
{
if (&src == &buttonGoToCurrLen)
{
//InteractionGoToCurrLen
//When buttonGoToCurrLen clicked change screen to Screen2CurrLen
//Go to Screen2CurrLen with screen transition towards East
application().gotoScreen2CurrLenScreenSlideTransitionEast();
}
}
2021-02-03 01:18 AM
Hi,
We are working on adding more documentation, videos and tutorials. Could you add the first topics that you believe should be addressed in the Idea Zone of the forum ? This will help us keep track of your input.
Concerning what you are trying to achieve, I would recommend having a look at the SwipeContainer widget as an alternative. Instead of going to another screen you will land to another page within the container. You can also dive into its implementation to understand how the swipe is handled in SwipeContainer.hpp and SwipeContainer.cpp .
/Romain
2021-02-03 12:29 PM
Using the SwipeContainer widget and it makes implementing multiple screen changed by swipe really easy to implement.
Keith
2021-02-04 10:12 AM
Hi, SwipeContainer is not an option, because I want to have separate screens to keep the project tidy.
I found a proper way to implement it by creating a custom container and then programming it. Will post a tutorial here for others very soon.
2021-02-05 02:18 AM
Great idea :thumbs_up: How did you program it ? Following the swipe implementation from the Swipe container or in one of the demos (demo 2 for example) ?
/Romain
2021-02-06 07:45 AM
Tutorial how to detect swipe to change screen:
Screen1MainCuttingView.cpp
#include <gui/screen1maincutting_screen/Screen1MainCuttingView.hpp>
Screen1MainCuttingView::Screen1MainCuttingView():
swipeCallback(this, &Screen1MainCuttingView::swipeCallbackHandler)
{
swipeDetectContainerMainScreen.setAction(swipeCallback);
}
void Screen1MainCuttingView::setupScreen()
{
Screen1MainCuttingViewBase::setupScreen();
}
void Screen1MainCuttingView::tearDownScreen()
{
Screen1MainCuttingViewBase::tearDownScreen();
}
void Screen1MainCuttingView::swipeCallbackHandler(int16_t velocity){
if(velocity < 0){
application().gotoScreen2CurrLenScreenSlideTransitionEast();
}
}
Screen1MainCuttingView.hpp
#ifndef SCREEN1MAINCUTTINGVIEW_HPP
#define SCREEN1MAINCUTTINGVIEW_HPP
#include <gui_generated/screen1maincutting_screen/Screen1MainCuttingViewBase.hpp>
#include <gui/screen1maincutting_screen/Screen1MainCuttingPresenter.hpp>
class Screen1MainCuttingView : public Screen1MainCuttingViewBase
{
public:
Screen1MainCuttingView();
virtual ~Screen1MainCuttingView() {}
virtual void setupScreen();
virtual void tearDownScreen();
protected:
private:
touchgfx::Callback<Screen1MainCuttingView, int16_t> swipeCallback;
void swipeCallbackHandler(int16_t);
};
#endif // SCREEN1MAINCUTTINGVIEW_HPP
SwipeDetectContainer.cpp
#include <gui/containers/SwipeDetectContainer.hpp>
SwipeDetectContainer::SwipeDetectContainer():
SwipeDetectContainerBase(), action()
{
setTouchable(true);
setVisible(true); //handleGestureEvent is reported by HAL only to drawables that are visible and touchable only
}
void SwipeDetectContainer::initialize()
{
SwipeDetectContainerBase::initialize();
}
void SwipeDetectContainer::handleGestureEvent(const GestureEvent& event){
if(event.getType() == touchgfx::GestureEvent::SWIPE_HORIZONTAL){
if(action -> isValid()){
action->execute(event.getVelocity()); // <-- getVelocity returns int16_t
}
}
}
SwipeDetectCointainer.hpp
#ifndef SWIPEDETECTCONTAINER_HPP
#define SWIPEDETECTCONTAINER_HPP
#include <gui_generated/containers/SwipeDetectContainerBase.hpp>
#include <touchgfx/Callback.hpp>
class SwipeDetectContainer : public SwipeDetectContainerBase
{
public:
SwipeDetectContainer();
virtual ~SwipeDetectContainer() {}
virtual void initialize();
virtual void setAction(GenericCallback<int16_t> &callback){
action = &callback;
}
virtual void handleGestureEvent(const GestureEvent& event);
protected:
GenericCallback<int16_t>* action;
};
#endif // SWIPEDETECTCONTAINER_HPP
These are the Base files generated by TouchGFX and are only needed to know how SwipeContainer object is named and to get function from button handler to initiate Screen change:
/*********************************************************************************/
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
/*********************************************************************************/
#ifndef SCREEN1MAINCUTTINGVIEWBASE_HPP
#define SCREEN1MAINCUTTINGVIEWBASE_HPP
#include <gui/common/FrontendApplication.hpp>
#include <mvp/View.hpp>
#include <gui/screen1maincutting_screen/Screen1MainCuttingPresenter.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Image.hpp>
#include <gui/containers/SwipeDetectContainer.hpp>
#include <touchgfx/widgets/Button.hpp>
class Screen1MainCuttingViewBase : public touchgfx::View<Screen1MainCuttingPresenter>
{
public:
Screen1MainCuttingViewBase();
virtual ~Screen1MainCuttingViewBase() {}
virtual void setupScreen();
protected:
FrontendApplication& application() {
return *static_cast<FrontendApplication*>(touchgfx::Application::getInstance());
}
/*
* Member Declarations
*/
touchgfx::Box __background;
touchgfx::Image BCKG1;
SwipeDetectContainer swipeDetectContainerMainScreen;
touchgfx::Button buttonGoToCurrLen;
private:
/*
* Callback Declarations
*/
touchgfx::Callback<Screen1MainCuttingViewBase, const touchgfx::AbstractButton&> buttonCallback;
/*
* Callback Handler Declarations
*/
void buttonCallbackHandler(const touchgfx::AbstractButton& src);
};
#endif // SCREEN1MAINCUTTINGVIEWBASE_HPP
/*********************************************************************************/
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
/*********************************************************************************/
#include <gui_generated/screen1maincutting_screen/Screen1MainCuttingViewBase.hpp>
#include <touchgfx/Color.hpp>
#include "BitmapDatabase.hpp"
Screen1MainCuttingViewBase::Screen1MainCuttingViewBase() :
buttonCallback(this, &Screen1MainCuttingViewBase::buttonCallbackHandler)
{
__background.setPosition(0, 0, 480, 272);
__background.setColor(touchgfx::Color::getColorFrom24BitRGB(0, 0, 0));
BCKG1.setXY(0, 0);
BCKG1.setBitmap(touchgfx::Bitmap(BITMAP_BACKGROUND_ELECTRONIC_ID));
swipeDetectContainerMainScreen.setXY(0, 0);
buttonGoToCurrLen.setXY(443, 120);
buttonGoToCurrLen.setBitmaps(touchgfx::Bitmap(BITMAP_RIGHT_ARROW_ID), touchgfx::Bitmap(BITMAP_RIGHT_ARROW_PRESSED_ID));
buttonGoToCurrLen.setAction(buttonCallback);
add(__background);
add(BCKG1);
add(swipeDetectContainerMainScreen);
add(buttonGoToCurrLen);
}
void Screen1MainCuttingViewBase::setupScreen()
{
swipeDetectContainerMainScreen.initialize();
}
void Screen1MainCuttingViewBase::buttonCallbackHandler(const touchgfx::AbstractButton& src)
{
if (&src == &buttonGoToCurrLen)
{
//InteractionGoToCurrLen
//When buttonGoToCurrLen clicked change screen to Screen2CurrLen
//Go to Screen2CurrLen with screen transition towards East
application().gotoScreen2CurrLenScreenSlideTransitionEast();
}
}
2021-02-06 07:49 AM
Not really. I looked how Button widget initiates screen change and then figured out how Button widget is implemented to detect ClickEvent. So I followed the similar structure while programing my custom widget (SwipeDetect container) only to make it react to GestureEvent instead.
2021-02-08 12:39 AM
Hi,
Thank you very much for sharing this.
/Romain