I am developing a GUI where the user is supposed to connect to a WiFi network.
At one point, the user is shown all the available networks in a "Vertical List" and he can choose one of them to connect. This list is supposed to be refreshed one in a while. I have implemented a timer which will call the function "updateAwailableNetworks()". This function is supposed to save the information about the available networks in 3 arrays, one for the names, one for the signal strengths and one for the fact whether there is a password needed or not. All the information about the networks is meant to be saved in the global variable called "WiFiNetworks", where there is also information about the current network an other things.
Before integrating it to the platform, I have built the dummy functions which update the information about available networks. When there is an update, I set the new properties of the vertical list, such as the NoOfItems, and force a reload by invoking the VerticalList.InvalidateItems().
The problem is that when I scroll the list up and down, some items disappear. Some are replaced by the default "WiFi Name". I do not understand why this happens.
After debugging I think that there is a problem I am having with the global variable, which does not seem to update itself in all the places where I call it. However I do not know howto solve this issue.
Attached you find the project.
Thank you very much for the support.
the problem is caused by automatically reclaimed autoobject Settings_WiFi::WiFiNetworks. Thus the data stored in the autoobject is lost. This is an expected behavior. If an autoobject is not needed (referenced) anymore by other objects, Embedded Wizard releases the autoobject automatically saving so the memory. Please see the documentation Lifetime of an autoobject.
To solve the issue, add a variable to your Application::Application class, declare the variable with type corresponding to the of the autoobject (or even with object) and initialize the variable with the autoobject. The variable will prevent the autoobject from being discarded - it will retain a permanent reference to the autoobject. Following screenshot demonstrates the modification within your application:
I hope it helps you further.
Thanks for the reply. It seems to solve the issue.
However, I have now another issue.
I have implemented three main screens, called channels, commands and settings. I have implemented a navigation using Dialogs with horizontal swipe between these main screens. I want to navigate also within these screens. For example: when I am at Settings I can go into the specific settings.
For this purposeI have used Modals. So, if you press "WiFi settings" a modal is started. The reason why I chose Modals is because when I implemented it using Dialogs, it somehow did not disable the screen on the back and I could still interact with the previous screens (Settings screen in this case). I could press "WiFi settings" many times, even though I was already inside "WiFi settings".
My main problem now is that when I am inside the WiFi settings, I can still swipe left and go to the "Commands" screen. This should not be allowed.So I have 2 questions:
1. How do I make sure that I can not swipe when I am inside the WiFi settings?
2. Is it preferable to use modals or dialogs? (In case of Dialogs, how do I make sure that the user can not interact with the previous screens?)
Thank you very much.
Attached you find the project.https://ask.embedded-wizard.de/?qa=blob&qa_blobid=4145558495861140828
the concept of a modal state is in fact older. Compared with it, the Dialogs offer more features and are more flexible. Therefore I would recommend to use Dialogs in new projects. On the other hand, managing the modal state is simpler. So it is eventually better for very simple application cases.
Since both approaches are different, mixing them will not work as expected. If you have already experience with Dialogs, I would use this technique only and ignore modal state completely. Concerning your issue, please try following:
1. Present the Settings_Wifi component as a dialog. Don't use Add() and BeginModal(). For this purpose modify the method Settings::Settings.onWiFiPress as follows:
2. In the method Settings_WiFi::Settings_WiFi.onBack adapt the code to dismiss the dialog in the correct context:
The problem in your preceding implementation was, you tried to present the WiFi dialog in context of the Settings dialog. In this way, the Settings dialog was still able to handle user inputs. The chapter Take a closer look at the Dialog functionality explaines the special behavior of nested dialogs. Since you don't need such sophisticated behavior, just present all dialogs within the root object (GetRoot() is used here).
Also please note the additional IsCurrentDialog() if-conditions. These protect the application from eventual race conditions. They are not obligatory. I recommend them :o) Please see: Identify the active Dialogs and avoid race conditions.
I need your advice once more, since now the project is getting a bit more sophisticated.Above I said that I had trouble with the dialogs not deactivating the other dialogs which were below it and you said the I need to preset a dialog using the GetRoot(), so that it is presented within the root object. And it indeed solved the issue.Now I have the same project, but I have arranged it a bit diffrent since I need some things which should always be on top of everything else, such as a status bar. What I did was divide my UI components into Level_0 and Level_1. Level_0 is on top of Level_1. I need to switch dialogs if I swipe in the Level_1 component. Then, within Level_1 I have the Settings section. When I press the WiFi button it should present a new Dialog, which should disable the Level_0 and Level_1 component from taking user inputs. Folloing you suggestion, I present the Settings_WiFi dialog under the root context. However, I can still interact with the things which are below it. I have attached the project and have made the Settings_WiFi background transparent so that you can see when the interaction with the screens bellow takes place.
How do I solve this issue?
Step 1: In the method Settings::Settings.onWiFiPress replace GetRoot() bei Owner. In this way the new dialog will be presented in context of the same owner component as the actual Dialog. The result is thus similar to presenting all dialogs in context of root object:
Step 2: In the method Settings_WiFi::Settings_WiFi.onBack also change GetRoot() in Owner. Also note, I have commented out the IsCurrentDialog() condition. I address this in the Step 3 again:
Step 3: The condition IsCurrentDialog() does not work anymore. To recognize a dialog as active one, the dialog and all its owner have to be dialogs too. The Level_1 component, however, is not presented as Dialog. Trying to present it as Dialog will however put it over Level_0 component. What can you do?
Option 1: Instead on IsCurrentDialog() use IsActiveDialog( false ). This tests the status of the dialog in a less global context.As long as you present all dialogs within Level_1 it should avoid evtl. race conditions (if any). For example:
Option 2: Don't use IsCurrentDialog() and avoid race conditions in another way.
Option 3: Present the GUI component Level_1 by using PresentDialog(). Then, however, the Level_1 will overlapp the Level_0 component. See your other thread Is it possible to set up a view that will always come on top of everything (like a status bar)? concerning the possible approaches of how to retain a GUI component on top of other components.
Thanks for the reply. It seems to solve the issue. I need to make sóme adjustments, but the first trial I made looks good.
There is one other thing which I have noticed and is a little strange. As you have seen in the project, there is a keboardIcon on the bottom right which is supposed to open and close the keyboard. I have implemented a short animation and it looks good.
The behavior I want is that when the keyboard is opened, the part of the screen that is on the back of the keyboard has to stop getting user inputs. In order to achieve that, I set up a touch handler as the bottom most object of the component keyboard which is supposed to do othing, but just prevent any touch events to penetrate through the keyboard. And it indeed was ok, untill I by chance did a double click right above the keyboard, which is indeed area of the keyboard component. You can see this in the picture attached.
I have set the thouch handler of the keyboard so that it does not retarget anything, however, the double click does this strange behavior.
Do you know where this comes from? Is there another way to disable the user inputs on the back of a certain component?
I suppose the handler in the background is configured to react to single taps only. As soon as you double tap on it, the handle resigns and other handler willing to react to the event will process. Please see the section Configure the filter condition. Especially please note the usage of the both properties MinStrikeCount and MaxStrikeCount. Set MaxStrikeCount to a value that is greater than the max. number of expected taps. If you set it to 10, the handler will process all tap sequences with 1 .. 10 taps.
Also possible approach is to present the keyboard as Dialog too and so prevent other dialogs from being able to react to touch event.
Ask Embedded Wizard
Welcome to the question and answer site for Embedded Wizard users and UI developers.
Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!