Make an UIImageView Fullscreen - ios

I'm trying to make an image go full screen on tap, which doesn't sound so complicated.
This it currently doing the work after the tap is detected:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (self.contentView.frame.origin.y >= 0 && CGRectContainsPoint(self.bottleImageView.frame, touchLocation)) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[bottleImageView setFrame:[[UIScreen mainScreen] bounds]];
bottleImageView.backgroundColor = [UIColor blackColor];
}completion:^(BOOL finished){}];
...
}
There's a problem though. I need to bring the UIImageView to the front, so that it draws the image in front of the other views. When I add in [self.view bringSubviewToFront:bottleImageView]; to the mix (either before the animation block, in the completion block, or after this code), things change. On the first tap, the UIImageView background changes to black, and on the second tap the view expands to full screen.
I'm sure it's just something small and dumb that I've overlooked.
EDIT: I've added the touch code
EDIT (2): I may have missed some vital information. I thought I'd try auto layout for this project. I'm guessing there's something there that's not letting everything work as intended?

You can use MHFacebookImageViewer
for this purpose. It is very simple to use.

Perhaps you have the wrong view content mode, add this line to where after the image is being set:
bottleImageView.contentMode = UIViewContentModeScaleAspectFit;

OK. The code above is fine for expanding a view.
I found there was a problem with the Autolayout restraints. I couldn't tell you exactly what I changed that fixed the problem - but a few hours debugging restraints solved the issue.
I found a much better solution however - Facebook POP works much better, and looks a lot slicker.

Add
[self.view bringSubviewToFront:bottleImageView]
immediately after you add
[self.view addSubview:bottleImageView]

Related

Animations not visible until another function is triggered

I have implemented the drag and drop functionality using
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
In the touchesBegan I check if the according image on the screen was hit, I make a copy of it on the same exact place and start resizing it using the following code :
[UIView animateWithDuration:1.0f
animations:^{
CGRect oldFrame = copy.frame;
copy.frame = CGRectMake(oldFrame.origin.x,oldFrame.origin.y, oldFrame.size.width+60, oldFrame.size.height+60);
}
completion:^(BOOL finished){
}];
The problem that I am getting is that the animations are not actually visible until touchesMoved is triggered. In other words if I press the image and there is no move recorded for more then 1s nothing happens during this time, but if I suddenly move the finger I already see the resized image, but if I start moving in less then 1s I see how the image gets resized in the way while I drag it.
How should I change the code such that the image get's resized even if touchesMoved is not triggered?
Edits:
the only code triggered in touchesMoved is :
CGPoint newPoint = [[touches anyObject] locationInView:self.view];
[copy setCenter:newPoint];
This seemed to work for me (in an example that wasn't using touches, however).
CGRect oldFrame = copy.frame;
oldFrame = CGRectMake(oldFrame.origin.x,oldFrame.origin.y, oldFrame.size.width+60, oldFrame.size.height+60);
[copy layoutIfNeeded];
[UIView animateWithDuration:1.0f animations:^{
copy.frame = oldFrame;
}];
The key is to use layoutIfNeeded for animations that don't seem to be animating. If you're using autolayout, this thread might be more useful:
Are NSLayoutConstraints animatable?
My solution was to add a dummy method that is being called at the end of touchesBegan. This removed the problem I was having and the animation was visible before the touchesMoved was triggered.

Setting UIView position and size

When creating a new UIView or panning/swiping a view to a new position, whats the proper way of setting the new position and size. Currently, to move views resulting from a pan/swipe action, I'm using ratios based on the original position of the view that I'm moving and its relation to other views and items (navigation bar).
When moving a view due to a swipe I do the following:
CGFloat swipeUpDelta = -1 *(self.view.bounds.size.height - (self.view.bounds.size.height - recordView.frame.origin.y) - (self.navigationController.navigationBar.bounds.size.height + ([UIApplication sharedApplication].statusBarFrame.size.height)));
[UIView animateWithDuration:.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
recordView.frame = CGRectOffset(recordView.frame, 0, swipeUpDelta);
} completion:nil];
Or creating a view that renders a sineWave across my viewcontroller:
self.sineWave = [[OSDrawWave alloc] initWithFrame:CGRectMake(-1*self.view.bounds.size.width, (.75*self.view.bounds.size.height), 2*self.view.bounds.size.width, .3125*(2*self.view.bounds.size.width))];
Everything works fine, but I wanted to know if there is a better way of doing these things.
I'm not sure I understand the question. initWithFrame: or myView.frame is considered the correct way of positioning a UIView. Using animateWithDuration: with a new frame size is also pretty standard.
I'm unsure of what you mean as well. When you move a UIView you can move the view a variety of ways, it depends on your code and what you want out of it. The below is a valid example of code to move a CALayer inside of a UIView to follow touch positions. You can use this, you can animate your view, you can use explicit animations when changing the position of the layer or center of the view (By default iOS animates any changed property values of a CALayer... you can ride off of this and enable this feature for UIViews if you please). If you're moving a UIView, it's a good idea to move the view according to the center property. This is pretty much how SpriteKit works and any high functioning animation engine (avoid always resetting the frame... especially if you don't need to).
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
boxLayer.position = p;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
[CATransaction begin];
[CATransaction setDisableActions:YES];
boxLayer.position = p;
[CATransaction commit];
}
As a note, note the comment in the following line of code
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
/*UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self]; // this causes the animations to appear sluggish as there is a consistant change in destination location. The above code corrects this.
[boxLayer setPosition:p];*/
This is valid, and may provide the results you want... it all depends on what you want.

