This is what I got but I am getting errors as you see in the picture.
I have the IBOutlets for UIImageView *bottomGroundContinue and one for *bottomGround
#implementation viewController
#property (nonatomic, assign) BOOL keepGoing;
#property (nonatomic, strong) UIImageView *bottomGround;
#property (nonatomic, strong) UIImageView *bottomGroundContinue;
- (void)getReady {
UIImage *theImage = [UIImage imageNamed:#"bottomGround.png"];
self.bottomGround = [[UIImageView alloc] initWithImage:theImage];
self.bottomGroundContinue = [[UIImageView alloc] initWithImage:theImage];
self.bottomGround.frame = self.view.bounds;
self.bottomGRoundContinue.frame = CGRectOffset(self.view.bounds, self.bottomGround.bounds.size.width, 0.0);
[self.view addSubview:self.bottomGround];
[self.view addSubview:self.bottomGroundContinue];
self.keepGoing = YES;
}
- (void)go {
CGFloat width = self.bottomGround.bounds.size.width;
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
self.bottomGround.frame = CGRectOffset(self.bottomGround.frame, -width, 0);
self.bottomGroundContinue.frame = CGRectOffset(self.bottomGroundContinue.frame, -width, 0);
} completion:^(BOOL finished) {
if (self.keepGoing) {
// now B is where A began, so swap them and reposition B
UIImageView *temp = self.bottomGround;
self.bottomGround = self.bottomGroundContinue;
self.bottomGroundContinue = temp;
self.bottomGroundContinue.frame = CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0.0);
// recursive call, but we don't want to wind up the stack
[self performSelector:#selector(go) withObject:nil afterDelay:0.0];
}
}];
}
You are declaring properties inside of #implementation. You need to declare them inside of #interface.
Related
I have a UIImageView and a UIView (filled with smaller imageviews) all placed in a UIScrollView (for zooming).
To better help you understand, I have a map (ImageView) with fog(UIView with smaller imageviews) in the scrollview so I can zoom the map.
If I add the mapview and fogview to the self.view then the application works as it should, touching the fog at a point removes that fog image.
However, when I add the map and fog views to the scrollview nothing responds to touches.
I ultimately want the default behavior to be touching fog view will remove the fog at one point. Unless the user presses a button to zoom/pinch the view, which will zoom both the mapview and fogview.
The problem below is no touches are processed when I add the mapview and fogview to the scrollview. Currently there is no ability to press a button to pinch/zoom as I still don't have the default behavior I want.
Any help?
#interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIActionSheetDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate>{
UIImage * fogImage;
NSUserDefaults * defaults;
bool canZoom;
}
#property (weak, nonatomic) IBOutlet UIButton *btnTakePicture;
#property (strong, nonatomic) UIButton * btnMenu;
#property (strong, nonatomic) UIButton * btnZoom;
#property (strong, nonatomic) UIScrollView* scrollView;
#property (strong, nonatomic) UIImageView *mapView;
#property (strong, nonatomic) UIView * fogView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
fogImage = [UIImage imageNamed:#"fog1.jpg"];
self.mapView = [[UIImageView alloc] initWithFrame:CGRectZero];
self.fogView = [[UIView alloc] initWithFrame:CGRectZero];
_scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
_scrollView.delegate = self;
_scrollView.minimumZoomScale = 0.75;
_scrollView.maximumZoomScale = 3.0;
[_scrollView addSubview:self.mapView];
[_scrollView addSubview:self.fogView];
[self.view addSubview:_scrollView];
self.mapView.hidden = YES;
self.fogView.hidden = YES;
self.scrollView.hidden = YES;
defaults = [NSUserDefaults standardUserDefaults];
canZoom = false;
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.mapView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.fogView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
- (void) zoom:(id)sender{
canZoom = !canZoom;
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
self.btnTakePicture.hidden = YES;
self.btnMenu.hidden = NO;
self.btnZoom.hidden = NO;
[picker dismissViewControllerAnimated:YES completion:^(void) {
[self fillScreenWithFog];
self.mapView.image = chosenImage;
self.mapView.contentMode = UIViewContentModeScaleAspectFit;
self.mapView.hidden = NO;
self.fogView.hidden = NO;
_scrollView.hidden = NO;
_scrollView.userInteractionEnabled = YES;
self.scrollView.contentSize = self.mapView.frame.size;
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#pragma mark Fog Maker
- (void) removeFogAtPoint:(CGPoint)point{
NSLog(#"removeFogAtPoint %#", NSStringFromCGPoint(point));
CGRect fingerRect = CGRectMake(point.x - 5, point.y-5, 10, 10);
for(UIImageView *view in self.fogView.subviews){
CGRect subviewFrame = view.frame;
if(CGRectIntersectsRect(fingerRect, subviewFrame)){
[UIView animateWithDuration:1.25
animations:^{
view.alpha = 0;
}
completion:^(BOOL finished){
[view removeFromSuperview];
}];
}
}
}
- (void) fillScreenWithFog {
// do a loop to fill the screen with fog getNewSquare
}
- (UIImageView*) getNewSquare:(CGRect)frame withTag:(int)tag{
UIImageView * imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = fogImage;
imageView.contentMode = UIViewContentModeScaleAspectFill;
return imageView;
}
-(void) touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(#"Touches Moved");
CGPoint location = [[touches anyObject] locationInView:self.scrollView];
[self removeFogAtPoint:location];
}
#end
I have a custom alterviewcontroller which subclasses UIViewController. It works great in apps that are portrait, but in landscape, it's running into issues with the frame orientation. I've tried a bunch of fixes, but none seem to be getting it right.
In the current version, it displays correctly but the main view is the wrong size, so the buttons that are outside of that view are not clickable.
In this image, the Next Turn button is not Clickable, the Go to Black button is. This is landscape left.
.h file
#import <UIKit/UIKit.h>
#import "SPRTitleFontLabel.h"
#protocol SPRAlertViewControllerDelegate;
#interface SPRAlertViewController : UIViewController
#property (nonatomic, weak) id <SPRAlertViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UIView *alertview;
#property (weak, nonatomic) IBOutlet SPRTitleFontLabel *titleLabel;
#property (weak, nonatomic) IBOutlet UITextView *messageLabel;
#property (weak, nonatomic) IBOutlet UIButton *yesButton;
#property (weak, nonatomic) IBOutlet UIButton *noButton;
#property (weak, nonatomic) IBOutlet UIButton *okButton;
#property int tag;
-(void)setTitle:(NSString *)title message:(NSString *)message andButtonCount:(int)buttonCount;
- (IBAction)doDismiss:(id)sender;
- (void)show;
#end
#protocol SPRAlertViewControllerDelegate <NSObject>
- (void)alert:(SPRAlertViewController *)alert didDismissWithButtonClick:(int)buttonIndex;
#end
.m file
#import "SPRAlertViewController.h"
#import "SPRAudioHelper.h"
#interface SPRAlertViewController ()
{
UIWindow *alertWindow;
}
#end
#implementation SPRAlertViewController
+(instancetype)new
{
SPRAlertViewController *alvc = [super new];
return alvc;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
alertWindow = [self windowWithLevel:UIWindowLevelAlert];
if (!alertWindow)
{
//rotate the window frame to get the right orientation
CGRect tempFrame = [UIScreen mainScreen].bounds;
CGRect tempFrame2 = tempFrame;
tempFrame2.size.height = tempFrame.size.width;
tempFrame2.size.width = tempFrame.size.height;
alertWindow = [[UIWindow alloc] initWithFrame:tempFrame2];
alertWindow.windowLevel = UIWindowLevelAlert;
[alertWindow makeKeyAndVisible];
NSLog(#"window frame %#", NSStringFromCGRect(alertWindow.frame));
}
alertWindow.rootViewController = self;
}
return self;
}
- (void)setTitle:(NSString *)title message:(NSString *)message andButtonCount:(int)buttonCount
{
self.titleLabel.text = title;
self.messageLabel.text = message;
if (buttonCount == 1)
{
self.yesButton.hidden = YES;
self.noButton.hidden = YES;
self.okButton.hidden = NO;
}
else
{
self.yesButton.hidden = NO;
self.noButton.hidden = NO;
self.okButton.hidden = YES;
}
CGRect frame = self.messageLabel.frame;
CGSize size = [self.messageLabel sizeThatFits:CGSizeMake(self.messageLabel.frame.size.width, FLT_MAX)];
frame.size.height = size.height;
self.messageLabel.frame = frame;
[self.messageLabel setNeedsDisplay];
float buttonTop = frame.size.height + frame.origin.y;
self.yesButton.frame = CGRectMake(self.yesButton.frame.origin.x, buttonTop, self.yesButton.frame.size.width, self.yesButton.frame.size.height);
self.noButton.frame = CGRectMake(self.noButton.frame.origin.x, buttonTop, self.noButton.frame.size.width, self.noButton.frame.size.height);
self.okButton.frame = CGRectMake(self.okButton.frame.origin.x, buttonTop, self.okButton.frame.size.width, self.okButton.frame.size.height);
self.alertview.frame = CGRectMake(self.alertview.frame.origin.x, self.alertview.frame.origin.y, self.alertview.frame.size.width, buttonTop+55);
NSLog(#"parent frame %#", NSStringFromCGRect(self.parentViewController.view.frame));
NSLog(#"view frame %#", NSStringFromCGRect(self.view.frame));
NSLog(#"alert frame %#", NSStringFromCGRect(self.alertview.frame));
NSLog(#"button frame %#", NSStringFromCGRect(self.yesButton.frame));
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIInterpolatingMotionEffect* m1 =
[[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.x"
type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
m1.maximumRelativeValue = #0.0;
m1.minimumRelativeValue = #0.0;
UIInterpolatingMotionEffect* m2 =
[[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.y"
type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
m2.maximumRelativeValue = #20.0;
m2.minimumRelativeValue = #-20.0;
UIMotionEffectGroup* g = [UIMotionEffectGroup new];
g.motionEffects = #[m1,m2];
[self.alertview addMotionEffect:g];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)show
{
CGRect tempFrame = [UIScreen mainScreen].bounds;
CGRect tempFrame2 = tempFrame;
tempFrame2.size.height = tempFrame.size.width;
tempFrame2.size.width = tempFrame.size.height;
self.alertview.center = CGPointMake(CGRectGetMidX(tempFrame2), CGRectGetMidY(tempFrame2));
self.alertview.transform = CGAffineTransformMakeScale(1,1.6);
self.alertview.alpha = 0;
self.view.alpha = 0;
[UIView animateWithDuration:0.1 animations:^{
self.view.alpha = 1;
}
completion:
^(BOOL finished){
[UIView animateWithDuration:0.25 animations:^{
self.alertview.alpha = 1;
self.alertview.transform = CGAffineTransformIdentity;
}];
}
];
}
- (UIWindow *)windowWithLevel:(UIWindowLevel)windowLevel
{
NSArray *windows = [[UIApplication sharedApplication] windows];
for (UIWindow *window in windows) {
if (window.windowLevel == windowLevel) {
return window;
}
}
return nil;
}
- (IBAction)doDismiss:(id)sender
{
// [[SPRAudioHelper sharedHelper] playSoundFromTag:lightClick];
NSLog(#"check");
[UIView animateWithDuration:0.25 animations:^{
self.alertview.transform = CGAffineTransformScale(self.alertview.transform, 1,0.5);
self.alertview.alpha = 0;
}completion:^(BOOL finished)
{
[UIView animateWithDuration:0.1 animations:^{
self.view.alpha = 0;
}completion:^(BOOL finished)
{
[alertWindow removeFromSuperview];
alertWindow = nil;
if (sender == self.yesButton)
[self.delegate alert:self didDismissWithButtonClick:1];
else
[self.delegate alert:self didDismissWithButtonClick:0];
}];
}];
}
#end
Here's the NSLog results:
2014-07-10 10:59:18.603 Damage Report Timer[5166:60b] window frame {{0, 0}, {568, 320}}
2014-07-10 10:59:18.720 Damage Report Timer[5166:60b] parent frame {{0, 0}, {0, 0}}
2014-07-10 10:59:18.722 Damage Report Timer[5166:60b] view frame {{0, 0}, {320, 568}}
2014-07-10 10:59:18.724 Damage Report Timer[5166:60b] alert frame {{0,51}, {568, 146.5}}
2014-07-10 10:59:18.726 Damage Report Timer[5166:60b] button frame {{101, 91.5}, {150, 50}}
I figured it out after doing more and more digging. I was really making the whole thing way more complicated than it is. 2 functions needed to be fixed, here's the updated functions:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
alertWindow = [self windowWithLevel:UIWindowLevelAlert];
if (!alertWindow)
{
alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
alertWindow.windowLevel = UIWindowLevelAlert;
[alertWindow makeKeyAndVisible];
}
alertWindow.rootViewController = self;
}
return self;
}
and
- (void)show
{
CGRect frame = self.view.bounds;
self.alertview.center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
self.alertview.transform = CGAffineTransformMakeScale(1,1.6);
self.alertview.alpha = 0;
self.view.alpha = 0;
[UIView animateWithDuration:0.1 animations:^{
self.view.alpha = 1;
}
completion:
^(BOOL finished){
[UIView animateWithDuration:0.25 animations:^{
self.alertview.alpha = 1;
self.alertview.transform = CGAffineTransformIdentity;
}];
}
];
}
Originally since show was centering the view on mainscreen bounds, it was putting it in the wrong place, since mainscreen bounds doesn't get updated on rotation. Then I made the mistake of resizing the window to accommodate for that. Which made buttons no longer be in the window.
I am working with images in iOS. So when a user presses let's say a button, I want an image to appear to fill up from the bottom to the top.
In order be more precise, imagine a thermometer that is empty and when you press a button the thermometer fills up from the bottom to the top. But I want this with animation.
Do you have any idea how to implement that?
Thanks!
You can easily do it by having a second view acting as a mask over the image view with your image. Then you can apply simple scale transform and animate it revealing the image. Alternatively, you can animate the frame change. Effect will be the same. I'm attaching code for 2 ways of doind this.
Here is what I achieved in both cases:
Code I used for the case I:
#interface MyViewController ()
#property(nonatomic, strong) UIImageView *imageView;
#property(nonatomic, strong) UIView *maskView;
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Image"]];
_imageView.center = self.view.center;
_imageView.layer.anchorPoint = CGPointMake(0.5, 0.0);
[self.view addSubview:_imageView];
_maskView = [[UIView alloc] initWithFrame:_imageView.frame];
_maskView.backgroundColor = [UIColor whiteColor];
_maskView.center = self.view.center;
_maskView.layer.anchorPoint = CGPointMake(0.5, 0.0);
[self.view addSubview:_maskView];
}
- (IBAction)buttonTapped:(id)sender
{
[UIView animateWithDuration:1.0f
animations:^
{
_maskView.transform = CGAffineTransformMakeScale(1.0, 0.0001);
}];
}
#end
Code I used for the case II:
#interface MyViewController ()
#property(nonatomic, strong) UIImageView *imageView;
#property(nonatomic, assign) CGFloat height;
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Image"]];
_imageView.center = self.view.center;
_imageView.contentMode = UIViewContentModeBottom;
_height = CGRectGetHeight(_imageView.bounds);
CGRect frame = _imageView.frame;
frame.size.height = 0.00001;
frame.origin.y += _height;
_imageView.frame = frame;
_imageView.clipsToBounds = YES;
[self.view addSubview:_imageView];
}
- (IBAction)buttonTapped:(id)sender
{
[UIView animateWithDuration:1.0f
animations:^
{
CGRect frame = _imageView.frame;
frame.size.height = _height;
frame.origin.y -= _height;
_imageView.frame = frame;
}];
}
#end
In both cases the end effect was the same.
You can do this by changing the frame of the view within the animate block. For example, if myView was a 100x100 sized view:
myView.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height, 0, 0);
[UIView animateWithDuration:1.0f
animations:^
{
myView.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height, 100, 100);
}];
This example should enlarge a 100x100 view in the bottom left corner of the screen, making it appear to reveal itself from the bottom up.
I created this dialog in IB:
I set a segue the following way:
This is how I configured the ViewController:
And this is how I configured the view metrics:
Here's what I get in the iOS Simulator:
So: could somebody tell me why, how could I get this they way I visually intend to and where I could find a very good Interface builder tutorial?
Thanks in advance.
The "Form Sheet" modal presentation style always uses the same size container, and you can't override it. With iOS 7 or later, you can define a custom modal presentation style to accomplish what you want, or search GitHub.
Here's an iOS 6-compatible implementation with a custom size.
/** Created in answer to mirx's question at http://stackoverflow.com/questions/18803961/why-are-the-dimensions-of-my-modal-view-different-from-what-i-expect/18805374?noredirect=1#comment27741546_18805374 */
#interface AHPresentingViewController : UIViewController
#property (nonatomic, weak) UIView *presentedBackgroundView;
#property (nonatomic, weak) UIViewController *formController;
#end
#implementation AHPresentingViewController
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UITableViewController *table = [UITableViewController new];
table.title = #"Form";
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:table];
table.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissPresentedForm:)];
[self presentForm:nav size:CGSizeMake(320, 240)];
}
-(void)presentForm:(UIViewController *)formVC size:(CGSize)size {
if(self.formController) return;
NSLog(#"Form view: %#",formVC.view);
UIView *background;
self.presentedBackgroundView = background = [[UIView alloc] initWithFrame:self.view.bounds];
background.opaque = NO;
background.backgroundColor = [UIColor blackColor];
background.alpha = 0;
[self.view addSubview:background];
formVC.view.frame = (CGRect){CGPointZero, size};
formVC.view.center = CGPointMake(CGRectGetWidth(self.view.bounds) / 2., CGRectGetHeight(self.view.bounds) + CGRectGetHeight(formVC.view.bounds));
[self addChildViewController:formVC];
self.formController = formVC;
[self.view addSubview:formVC.view];
[UIView animateWithDuration:0.5 animations:^{
background.alpha = 0.4;
formVC.view.center = CGPointMake(self.view.bounds.size.width / 2., self.view.bounds.size.height / 2.);
}];
}
-(void)dismissPresentedForm:(id)sender {
if(!self.formController) return;
[UIView animateWithDuration:0.5 animations:^{
self.presentedBackgroundView.alpha = 0;
self.formController.view.center = CGPointMake(CGRectGetWidth(self.view.bounds) / 2., CGRectGetHeight(self.view.bounds) + CGRectGetHeight(self.formController.view.bounds));
} completion:^(BOOL finished) {
[self.presentedBackgroundView removeFromSuperview];
[self.formController.view removeFromSuperview];
[self.formController removeFromParentViewController];
}];
}
#end
I'm interesting, how can it is possible to make text moving from right to left like a "running news line in TV"?
I can do text moving from right to left (or any other) in UILabel, but this animation moving should be infinity loop, not only one time.
Here's a few:
https://github.com/caydenliew/CLTickerView
https://github.com/malcommac/DMScrollingTicker
https://github.com/MugunthKumar/MKTickerViewDemo
https://github.com/jeffhodnett/JHTickerView
https://github.com/cbess/AutoScrollLabel
There's probably more at Cocoa Controls.
How about like this:
-(void) animate {
label.center = CGPointMake(self.view.bounds.size.width + label.bounds.size.width/2, label.center.y);
[UIView animateWithDuration:20 delay:0 options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionRepeat) animations:^{
label.center = CGPointMake(0 - label.bounds.size.width/2, label.center.y);
} completion:nil];
}
// CrawlView.h
#import <UIKit/UIKit.h>
#interface CrawlView : UIScrollView
#property (assign, nonatomic) NSTimeInterval period;
#property (strong, nonatomic) NSMutableArray *messages;
- (void)go;
#end
// CrawlView.m
#define kWORD_SPACE 16.0f
#import "CrawlView.h"
#interface CrawlView ()
#property (assign, nonatomic) CGFloat messagesWidth;
#end
#implementation CrawlView
- (void)buildSubviews {
for (UIView *subview in [self subviews]) {
if ([subview isKindOfClass:[UILabel self]]) {
[subview removeFromSuperview];
}
}
CGFloat xPos = kWORD_SPACE;
for (NSString *message in self.messages) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = message;
CGSize size = [message sizeWithFont:label.font];
CGFloat width = size.width + kWORD_SPACE;
label.frame = CGRectMake(xPos, 0.0, width, self.frame.size.height);
[self addSubview:label];
xPos += width;
}
self.messagesWidth = xPos;
self.contentSize = CGSizeMake(xPos, self.frame.size.height);
self.contentOffset = CGPointMake(-self.frame.size.width, 0.0);
}
- (void)go {
[self buildSubviews];
if (!self.period) self.period = self.messagesWidth / 100;
[UIView animateWithDuration:self.period
delay:0.0
options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionRepeat
animations:^{
self.contentOffset = CGPointMake(self.messagesWidth, 0.0);
} completion:^(BOOL finished){
[self buildSubviews];}];
}
#end