Image magnification techniques, clarification needed - ios

Before i start reinventing the wheel, i thought i'd check here to see if there are known image magnification techniques people know and love?
I am thinking .. for each image, on finger tap, i'd pop up an enlarged version of the same image (part of probably). Can i get away with a single image (and actually magnify it) or should i just swap images as user moves his/her finger?
Does this sound reasonable or, is this too much of a brute force approach?

From what I understand of your question - you want to tap on a thumbnail and it transitions to the full size/ larger size.
Best way of the top of my head would be to have a UIImageview with it's content mode set to UIViewContentModeAspectFill.
add the image view with CGSize of say 50X50 -- then add a UITapGestureRecogniser on it that triggers a function that does something like this:
- (void)tapped:(id)sender{
UIImageView *v = [(UITapGestureRecognizer *)sender view];
CGRect f = [v frame];
f.size = CGSizeMake(200,200);//or whatever size
[UIView animateWithDuration:0.25f
animations:^(){
[v setFrame:f];
}];
}
hope this helps
Cheers,
Michael

Related

How to pinch to zoom a view without making the view bigger?

This is what I currently have:
func handlePinching(recognizer : UIPinchGestureRecognizer) {
self.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformScale(self.transform, recognizer.scale, recognizer.scale));
recognizer.scale = 1.0;
}
Using self.view.transform for that also makes it bigger. I want to make it zoom "internally" (I really don't know how to explain it).
So I'm not 100% sure to understand the question but I guess I get it.
For example you want to zoom on an image without zooming the other element of the UI (NavBar, Buttons, ...) right?
So I guess in you're example you're in a viewController, which means, when you change the scale of self.view you'll zoom everything. You have to apply the scale on the specific view that you want to zoom in.
In the example below, to zoom on the image, the image is inside of an UIImageView, and this imageView is subView of self.view. And you will just apply a transform on this imageView.
Moreover I think you get a little bit confused on how to zoom, considering the view you want to zoom is imageView you just need to do
imageView.transform = CGAffineTransformMakeScale(recognizer.scale,recognizer.scale)
I hope this answer your question, let me know if something is not clear.

UIPageViewController with UISlider inside controller - increase hit area of slider

I have multiple controllers in my PageViewController and in one controller I have a few sliders. Now there is a problem that user must touch exactly slider circle (I am not sure about right expression, thumb? - that moving part) and I would like to increase area in which reacts slider and not the whole PageViewController. I tried these solutions but it doesn't help:
thumbRectForBounds:
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
return CGRectInset ([super thumbRectForBounds:bounds trackRect:rect value:value], 15, 15);
}
Increase hitTest area:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point) || CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point)) {
return self;
}
return [super hitTest:point withEvent:event];
}
I have these methods in my custom slider class because I would like to reuse this. Last thing what I found and not tried yet is create some object layer over slider which "takes" gesture and disable PageViewController but I am not sure how to do it and I am not sure if it's good/best solution.
I am not a big fan of the UISlider component because as you noticed, it is not trivial to increase the hit area of the actual slider. I would urge you to replicate the UISlider instead using a pan gesture for a much better user experience:
i. create a slider background with a seperate UIImageView with a slider image.
ii. create the PanGesture:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:);
[imageView addGestureRecognizer:pan];
iii. implement handlePan Method:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
//pan (slide) begins
CGPoint translation = [recognizer locationInView:self.view];
translation.y = self.slideImage.center.y;
self.slideImage.center = translation;
if(recognizer.state == UIGestureRecognizerStateEnded) {
LTDebugLog(#"\n\n PAN, with spot: %f\n\n", self.slideImage.center.x);
//do something after user is done sliding
}
}
The big benefit of this method is that you will have a much better user experience as you can make the responsive UIImageView as big as you want.
Alternatively, you could subclass a UISlider and increase the hit space there, although in my experience this gives mixed results.
Hope this helps
In your CustomSlider class override thumbRectForBounds method:
Simply return rect value as you required:
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
return CGRectMake (bounds.origin.x, bounds.origin.y, yourWidthValue, yourHeightValue );
}
Change yourWidthValue and yourHeightValue as per your requirement. And then while using
Create object like below:
CustomSlider *slider = [[CustomSlider alloc] initWithFrame:CGRectMake(0, 0, 300, 20)];
[slider thumbRectForBounds: slider.bounds trackRect:slider.frame value:15.f]; // change values as per your requirements.
Hope this helps.
Create a custom thumb image which has a large empty margin and set that on your slider, like this:
[theSlider setThumbImage:[UIImage imageNamed:#"slider_thumb_with_margins"] forState:UIControlStateNormal];
To make the image, get a copy of the system thumb image using any one of a number of UIKit artwork extractors (just search the web for one). Open the thumb image in Photoshop and increase the canvas size by twice the margin you want to add. Make sure you change the canvas size and not the image size, as the image size will stretch the image to fill the new size. This will put empty space around the thumb which will be part of the hit-test area but since it is all transparent it won't change the look of the slider.

IOS core animation for zoom in and zoom out

I am working a pictureView which needs to be zoom in and zoom out on tap,
I have searched for the proper zoom in and zoom out, but not found (I have tried to achieve same task with UIView but its not good), so i came to ask if any body can help ?
I have 4 images assembled in a tableview, 2 in a row.
What i want is if user taps an image, it just zoom in and if he taps again it should zoom out.
Following is the code sample i have tried so far
[UIView animateWithDuration:1.0f animations:^{
img.frame = CGRectMake(0, 0, 300, 300);
img.alpha = 1.0;
}];
but when ever i try to use that, instead of zooming in, it translates from one of the 4 diagonals :( I hope I have cleared this question as possible as I can.
Regards
You need to add tap gesture recognizer for each UIImageView you are adding to the cells.
You need to have hidden UIImageView to show when user taps the image.
Here is what you do on tap:
2.1 Assign image to your hidden UIImageView, set its alpha to 0.0 and make it not hidden
2.2 Set proper frame to the hidden image view.
2.3 animate the reveal of the image like
[UIView animateWithDuration:1.0f animations:^{
img.frame = CGRectMake(0, 0, 300, 300);
img.alpha = 1.0;
}];
2.4 add tap gesture recognizer to your hidden image view in order to dismiss it when user taps.
2.5 make reverse animation when user taps e.g. set alpha of displayed image view to 0.0 in uiview animation block.
I didn't provide the code for the whole thing assuming that you will learn and remember such things.
Good Luck!
EDIT: don't forget to add hidden uiimageview to your view.

resizing a UIControl in an animated fashion

I have created a button which I want to expand/contract. I found a way to get the x,y coordinates along with width and height. Using these I call CGRectMake function to redraw the button. I am trying to figure out how to redraw in an animated fashion. Below is my attempt but I am almost sure that there are better ways of doing this. Any comments?
pointX = navigateBtn.frame.origin.x;
pointY = navigateBtn.frame.origin.y;
height = CGRectGetHeight(navigateBtn.frame);
width = CGRectGetWidth(navigateBtn.frame);
for (int i=1;i<=800000;i++) {
int k=i/100000;
navigateBtn.frame=CGRectMake(pointX, pointY, width, height*k);
}
Thanks in advance.
All you need to know is what the destination rect will be and then you can animate like this
[UIView animateWithDuration:0.25f
animations:^{
navigateBtn.frame = endFrame;
}];
No. Don't try to animate things yourself.
Use UIView animation. A good tutorial is available from Ray Wenderlich: http://www.raywenderlich.com/2454/how-to-use-uiview-animation-tutorial
But to be perfectly honest you should probably start with an introductory iOS programming book. The way you phrased your question makes me think that you still have a lot of fundamentals to learn.

Rotate UIView based on UITouch

I'm working on a drawing app.
I want the user to be able to "drop" a shape on the screen and then move, resize or rotate it as desired.
The problem is with the rotation. I have the moving and resizing working fine.
I did this before with a rather complex and memory/processor-intensive process, which I am now trying to improve.
I've searched and searched but haven't found an answer similar to what I'm trying to do.
Basically, let's say the user drops a square on the "surface". Then, they tap it and get some handles. They can touch anywhere and pan to move the square around (working already), touch and drag on a resize handle to resize the square (working already), or grab the rotation handle to have the square rotate around its center.
I've looked into drawing the square using UIBezierPath or just having it be a subclass of UIView that I fill.
In either case, I'm trying to rotate the UIView itself, not some contents inside. Every time I try to rotate the view, either nothing happens, the view vacates the screen or it rotates just a little bit and stops.
Here's some of the code I've tried (this doesn't work, and I've tried a lot of different approaches to this):
- (void) rotateByAngle:(CGFloat)angle
{
CGPoint cntr = [self center];
CGAffineTransform move = CGAffineTransformMakeTranslation(-1 * cntr.x, -1 * cntr.y);
[[self path] applyTransform:move];
CGAffineTransform rotate = CGAffineTransformMakeRotation(angle * M_PI / 180.0);
[[self path] applyTransform:rotate];
[self setNeedsDisplay];
CGAffineTransform moveback = CGAffineTransformMakeTranslation(cntr.x, cntr.y);
[[self path] applyTransform:moveback];
}
In case it isn't obvious, the thinking here it to move the view to the origin (0,0), rotate around that point and then move it back.
In case you're wondering, "angle" is calculated correctly. I've also wrapped the code above in a [UIView beginAnimations:nil context:NULL]/[UIView commitAnimations] block.
Is it possible to rotate a UIView a "custom" amount? I've seen/done it before where I animate a control to spin, but in those examples, the control always ended up "square" (i.e., it rotated 1 or more full circles and came back to its starting orientation).
Is it possible to perform this rotation "real-time" in response to UITouches? Do I need to draw the square as an item in the layer of the UIView and rotate the layer instead?
Just so you know, what I had working before was a shape drawn by a set of lines or UIBezierPaths. I would apply a CGAffineTransform to the data and then call the drawRect: method, which would re-draw the object inside of a custom UIView. This UIView would host quite a number of these items, all of which would need to be re-drawn anytime one of them needed it.
So, I'm trying to make the app more performant by creating a bunch of UIView subclasses, which will only get a command to re-draw when the user does something with them. Apple's Keynote for the iPad seems to accomplish this using UIGestureRecognizers, since you have to use two fingers to rotate an added shape. Is this the way to go?
Thoughts?
Thanks!
-(void)rotate{
CGAffineTransform transform;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationOptionBeginFromCurrentState];
myView.alpha = 1;
transform = CGAffineTransformRotate(myView.transform,0.5*M_PI);
[myView setUserInteractionEnabled:YES];
myView.transform = transform;
[UIView commitAnimations];
}
This might help.
for just simple rotation you might leave out the Animation:
-(void)rotate:(CGFloat)angle
{
CGAffineTransform transform = CGAffineTransformRotate( myView.transform, angle * M_PI / 180.0 );
myView.transform = transform;
}
I use a simple NSTimer to control a animation.

Resources