uiimageview refreshing all other imageviews

I'm making an iphone app and I made a method that creates a new UIImageView programmatically and it's working great (well.. somewhat great) BUT obviously theres an issue.
Whenever the method gets called, every other UIImageView that I created in the storyboard gets refreshed, meaning, they all get placed back to where I placed them originally on the storyboard (they're supposed to be moving randomly)
heres the method
- (UIImageView *)shootNewBullet {
UIImageView *newBullet = [[UIImageView alloc] initWithFrame:CGRectMake(80, playerShip.center.y,15,3)];
newBullet.Image=[UIImage imageNamed: #"bullet2.png"];
newBullet.hidden = NO;
[bulletArray addObject:newBullet];
[self.view addSubview:newBullet];
return newBullet;
}
heres where the method gets called
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
if (point.x > 101) {
bullets = [self shootNewBullet];
}
}
if more code is necessary to give good answers please let me know
This is probably a consequence of using auto layout (you can turn that off in IB to see if this is the problem). When using auto layout, you shouldn't set any frames. If you do, as soon as the view needs to be redrawn, all frames will be reset to the frames defined by the constraints. If you want to leave auto layout turned on, then you should do any changing of size or position by modifying the constraints rather than directly setting frames.

Objective C iPhone programming a dot or shape to follow your cursor

How would I create a program so a dot starts in the center, and when I click the screen the dot follows where I clicked? Not as in teleports to it, I mean like changes it's coordinates towards it slightly every click. I get how I could do it in theory, as in like
if (mouseIsClicked) {
[mouseX moveX];
[mouseY moveY];
}
And make the class that mouseX and mouseY are have some methods to move closer to where the mouse is, but I just don't know any specifics to actually make it happen. Heck, I don't even know how to generate a dot in the first place! None of those guides are helping at all. I really want to learn this language though. I've been sitting at my mac messing around trying to get anything to work, but nothing's working anywhere near how I want it to.
Thanks for helping a total newbie like me.
If you are going to subclass UIView, you can use the touchesBegan/touchesMoved/touchesEnded methods to accomplish this. Something like:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
//slightly update location of your object with p.x and p.y cgpoints
[self setNeedsDisplay];
}
-(void)drawRect{
//draw your object with updated coordinates
}
You can create a dot and move it around based on taps all within your UIViewController subclass.
Make your dot by creating a UIView configured to draw the way you want - look into CALayer and setting dotview.layer.cornerRadius to make it be round (alternately you can make a UIView subclass that overrides drawRect: to make the right CoreGraphics calls to draw what you want). Set dotview.center to position it.
Create a UITapGestureRecognizer with an action method in your view controller that updates dotview.center as desired. If you want it animated, simply set the property within a view animation call & animation block like this:
[UIView animateWithDuration:0.3 animations:^{
dotview.center = newposition;
}];
You can download the sample code here that will show you general iOS gestures. In particular it has a sample that shows how to drag and drop UIViews or how to swipe them around. The sample code includes both driven and fire-n-forget animations. Check it out, its commented and I'd be happy to answer any specific questions you have after reviewing the code.
Generating a simple circle
// Above Implementation
#import <QuartzCore/QuartzCore.h>
// In viewDidLoad or somewhere
UIView *circleView = [[UIView alloc] initWithFrame:CGRectMake(32.0, 32.0, 64.0, 64.0)];
[circleView setBackgroundColor:[UIColor redColor]];
[circleView.layer setCornerRadius:32.0];
self.view addSubview:circleView];

