Skip to main content
PPete
Associate III
February 20, 2024
Solved

Custom Container setTouchable not working

  • February 20, 2024
  • 10 replies
  • 4195 views

I build a custom Numpad Container. Iam setting it Visible when a textarea is clicked. And it is the top layer on the Screen. Trying to set other containers on a lower layer not touchable is not working.
I can still click the slide menu button und some other buttons on my Background container.

Is it a bug?

scrollableContainer.setTouchable(false);

slideMenuContainer.setTouchable(false);

backGroundContainer.setTouchable(false);

This topic has been closed for replies.
Best answer by JTP1

Hello

Easy way to make your keypad 'modal' is first make keypad container size to match your screen size and move the actual keypad to the center of the screen, for example.

Then place normal box- widget to your keypad- container and match the size of it so that it equals your screen size. Put last in the list, i mean, behind the the other widgets of keypad.

Then put mixins - clickListener selected from that keypad background box.Then this box 'eats' all clicks which are not pointed to keypad area.

You can also set alpha value of it so that its fully transparent. Or make it partially transparent to get your keypad popup since other parts of ui are dimmed.

Then its enough just to set keypad visible true, not needed to work with touchable- property of other containers on the screen.

BR JTP

10 replies

urbito
Senior II
February 20, 2024

have you also called scrollableContainer.invalidate(); after each one? you need to invalidate everytime you change something in any object/widget.

 

Greetings.

PPete
PPeteAuthor
Associate III
February 20, 2024

I also tried this yes, but it didnt help.

urbito
Senior II
February 20, 2024

Inside each container, there are something you dont want to "touch" when your numpad is visible, have you tried to set not touchable what is inside those containers, instead of whole container?

PPete
PPeteAuthor
Associate III
February 20, 2024

Yes, if the user will click on a textarea the numpad container will popup on the top layer.
When the user confirmed the numpad input, the input will be copied to the testArea. This works fine.
Mz goal is to block all other inputs on the display. In the back there is a background container with a button to switch the language, set the time and some other buttons. I tried to block these buttons with the function setTouchable(false) and invalidate();. But this worked not for all the buttons in the background container. So i tried to block the touch input for the container.

urbito
Senior II
February 20, 2024

If it is possible for you, share the code you are using to enabling and disabling the touchpad on the components/widgets. Seems for me some kind of logic issue when Disabling and Enabling the touchable.

 

Maybe in your "HandleTickEvent" or in you "setupscreen" or whatever function you are enabling the touchPad, you are enabling again something before the showingup the touchPad. 

 

 

PPete
PPeteAuthor
Associate III
February 20, 2024

I have two Callbacks. One from the textArea and one from the numpad Container.

 

void SettingsView::valueContainer_ClickHandler(ValueContainer *valueContainer)
{
	numPadContainer.setVisible(true);
	numPadContainer.invalidate();

	scrollableContainer.setTouchable(false);
	scrollableContainer.invalidate();

	slideMenuContainer.setTouchable(false);
	slideMenuContainer.invalidate();

	backGroundContainer.setTouchable(false);
	backGroundContainer.invalidate();

	valueContainer_Ptr = valueContainer;

	this->invalidate();
}

void SettingsView::numPadContainer_ClickHandler(double *numPadInput)
{
	if(numPadInput != NULL)
	{
		valueContainer_Ptr->setTextArea_Value(*numPadInput);

#ifndef SIMULATOR
		uint16_t msgIndex = valueContainer_Ptr->get_MessageIndex();
		Msg_ValueStruct_t MsgFromGui = { .index = msgIndex, .eventType = EVENT_VALUE_SET, .value = *numPadInput };
		presenter->set_Value(MsgFromGui);
#endif
	}

	numPadContainer.setVisible(false);
	numPadContainer.invalidate();

	scrollableContainer.setTouchable(true);
	scrollableContainer.invalidate();

	slideMenuContainer.setTouchable(true);
	slideMenuContainer.invalidate();

	backGroundContainer.setTouchable(true);
	backGroundContainer.invalidate();

	this->invalidate();
}

Unbenannt.PNG 

urbito
Senior II
February 20, 2024

If i am not wrong, this numPadContainer_ClickHandler would happen whenever you click any button from the numPad, so, in the moment 0 before you click any button, all of your other containers are not touchable, but once you do your first touch in the container, they go back as touchable and also the numPad itself would not be even vissible. 

 

Is this the intended behaivour?

 

Else you can add another condition in the numPad handler, waiting for a certain button to be clicked before putting everything as touchable again?

PPete
PPeteAuthor
Associate III
February 20, 2024

I only run the callback function if the user hits ok or cancel.
I just debugged it.

void NumPadContainer::function_NumPad_Cancel(void)
{
	if (viewCallback && viewCallback->isValid())
	{
		numPadInput = 0;
		viewCallback->execute(&numPadInput);
	}

	Unicode::UnicodeChar del[] = { 0x00	};
	Unicode::strncpy(&textAreaNumPadBuffer[0], del, TEXTAREANUMPAD_SIZE);
	textAreaNumPad.invalidate();
}

