iOS - How to control UIBezierPath drawing with UISlider? - objective-c

I want to control the drawing of my UIBezierPath using a UISlider.
The aim is to be able to scrub the timeline (UISlider) and cause the line (UIBezierPath) to draw based on the current position of the slider.
So that when I scrub forward the path renders forward & when I scrub back the path renders backwards.
I have the code to render the path drawing in both directions based on this sample code which I added reverse path to (https://github.com/ole/Animated-Paths)
The main thing I am struggling to understand is how can I have the path render when I move the slider since I cant really use animations as they would not update with the sliders movement..
Cheers
Damien

If you are tracking the "Control Events" of the UISlider, for example like this:
[yourSlider addTarget:self action:#selector(seekBegan:) forControlEvents:UIControlEventTouchDown];
[yourSlider addTarget:self action:#selector(seekContinues:) forControlEvents:UIControlEventTouchDragInside];
[yourSlider addTarget:self action:#selector(seekEnded:) forControlEvents:UIControlEventTouchUpInside];
.. you can then do your animations inside "seekContinues:". I can't say how smooth it will be though! as there may be a lot of calls to that method.

So I found that I was unable to use animations to achieve what I wanted so I used a custom UIView subclass and implemented in its drawRect method the code to handle the animations
Basically I set a index in the subclass that controlled how many of the points the drawrect method draws.
This gave me the desired approach and allowed me to change the value based on the slider.
For the drawing I used CGContextMoveToPoint & CGContextAddLineToPoint to render the paths
Cheers

Related

NSWindow: place part of image outside window

I've a Cocoa application with a NSWindow with the style NSBorderlessWindowMask (without titlebar). I would like to place a image in the window but a part of the image should be places outside of the window.
How can this be done?
Here are two articles I found related to what you want to do.
Cocoa With Love Example
parmanoir.com example
The gist is to subclass NSWindow to make it a borderless transparent window, then make a sub view that draws your custom shape and make it the windows content view.
From the look of the sample the shadow should still apply.
From Cocoa With Love:
The shadow behind the window is drawn automatically for whatever shape we draw. Any part of the window that is left completely clear will not receive mouse clicks (they will fall through the window).
to draw the border do something like this in your view class display method:
NSBezierPath* border = [NSBezierPath bezierPathWithRect:self.frame];
[border setLineWidth: 1.0];
[[NSColor windowFrameColor] set];
[border stroke];
If you don't have a custom view class then do [view lockFocus]; before doing that path and replace self with your view instance. after drawing be sure to do [view unlockFocus];
An important message from the docs concerning lockFocus:
Hiding or miniaturizing a one-shot window causes the backing store for that window to be released. If you don’t use the standard display mechanism to draw, you should use lockFocusIfCanDraw rather than lockFocus if there is a chance of drawing while the window is either miniaturized or hidden.
Another way to do this that for sure would keep the shadow would be to use two windows and make one a child to the other.
You will not ever be able to draw outside of a window for various reasons, not the least of which being your process needs to own or have permission for what it draws to (many other reasons too).

UIButton does not remove target for UIControlEventtouchDragInside

having some problems with removing targets from UIButton. Basically I have a calendar and want to be able to move a button representing an event saved in the calendar around. I start with:
[self.chosenButton addTarget:self action:#selector(dragMoving:withEvent:) forControlEvents:UIControlEventTouchDragInside];
and then after the moving is done I call
[self.chosenButton removeTarget:nil action:NULL forControlEvents:UIControlEventTouchDragInside];
After that, however, I can still move the button around even though it should remain still. In the dragMoving:withEvent: function I only assign the coordinates of the button depending on the touch point and check its validity (if it is within the screen, etc.)
Any idea why is the dragMoving:WithEvent still being called?
Thanks
It's because you actually do not remove target, try:
[self.chosenButton removeTarget:self action:#selector(dragMoving:withEvent:) forControlEvents:UIControlEventTouchDragInside];

How to disable touch detection on a UIImage?

I am working on an app, which actually works like MSPaint (something to draw lines, etc...).
I got a white UIView, basically where the user draws. On top of this UIView I set up a UIImage, which is gray, with a 0,4 alpha. I want this UIImage to be used as a blotting paper. The idea is to disable touch when the user put the palm of his hand on this area, so it's more comfortable to draw (multitouch is disabled, and with this "blotting paper" you won't draw something accidentally with your palm...)
Even if I bring the UIImage to the front, on top of the view, and even if I disable user interactions on this UIImage, it is still possible to draw on the UIView. , behind the UIImage (kind of strange!)
I do not understand what's happening, because, it seems that the image is transparent, and that the UIView "behind" is still active, even if she's overlaid by the UIImage?!
Any help/indication/idea would be much appreciated! Thank you :-)
Have you set the "userInteractionEnabled" property of the UIImage to "NO" ?
You may actually want to do the opposite. When you disable user interaction or touches, the view basically becomes invisible to touches and they are passed on to the next view.
In your case you do want userInteractionEnabled because you want the view to catch those touches.
You have to disable the user interaction on the UIImageView not the UIImage and it should work.
Edit:
Or you could be sneaky and just add an empty view over it. Use the same frame size so it overlaps perfectly and thats it. You'll be able to see everything you need and it's not a subview of it so there will eb no interaction and touches will get registered but won't have any effect. :P
No better ideas unless you post some of your code...
OK, so I managed to do what I wanted to! YAY!
I got 3 different classes :
StrokesViewController (UIViewController)-the view controller
StrokesView (UIView) - the view where the user draws the strokes.
BlottingPaper (UIView) - the blotting paper.
I got a XIB file "linked" to all three.
I created this new class, called "BlottingPaper", typed UIView. the .h and .m file are actually empty (I do import #import < Foundation/Foundation.h >)
User interaction is enable on BlottingPaper.
I do not use the exclusive touch on this class.
On the XIB file, I just put a view on top of StrokesView. I link it to BlottingPaper (modify the alpha as I want, blablabla...)
And that's it! When I put the palm of my hand on it, it doesn't draw anything on the area where my hand is, but I still can draw with my finger on the rest of the StrokesView!
In addition to Dancreek's response, you should be setting buvard.userInteractionEnabled = YES; so that it captures interaction.
You should also set buvard.exclusiveTouch = YES; so that buvard is the only view which will receive touch events.
When you remove buvard you should set buvard.exclusiveTouch = NO; so that other views will regain their ability to receive touches.

Draw NSImage while space switching?

Currently in my project i've a simple nsimage which is updated via drawRect function.
I need to change the nsimage when the user switches between spaces... so i set my new image and called setNeedsDisplay when the NSWorkspaceActiveSpaceDidChangeNotification triggers.
The problem is that the drawRect method seems to be called to late... in other words, the previous image appears briefly before the new one. Is there any way to run the drawRect method while the transition between spaces is running? or any other way to accomplish the desired effect?
Thanks

Cause UIScrollView zoomToRect: to only display a portion

I have a UIScrollView subclass that contains a UIImageView. When the user double taps on the zone I want to zoom to that CGRect (calculated from CGPoint) and "hide" the rest of the UIImageView. The final effect is similar in Mavel.app and The Walking Dead.app when you are reading a comic.
Until now I got:
-(void)presentRect:(CGRect)rect {
self.bounds = originalFrame; //1
[UIView beginAnimations:#"navigateToPos" context:nil];
[self zoomToRect:rect animated:NO];
self.bounds = rect;
[UIView commitAnimations];
}
This works, but "zoomToRect" needs the whole bounds of the UIScrollView and when I restart it (line 1), it gives an undesired effect.
I am stuck with this. I don't know if I need a new approach or need to use another property of UIScrollView.
Any help is appreciated. Thanks.
I downloaded this apps to see it. I'm almost sure they didn't even use uiscrollview. The way the pages moves make me think about that. And uiscrollview should be used only when you really need it, because it have a lot issues when you're customizing. (tiled content, zooming and others problems).
Slide to a next page only 50px aprox., the page goes to the next, in uiscrollview it didn't happen because it works diff.
As I said before, probably it's made using 4 bars (as you correct me) or it can be done with a view wrapping the uiimage and working as a mask. You only need calculate the size of the zoom square and move it to center, and resize the wrapper view to fit this new size. The substitute for the uiscrollview for pages can be a simple image gallery, but where is images you put this "comic-view".
I've solved using other properies from UIScrollView simulating the desired effect.