CGRectContainsPoint for a UIButton during animation

I am creating a UIButton that follows the UITouch point, I want that when I Keep pressing the touch and the animation boundaries reach my touch point I perform some activity there.
Following is the code.
I am always getting x,y 0 for the UIButton.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[UIView beginAnimations:#"MoveAndStrech" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationBeginsFromCurrentState:YES];
if([touches count] == 1) {
UITouch *touch = [touches anyObject];
self.uiButton.center = [touch locationInView:self.view];
}
[UIView commitAnimations];
UITouch *touchTemp = [touches anyObject];
CGPoint pCurrent = [touchTemp locationInView:self.view];
CGRect currentRect = self.uiButton.layer.bounds;
NSLog(#"Current Rect x:%f,Current y:%f",
currentRect.origin.x,
currentRect.origin.y);
NSLog(#"TouchPoint x:%f,TouchPoint y:%f",
pCurrent.x,
pCurrent.y);
if(CGRectContainsPoint(currentRect, pCurrent)) {
NSLog(#"Touched....in rect");
}
}
Regards
Sara
Replace
CGRect currentRect = self.uiButton.layer.bounds;
with
CGRect currentRect = self.uiButton.frame;
If that doesn't work, then
CGRect currentRect = self.uiButton.presentationLayer.frame;
Also, why aren't you using UIView animation blocks? It'd make your life much easier and your code much cleaner.
Several things. At first I thought you were missing the call to commitAnimations.
DO NOT PUT MULTIPLE STATEMENTS ON THE SAME LINE!!!! That is a very nasty coding habit that makes your code all but impossible to read.
Next, the old style beginAnimations/commitAnimations calls are outdated, and should not be used in iOS 4 or later. To quote the docs of beginAnimations:context:
Use of this method is discouraged in iOS 4.0 and later. You should use
the block-based animation methods to specify your animations instead.
You should be using the new block-based animation calls (of the form (animateWithDuration:animations:)
Next, UIView animations cause the object being animated to move to it's final location instantly. They only LOOK LIKE they are moving to their final location over time. They also disable user interaction during animations by default.
If you want to figure out where the view appears on the screen at any given moment then you need to check the view's layer's animationLayer. I have a sample project on Github (link) that includes a UIView animation of an image where you can tap on the image and the animation stops. This sample project shows how to use the view's layer's animation layer to figure out where the animation is located at the instant the user taps the screen.
If you want code that does something when the animated view gets to a certain point it would be more tricky. You might need to attach a CADisplayLink to your view (which will be called on each screen refresh) and use that to check the position of your animation and compare it to the current touch location.

Resources