void NumPadContainer::function_NumPad_Ok(void)
{
	if (viewCallback && viewCallback->isValid())
	{
		Unicode::toUTF8(textAreaNumPadBuffer, utf8_Buffer, BUFFER_SIZE);
		numPadInput = std::atof((const char *)utf8_Buffer);
		viewCallback->execute(&numPadInput);
	}

	Unicode::UnicodeChar del[] = { 0x00	};
	Unicode::strncpy(&textAreaNumPadBuffer[0], del, TEXTAREANUMPAD_SIZE);
	textAreaNumPad.invalidate();
}
JTP1Best answer
Graduate II
February 20, 2024

Hello

Easy way to make your keypad 'modal' is first make keypad container size to match your screen size and move the actual keypad to the center of the screen, for example.

Then place normal box- widget to your keypad- container and match the size of it so that it equals your screen size. Put last in the list, i mean, behind the the other widgets of keypad.

Then put mixins - clickListener selected from that keypad background box.Then this box 'eats' all clicks which are not pointed to keypad area.

You can also set alpha value of it so that its fully transparent. Or make it partially transparent to get your keypad popup since other parts of ui are dimmed.

Then its enough just to set keypad visible true, not needed to work with touchable- property of other containers on the screen.

BR JTP

PPete
PPeteAuthor
Associate III
February 21, 2024

Hello thanks for the fast response.
the solution with the clicklistener is working for me. But it feels like a Workaround.

Set the background container to "not touchable" and back to "touchable" is not activating the touch Event to all of my four buttons in the Background Container. I think something is slumbering there.

Greats Peter

Graduate II
February 21, 2024

Hello

Yes, seems to be that 'setTouchable(0)' doesn't do anything with custom containers, but with widgets it works fine.

Maybe easiest way is to add implementation of 'setTouchable' function to custom container and list all widgets in that container there, like:

 

void CustomContainer1::setTouchable(bool touch)
{
 button1.setTouchable(touch);
		button2.setTouchable(touch);
}

 

Other way to solve it is to add implementation of setTouchable to the 'Container.hpp' at '\touchgfx\framework\include\touchgfx\containers' folder:

 

	virtual void setTouchable(bool touch)
	{
		// find first child
		Drawable* child = firstChild;
		
		// child found (!=0)
		while (child)
		{
			// set the touchable property of that child
			child->setTouchable(touch);
			
			// find next sibling
			child = child->nextSibling;
		}
	} 

 

What says @GaetanGodart ,is this proper correction ?

Br JTP

GaetanGodart
Technical Moderator
February 22, 2024

Hello @JTP1 and @PPete 

 

SETTING ELEMENT AS TOUCHABLE

When clicking on a pixel, TouchGFX will check if the first layer is touchable or not, if it isn't, it will check the layer below until he finds the first touchable layer.

Therefore, as @JTP1 said in the post that is marked as best solution, by simply setting a custom container as touchable, you won't be able to click on a button bellow that custom container.

There are many ways of setting an element (custom container or widget) as touchable.

1)
You can do so within the screen.cpp file it is in such as :

 

 

myCustomContainer.setTouchable(true);
button1.setTouchable(true);

 

 

2)
You can also set a custom container directly touchable from his own cpp file (ex. myCustomContainer.cpp) from the initialize function such as:

 

 

void myCustomContainer::initialize()
{
 myCustomContainerBase::initialize();
 setTouchable(true);
}

 

 

3)
You can set an element as touchable by activating the mixin "clickListener" active

GaetanGodart_0-1708598350588.png
This is possible in Designer from within the screen and also from within the custom container if you have a background buy setting the background as ClickListener (or setting all the elements of your custom container that you don't want to be able to click through as clickListener).

4)
Finally, you can set an element as touchable during runtime by calling setTouchable(true) as previously.
Find an example of that in the file attached.

 

SETTING CHILD OF CUSTOM CONTAINER AS TOUCHABLE

If on the other hand you do not want to set the whole container as touchable but you want to set all the elements of the custom container as touchable, @JTP1 's implementation to set all child touchable is great.
Please find an example of this implementation in the same example attached.
The code setting children touchable is directly inside the interaction in the custom container.

I had to change nextSibling by getNextSibling() because the nextSibling attribute is protected.
Other than that it works great!
Thank you for your response.

Regards,

Graduate II
February 22, 2024

Hello

Thank you very much for your answer Gaetan.

I must say that my opinion is that if somebody disables Touchable- property from any container (customContainer, Container or even scrollList), all the widgets inside of that container should be disabled also.

But my quick idea of overwriting setTouchable at 'Container.hpp' and set it to affect all of its child seems to be bit problematic with some containers. (for example with scrollList which is based container- class).

So maybe it would be good addtion to add new function to container class (container.hpp) like

 

	virtual void setContainerTouchable(bool touch)
	{	
		// set also the container own Touchable- property
		touchable=touch;
		
		// find first child
		Drawable* child = firstChild;
		
		// child found (!=0)
		while (child)
		{
			// set the touchable property of that child
			child->setTouchable(touch);
			
			// find next sibling
			child = child->nextSibling;
		}
	} 

 

Then setTouchable works like before and with this new function its possible enable or disable container and its child widget with one function call. In same cases it might be useful.

Br JTP