How to scroll Firemonkey TListBox without capturing focus in its controls? - delphi

I have a TListBox with controls in each item, such as TEdit, TComboBox, TSwitch, etc, aligned to the right. There are about 20 items in this list, so it extends beyond the screen, and thus user needs to scroll (by sliding finger) to get to the bottom.
The problem is that even in a quick gesture, if user swipes their finger initially on one of these controls, that control takes focus and the list doesn't scroll. Currently, the only way to scroll up or down is to swipe the finger on the left side of the list, where there aren't any controls. I could disable HitTest or CanFocus, but then that control would never get focus, even when the user wants to actually tap on it.
How can I allow user to swipe up or down on these controls to scroll the list without that control taking focus?

I had the same issue.
To solve that insted using a TListBox I used a TVertScrollBox with a layout inside.
Each control is align to top and, to make it work, I needed a VKVertScrollBox from:
https://github.com/DelphiWorlds/KastriFree/tree/master/Demos/VKVertScrollbox
Doing so you will have a scrollable list of components where you can swipe your finger down and see it moving.
Besides, to avoid the entering and getFocus on each component when swiping you can use a helper on each component to catch the movement by overriding MouseDown, MouseMove and MouseUp and prevent entering overriding doEnter (also overrited) if it is moving (catched on MouseMove method).

Related

How to make the TScrollBox automatically scroll when DragMode is dmAutomatic?

I have a ScrollBox in which I have a GridPanel in which I have Buttons.
I set DragMode to dmAutomatic for all buttons so I can move the buttons around (drag and drop).
But I have a problem: because the GridPanel is larger than the ScrollBox, the ScrollBox has the vertical scrollbar visible. I want to make the ScrollBar to automatically scroll down so I can drop a bottom from the visible (top) rows into the inaccessible rows at the bottom (this is typical behavior for all Windows programs, right?)
I have simple code that is doing this: In MouseMove I detect when the mouse is getting close to the bottom of the ScrollBox and I adjust ScrollBox.VertScrollBa.Position to scroll down. This works ONLY if I am NOT in "drag and drop" mode (if I am not dragging a button).
If I start a drag and drop operation NO mouse events are fired.
What can I do to receive MouseMove event even if I am in "drag and drop" mode?
A solution would be not to use dmAutomatic and implement my own drag and drop alternative (based on mousedown, mousemove, mouseup). Is these a quicker fix?
During drag-and-drop operations the VCL will create a TDragObject to manage said drag-and-drop operation. This TDragObject - or a derived class - will start receiving and handling mouse events as long as dragging lasts. In turn, it will generate drag-and-drop specific events like OnDragOver and OnDragDrop which can be handled by - potential target - controls under current mouse position.
This will allow you to handle OnMouseMove whenever no drag-and-drop is happening. In addition handle OnDragOver in a similar way to catch mouse movements when currently dragging.

Scrolling Programmatically THorzScrollBox Firemonkey XE6

I have a THorzScrollBox in a form, and some TStyledControls inside. Each StyledControl has a Tag to identify. Using an TEdit to inform a value, I can find inside the ScrollBox an specific Control by his tag.
If the control that I searched is not on the screen, I want to scroll the ScrollBox to show it.
How can I do this programmatically?
I found a way to do this.
I have to use ScrollBy. But the detail is that if I want to scroll the controls to right I have to use a negative value.
Example:
sbItems.ScrollBy(-10, 0); // this will scroll to right
If I use a positive value, it will scroll to left.
sbItems.ScrollBy(10, 0); // this will scroll to left
The point is, if you scroll once, the ViewportPosition will change and the next time you execute ScrollBy, it will not reset the scroll position, it will scroll from the point you already have scrolled.

Delphi iOS TMemo Scroll Versus Pan

I have a readonly memo shwoing some text. However, there is a usability oddness. The user can pan the content in TMemo when only scroll ought to be possible.
Since people seem to think panning and scrolling is the same, I will give my definitions:
Panning = You can drag the entire content top/bottom/left/right (i.e. all
directions... NOT scrolling text but more like dragging entire "textview" object/widget. Also what is normally seen in image panning demos where you can pan the image in different directions to see e.g. top/bottom/left/right.)
Scrolling of text = scrolling of text the direction the content in the widget is placed (e.g. scrolling text up/down)
My question is how to only have scroll if possible. (And not be able to drag 2/3 of the entire text control out of the view although i bounces back when touch is let go)
What you are experiencing is an animation effect.
It can be turned off by setting the property:
AniCalculations.BoundsAnimation := false;
See FMX.InertialMovement.TAniCalculations.BoundsAnimation for more information.

How to design a scrollable menu?

I have a CCMenu with cocos2d-iphone. It lists many items vertically.
I want the user to be able to swipe his finger to scroll.
What I have done so far was check when the user makes a touch and moves it. That way I can calculate the relative movement required to move the menu properly. And it works.
However, if the touch begins over a CCMenuItemImage, my layer will not receive the ccTouchesBegan nor the ccTouchesMoved messages, so I can't perform such calculations.
What do I do?

Is it possible to remove the delay of UIButton's highlighted state inside a UIScrollView?

I have noticed a slight delay on the highlighted state of a UIButton when touched down if it is inside a UIScrollView (or a table view). Otherwise, the highlighted state is pretty much instantaneous.
I surmise this must be by-design to provide a chance for user to scroll. But it just seems like the button is unresponsive to me. Is there a way to fix this?
Indeed, it's a design choice. It needs this small time to differentiate a scroll (panGesture) from a tap. If you eliminate this delay, then the user won't be able to scroll if he places the finger on top of the button, which is not good user experience.
Because a scroll view has no scroll bars, it must know whether a touch signals an intent to scroll versus an intent to track a subview in the content. To make this determination, it temporarily intercepts a touch-down event by starting a timer and, before the timer fires, seeing if the touching finger makes any movement. If the timer fires without a significant change in position, the scroll view sends tracking events to the touched subview of the content view.
from the UIScrollView Documentation
I wouldn't recommend disabling the delay, but if you insist, you can set it in interface builder (select the Scroll View, and on the right panel, right under "Bounces Zoom"), or using this code:
scrollView.delaysContentTouches = false

Resources