Can't properly force a component on-screen with scrollComponentToVisible - codenameone

On a given form, we replace one component with another.
The original component is a series of TextFields, and the new form is some informational text and a button. We hide the first one, and show the second one (the UI designer has both Containers within the form).
I tried using scrollRectToVisible with various values but it didn't seem to make any difference with the scrolling.
continueButtonContainer.setHidden(false);
f.forceRevalidate();
Button continueButton =
(Button)StateMachine.GetInstance().findByName("ButtonContinue", f);
f.scrollComponentToVisible(continueButtonContainer);
f.scrollComponentToVisible(continueButton);
I'm expecting the continue button to be near the top of the screen.
If the screen was scrolled before displaying the continue button, the button ends up right at the bottom of the screen (it was below the bottom of the screen before I put in the scrollComponentToVisible line(s).
After the user scrolls the screen, the button goes up to where it needs to be, and stays there.
If the screen is not scrolled, the button appears where it should be.
I know I can probably add some invisible containers underneath the button and force them onto the screen, but I would rather have a slightly more robust solution.

There are a few issues with this. First you are using forceRevalidate which should be used in very rare cases.
Second it seems that you are invoking this on a Form, this is a bit misleading. While it seems that:
f.add(myCmp);
Adds a component to the form it is really a synonym to:
f.getContentPane().add(myCmp);
That's important because you need to invoke the scrollComponentToVisible on the scrollable container which will actually do the work and ideally be the direct parent of said component. I'm assuming it's the content pane in your case but it depends on layout etc.
The last part is letting the layout do its job. If you are invoking this before the form is showing this might not work. Notice that doing it after a call to show is meaningless as the form might take time with transitions. You can use a show listener or override the laidOut callback method to perform things like this.

Related

Material UI AutoComplete component size behavior

I want autocomplete(for me it's a search bar) component to stay in one line and expand when searching. Sadly, the component adds another line when there is a long chip.
For example:
the image shows that the component added a line
how can I stop the component from adding a new line while maintaining it's behavior while writing in it (when you write in the component it expands to show the entire search)
I tried changing its CSS a max lines prop but it didn't work.
granted I might missed something in the CSS
To summarize the behavior of the bar:
it is a multi select
There are two situations
the user isn't using it.
In that situation the bar should just be one line nothing more
the user clicked on it and editing in the bar
In that situation the bar should expand vertically to and show all the chips
right now It correspond with the situation that I described, but if a chip that is too big it expands to two lines and I want it to stay just one line if it isn't situation 2.

React material ui: how to disable pointer capture when touching and dragging outside a Card?

I'm using React, and have a material UI Card that toggles on and off when clicked. I am trying to 1) get the card to toggle on/off correctly if the user long-presses it, and 2) disable the card toggling if the user presses it and slides(drags) away, then releases. Performing these actions with a mouse has all the desired effects, and there are no problems. However, my app is used on a touch-screen monitor (without a mouse) and so I must replicate the same outcomes with touching the screen.
Initially, I was using the onClick event handler to toggle the card. Long pressing with your finger (the first issue) was not properly toggling it. After a bit of research, I learned that mouse and touch events were combined into one: pointer events. So I switched onClick to onPointerUp and it worked magically.
However, this is where the second issue comes in. If the user clicks the card and drags his or her finger away from it and releases, it still gets toggled (using the mouse doesn't have this same effect). I did some digging and according to MDN, pointer capture could be related:
Pointer capture allows events for a particular pointer event (PointerEvent) to be re-targeted to a particular element instead of the normal (or hit test) target at a pointer's location. This can be used to ensure that an element continues to receive pointer events even if the pointer device's contact moves off the element (such as by scrolling or panning).
My question is, why is the mouse click working correctly while touching doesn't? And how does one go about disabling the card getting toggled when your finger is dragged away from it?
Codesandbox of sample
Edit: Forgot to mention, I want the card to toggle correctly as long as the touch is released while on the card (even if it is dragged away and returns). This works fine with the mouse, but for touching, it toggles regardless of where your finger is released.
Edit2: Added codesandbox link.
Some things of note: touch-action is set to none (CSS) and this is where the strange behavior happens, but I need to have it set that way to prevent unwanted touch registers like scrolling.
I also noticed that for mouse clicks, you can select a card by clicking outside the card and dragging into it and releasing the click. I guess since the event is onPointerUp that would make sense. Although this effect is undesirable, users will only use touching in my app so it's not something I have to worry about. Regardless, I would like to understand the right way to approach this and how to achieve my desired effects.

Codename One Focus and Removing Components

I have implemented code in focusGained that in some cases may cause the component (a container I have set to be focusable) which just received that focus to be removed from the screen, and replaced in the container by another component. This will also cause a redraw of the screen to show the changed component.
This does work but I have a bit of a problem, in that the next component in the container also gains focus and so my code removes/replaces it also. I assume this is because on the redraw, that component now occupies the same space where the tap originally occurred.
If the last component in the container was originally selected, then the replacement component is itself given focus and so it is removed and replaced.
Any ideas on what I may have miscoded or anything I can do to avoid the second focusGained call?
I doubt you did something wrong. If we remove the component with the focus we'll find the next available one. The replace method doesn't take focus into consideration but can't grant focus to a component that isn't physically here yet so it's granted to the next component. Not much to do here.
You can requstFocus() after the transition completes to fix the order manually.

How to make the screen reader start to read the web content after scrolling

I'm making an accessible web application. One of the feature is a button that allows users to scroll to a certain section of the page. I'm using window.scrollTo(x,y) for this functionality.
Now testing my application using the built-in Mac VoicerOver, I found that although I can click on the button and scroll with no problem, after scrolling, VoiceOver doesn't read anything. Instead I have to click on the mouse one, or use the keyboard equivalents to make it read the content that's on the screen after scrolling.
I'm afraid that some users may not realize that they need another click after clicking on the button. I have two possible solutions:
When the screen reader read the button, it also tells the user that if they want to go to the livechat, they need to click again after clicking on the button. I know how to implement this one, but it looks verbose and dumb.
Change my code so that VoiceOver will read the content after scrolling. I don't know how to implement this one.
The content I would like the screen reader to read is wrapped in a tag.
If you are only scrolling the page, then most screen reader users will not care that you scrolled. With limited or no vision, whether the screen scrolls or not does not matter because the screen cannot be seen.
However, if you are scrolling the page in order to put a certain element into view, then that would benefit screen reader users too.
It sounds like you're trying to do the latter:
allow users to scroll to a certain section of the page
In that case, you also need to put the keyboard focus on that element via the focus() javascript call. Moving the focus will cause VoiceOver to read that content. But to move the focus to a natively non-focusable element (such as an <h2> or a <section> or <p>), the receiving element will need tabindex="-1".
<h2 tabindex="-1" id="myh2">some heading</h2>
and then somewhere you'd have this javascript:
var element = document.getElementById("myh2");
element.focus();

CodenameOne set indexing of fields for virtual keyboard

Using CodenameOne,
I have a Form that the user needs to fill in. All of the components, however, are actually Containers that represent custom functionality. As an example, I would have a TextField alongside a Button on a Container, and I would use that Container as a "Component". This allows me to create more advanced functionality by combining existing Components.
A good example of where this is necessary is that of a custom date entry field existing out of 3 TextFields or a combination of TextFields and ComboBoxes.
I have a "Field" that has functionality for that of a Contact Component.
This all serves as a single "Unit" in order to allow the user to choose a contact or fill in their own. Buttons open Dialog popups, etc.
My problems comes with when the user uses the Android keyboard. Should this Contact Object be the second "Field" and the user presses the 'Next' button on the Android keyboard, the App does not know what field to give focus.
Furthermore, If one of the fields are a ComboBox or a Button and the user presses next to reach that Component, the keyboard doesn't close, and instead removes the 'Next' button, replacing it with a return button or an emoticon selector.
Below is an example situation:
The user would press on the first field, the Keyboard shows up, and when the user presses next, the keyboard's Next button dissapears, as the immediate next field happens to be a Button or ComboBox.
Is there a way to change the focusing index, or omit certain fields form ever gaining focus in this way? I tried making the entire thing a Component but that doesnt allow me to combine other Components. Even if it is possible to make the parent Container a Component, how would I solve this particular issue?
The default behavior is to use the "next focus down" for this functionality so just use setNextFocusDown(nextTextField) on each one of the components. Notice that a ComboBox won't work as expected although you might want to change that to an AutoCompleteTextField which would.

Resources