I have a NSScrollView with a NSImageVIew within.
I'm using magnification enabled on NSScrollView.
I'm seeing a funny downward drift of the NSImageView when scaling using a 'pinch' gesture on my MBP track pad.
If you pinch and un-pinch continuously ... zooming in and out, the image drifts downwards within the NSScrollView. Can't explain it or locate bug.
See here > https://github.com/BinaryBlobs/ScrollViewBug
What am I doing wrong ?
Related
In a MacOS application being written in Swift, I have a vanilla, sub-classed NSScrollView that allows magnification. The documentView it presents is not very wide and completely fits horizontally within the bounds of the NSScrollView's display area. But the document is very long, and so it scrolls vertically.
When I pan slowly using a two-finger gesture on my trackpad, the NSScrollView prevents any horizontal movement (other than a little springiness). Panning vertically also works as expected.
When I pan vertically hard (with a little flick to it) and let go, the scrolling in that direction continues for a little while with virtual momentum, then slows down and stops. Again, all seems correct.
Sometimes, though, scrolling jerks to an immediate stop, based on some difference (I presume) in how Apple's internal (default) NSPanGestureRecognizer analyzes the movement. The jerking to a stop is unwanted and frustrating. It seems to only occur when the document has been zoomed out. When zoomed in, the jerking doesn't happen after a trackpad flick. So the difference likely has to do with the gesture recognizer working in the screen coordinate system, rather than the magnified coordinate system of the NSScrollView.
The other problem is that if the pan gesture is strong, and has any diagonal direction to it (which is most of the time, since it's really hard to flick on the trackpad perfectly vertically), the automatic, continual scrolling drifts the document view right or left in that diagonal direction, even though there's no reason to and it's normally pinned horizontally. For very long continuous scrolls, the document view even drifts completely outside the visible bounds, which is kind of ridiculous. Then, when the continuous scrolling stops, the NSScrollView instantly (without continuous scrolling) jumps the documentView completely back into view (horizontally).
The same drifting analogously occurs when doing horizontal continuous scrolling for documents that are very wide and not very high.
This drifting during continuous scrolling after the gesture has finished occurs regardless of whether any centering constraint is in effect, a là this stackoverflow question and answer.
So ... is there a way to prevent this jerking and this drifting during continuous scrolling in an NSScrollView?
Willeke's advice seems to be spot-on. It also solves the jerkiness problem, for reasons I don't understand. The sub-classed NSScrollView is now:
class MyScrollView : NSScrollView {
override init(frame fr: NSRect)
{
super.init(frame: fr)
prepareScrolling()
}
required init?(coder: NSCoder)
{
super.init(coder: coder)
prepareScrolling()
}
private func prepareScrolling()
{
self.allowsMagnification = true
self.usesPredominantAxisScrolling = true // <-- Added to fix the problem
self.maxMagnification = 4.0
self.minMagnification = 0.25
}
// Etc.
}
Hi I would like to implement an rotating imageview where user can rotate the imageview by touching only the corners.
how could i implement that. Please help.
I would like to implement an rotating imageview where user can rotate the imageview by touching only the corners.
There are two parts to this task, and I'm not sure which one you're asking about:
How to do something in response to a dragging gesture.
How to rotate a view.
Whether you're talking about iOS or macOS, there are at least two options for responding to a dragging operation. One is to track the touch or mouse event yourself. Touches and mouse interactions both have a beginning, when the finger touches the screen or the mouse button is depressed; a middle, when the location of the finger or cursor may change; and an end, when the finger leaves the screen or the mouse button is released. Both operating systems have events for these things that are sent through their respective event handling systems.
An easier method is to use a gesture recognizer, which is usually easier to get right AND the existing gesture recognizers encourage you to implement the expected behavior by making that the easiest option. For example, UIKit and AppKit each have a rotation gesture recognizer that recognizes two touches moving in opposite directions as a rotation gesture, since that's a common way to rotate objects. But you can also implement your own gesture recognizer that can notice that a touch happens a) for longer than some minimum time, b) within some minimum distance from a corner, and c) with movement in a direction that would cause rotation. So, if you want to handle dragging in order to rotate something, look into gesture recognizers.
UIView and NSView both provide methods for rotating a view in its superview's coordinate system. NSView provides a frameRotation property that you can set, and UIView has a transform property to which you can apply Core Graphics functions like CGAffineTransformRotate().
In summary, what you should do is to create a gesture recognizer subclass that recognizes the rotation gesture that you want and rotates the view that it's attached to. Then instantiate that gesture recognizer and apply it to the view that you want to rotate.
I have an NSScrollview with a large canvas that can be scrolled and zoomed etc. When I scroll diagonally at an angle of around 20 degrees from vertical it's really jerky (using a track pad.) This jerkiness even continues as the scrolling animates to rest.
All other angles of scroll are buttery smooth - which makes me think it's got something to do with a preference for vertical scrolling (predominant axis scrolling is disabled.)
The effect only seems to happen when I'm using layer backed views.
Anyone know what's going on here?
Thanks
Craig
Confirmed bug in OSX Yosemite (by Apple DTS)
I have a OSX Cocoa WebView that is a subview of view in a NSViewController. The view of the NSViewController has been added as a subview to the main window controller's view.
I am attempting to load HTML5 games into the WebView and proportionally scale them so that they fit the WebView with the least empty space possible.
I have a LOT of games I am trying to make this work for with different constraints.
For HTML5 games that were designed to auto-scale to the window, this works perfectly out of the box.
For HTML5 games that were design a fixed size for iPhone, they appear in the upper left of the WebView and take up a very small portion of the window.
For example, many games are 480x360. The window size is 1024x768 (less the title bar).
I've tried various methods for scaling up the content:
How to resize WebView according to its content?
Scale WebView in Cocoa
I've also tried using javascript to scale the content.
These definitely DO work in scaling up the content and I can get good results in filling the screen.
HOWEVER, this does NOT properly scale the position of the mouse events on the WebView canvas. Meaning, no matter how big I scale the WebView clipview which resizes content, the actual area that is clickable with the mouse is still the smaller unscaled area (as if visually things are scaling but functionally things are not).
Is there some way to scale the mouse click event for position? I can see if I click in the lower right area of the smaller bounding box, it has an affect on the larger scaled content as if I clicked the lower right area.
It seems I could add some scaling math somewhere in capturing the mouse click events but I don't understand where this can be done.
Appreciate any help.
Thanks
Short
How can I control wether or not a swipe on a UIScrollView has made a big enough Y delta to be considered a vertical swipe and let it be handled by a nested UIScrollView (UIWebView)?
Long
I have a UIScrollView which pages horizontally. A ‘page’ is a UIWebView (which contains a UIScrollView) and only scrolls vertically. The content sizes are all properly set so that this works as expected.
However, I’ve noticed that when you try to swipe horizontally fast, you have a high chance of making a slightly diagonal swipe. If it’s only a tiny bit, the scrollviews handle it as I would like to, but every now and then the Y delta is enough to make the nested scrollview (UIWebView) recognise the swipe as a vertical one, whereas the X delta could be considered big enough to indicate a horizontal swipe.
I have found a lot of old articles that explain that one should override the standard UIResponder touch methods (e.g. touchesBegan:withEvent:), however, nowadays this is all handled by gesture recognisers.
So how can I influence the paging scrollview’s pan gesture recogniser to allow more Y delta for a horizontal swipe?
One way to make it work, as I need, is by:
setting delaysContentTouches on the paging scrollview to NO
to the nested scrollviews’ pan gesture recognisers add a dependency on the paging scrollview’s pan gesture recogniser to fail.
However, this breaks vertical scrolling in the nested scrollviews in such a way that they are not recognised until the swipe has ended and done fast. I suspect this is because the paging scrollview’s pan gesture recogniser doesn’t fail until the touches end.