iOS alert banner/label? - ios

I apologize if this question is very basic. I have been googling around but can't seem to find the api/reference for a drop down alert banner/label (I do not know the proper term for this), therefore I am posting here.
This: The label/banner which has "Please enter valid email address" in it.
So here a my questions:
What is the proper term for this (alert banner? notification? label?)
I am trying accomplish similar functionality to what is shown in the image, so basically if any field is invalid, the "label/banner" expands from underneath the navigation bar with the message in it:
If this is just a UILabel, what is the simplest way of adding the expand animation?
If it is something built in, since I have seen bunch of apps do it for alerting, please let me know what its called.

Have a look here, I'm sure you will be able to find something to suite your needs.
The basic idea is that its simply a UIView that you animate down from the top of the screen (at the very basic). You can get a lot fancier by adding gradients, touch recognizers to dismiss it, etc. But pretty much to get the base line functionality you would just do something like this:
//Create a view to hold the label and add images or whatever, place it off screen at -100
UIView *alertview = [[UIView alloc] initWithFrame:CGRectMake(0, -100, CGRectGetWidth(self.view.bounds), 100)];
//Create a label to display the message and add it to the alertView
UILabel *theMessage = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(alertview.bounds), CGRectGetHeight(alertview.bounds))];
theMessage.text = #"I'm an alert";
[alertview addSubview:theMessage];
//Add the alertView to your view
[self.view addSubview:alertview];
//Create the ending frame or where you want it to end up on screen, in this case 0 y origin
CGRect newFrm = alertview.frame;
newFrm.origin.y = 0;
//Animate it in
[UIView animateWithDuration:2.0f animations:^{
alertview.frame = newFrm;
}];

Check out my project - it might be just the thing you're looking for.
https://github.com/alobi/ALAlertBanner

For easier control over animating the alert, you can embed your custom view in a UIStackView and simply show/hide it in an animation block. That way will significantly reduce the amount of code needed to animate the visibility of the alert.

Related

Key-Frame Animation appears fuzzy when moving Frames?

I use JazzHands to create a key frame based animation in a UIScrollView.
Here is an example. Look at the view at the top. When you move from page to page. While the animation is running the view at the top is slightly moving from left to right. The animation appears a bit fuzzy.
Here is the code taken from the example here:
IFTTTFrameAnimation *titleView1FrameAnimation = [IFTTTFrameAnimation new];
titleView1FrameAnimation.view = self.titleView1;
[self.animator addAnimation:titleView1FrameAnimation];
[titleView1FrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(1)
andFrame:self.titleView1.frame]];
[titleView1FrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(2)
andFrame:CGRectOffset(self.titleView1.frame, timeForPage(2), 0)]];
[titleView1FrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(3)
andFrame:CGRectOffset(self.titleView1.frame, timeForPage(3), 0)]];
[titleView1FrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(4)
andFrame:CGRectOffset(self.titleView1.frame, timeForPage(4), 0)]];
When running the demo take a look at the part marked with red in the following screenshot:
Edit: Here is the code containing this problem: https://github.com/steffimueller/Intro-Guide-View-for-Talk.ai
How can I make the animation running smooth and less fuzzy?
This is due to the frame rate in the JazzHands IFTTTAnimatedScrollViewController being set for non-retina displays. You need to double the number in timeForPage, and also use double the number of the contentOffset in animate, but use the original non-doubled values of timeForPage in places where you were using that for laying out the positions of views instead of using it for the animation time.
Here's a Gist of the changes you'd have to make to your example to get it working. Fixed Demo Gist
You need this method for setting the animation times:
#define timeForPage(page) (NSInteger)(self.view.frame.size.width * (page - 1) * 2.0)
And this one for setting the centers of your views based on the page dimensions:
#define centerForPage(page) (NSInteger)(self.view.frame.size.width * (page - 1))
Then you need to override the scrollViewDidScroll: method in IFTTTAnimatedScrollViewController to use double the numbers it's currently using.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.animator animate:(NSInteger)(scrollView.contentOffset.x * 2)];
}
We'll work on getting the JazzHands demo updated!
Before you start your animation call:
view.layer.shouldRasterize = YES; (seems that you are using objective-c so I put YES here, for swift should be true)
As soon as the animation is finished call
view.layer.shouldRasterize = NO; (seems that you are using objective-c so I put NO here, for swift should be false)
You should always use it when you animating a view
You can see more details about it in the WWDC 2012 Polishing Your Interface Rotations video (paid developer subscription needed)
I hope that helps you!
[EDIT]
Every Time you call the method animate set shouldRasterize to YES before it, like in the example bellow:
titleView1FrameAnimation.view.layer.shouldRasterize = YES;
[self. titleView1FrameAnimation animate:scrollView.contentOffset.x];
I've messed around a bit with the code and it seems that keeping those top views in place while the scrollview is scrolling made it jiggle left and right.
What I did is take out the title view from the scroll view and add it to the view controller view.
You can see it in action here
Later edit:
To actually see what I've changed you can check the file differences in Git. Basically I moved your titleViews (titleView1, titleView2, etc) from the scrollView to the view controller's view (so basically I've replaced all the lines that were like this:
[self.scrollView addSubView:self.titleView1]
to something like this:
[self.view addSubView:self.titleView1]
After that I've also took out the keyframe animations that were keeping your title views in place since they were not moving with the scrollview anymore. Practically I've deleted all the lines that were adding a frame animation to your titleviews from each configurePageXAnimation.
2nd question answer:
Say your screenshot view is called screenshotView. You can go ahead and create it like this:
UIImageView *screenshotView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ScreenshotImage"]];
[self.view addSubview:screenshotView];
self.screenshotView = screenshotView;
[self.screenshotView setCenter:CGPointMake(self.view.center.x + self.view.bounds.size.width, <#yourDesiredY#>)];
And animate it like this:
//screenshotView frame animation
IFTTTFrameAnimation *screenshotViewFrameAnimation = [IFTTTFrameAnimation new];
screenshotViewFrameAnimation.view = self.screenshotView;
[self.animator screenshotViewFrameAnimation];
[screenshotViewFrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(1) andFrame:self.screenshotView.frame]];
[screenshotViewFrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(2) andFrame:CGRectOffset(self.screenshotView.frame, -self.scrollView.bounds.size.width, 0.0)]];
[screenshotViewFrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(3) andFrame:CGRectOffset(self.screenshotView.frame, -self.scrollView.bounds.size.width, 0.0)]];
[screenshotViewFrameAnimation addKeyFrame:[[IFTTTAnimationKeyFrame alloc] initWithTime:timeForPage(4) andFrame:CGRectOffset(self.screenshotView.frame, -self.scrollView.bounds.size.width * 2, 0.0)]];

UIActivityIndicatorView not appearing in Subview

So previously in my application, I had an UIActivityIndicatorView for processes that let the User know that something is loading. I wanted to add a layer of text to inform the user such as signing up,retrieving data, etc. I created a UIView, set it's frame to be in the center of the screen, than my hope was to create the UIActivityIndicatorView in the center and the UILabel in the bottom fourth. My label appears as planned, however now my UIActivityIndicatorView does not appear anymore so I'm curious to as why. I have made sure that the UIActivityIndicatorView is white so it's visible against the black background color and checked other common pitfalls. It seems I'm not understanding something and I was curious if someone could point me in the right direction. Thanks
/*Create the UIView that will serve as the frame to our label and activity view*/
UIView *indicatorFrame=[[UIView alloc]initWithFrame:CGRectMake(self.view.frame.size.width/2-50, (self.view.frame.size.height-self.navigationController.navigationBar.frame.size.height-self.tabBarController.tabBar.frame.size.height)/2.0-50, 100, 100)];
indicatorFrame.backgroundColor=[UIColor blackColor];
indicatorFrame.layer.borderColor=[[UIColor whiteColor]CGColor];
indicatorFrame.layer.borderWidth=2.0f;
indicatorFrame.layer.cornerRadius=10.0f;
indicatorFrame.layer.masksToBounds=YES;
[self.view addSubview:indicatorFrame];
/*Create activity indicator*/
UIActivityIndicatorView *spinner=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[spinner setCenter:CGPointMake(indicatorFrame.frame.size.width/2.0,indicatorFrame.frame
.size.height/2)];
[indicatorFrame addSubview:spinner];
/*Create Text Label to be added to the indicatorFrame*/
UILabel *indicatorViewText=[[UILabel alloc]initWithFrame:CGRectMake(5,indicatorFrame.frame.size.height/2,indicatorFrame.frame.size.width-5,30)];
[indicatorViewText setCenter:CGPointMake(indicatorFrame.frame.size.width/2,(indicatorFrame.frame.size.height)*3/4)];
indicatorViewText.text=#"Logging In";
indicatorViewText.font=[UIFont fontWithName:#"Georgia" size:18];
indicatorViewText.numberOfLines=1;
indicatorViewText.textColor=[UIColor whiteColor];
indicatorViewText.textAlignment=NSTextAlignmentCenter;
indicatorViewText.adjustsFontSizeToFitWidth=YES;
[indicatorFrame addSubview:indicatorViewText];
[spinner startAnimating];
Tried your code and it works without a problem. Your problem could be somewhere else in the rest of your view controller.
Your codes' output http://i.imgur.com/6i5zxBP.png
However, the only change i did is to make the text visible by settings its background color to clear color.
My personal opinion however, is to use a library like MBProgressHUD or JGProgressHUD. They cut down your code drastically and you do not have to worry about these kind of problems.

Create multiple UIViews dynamically

I want to create a bar chart using UIView animations. The bar chart will be dynamically created, using data retrieved from my persistent store.
To teach myself how to use UIView animations, I followed this Ray Wenderlich tutorial then built a modified app based on it. As a result, I feel comfortable with the animation aspects--at least as long as it involves discrete (Storyboard-created) views specified by hard-coded data.
However, in the full implementation, the bar chart will have multiple columns, the number, heights, widths, etc. of which will be specified proportionally by live data.
At this point, I've created a UIView in the storyboard, linked to a custom UIView subclass called RiserBar, thinking to create instances of the views (RiserBar *) on the fly. However--and I feel kinda dumb admitting it--I realize I don't really know how to implement this idea. For example, if I'm iterating through an array containing the specifications for several bars, what would that look like? Would each bar have a name? How would those names be generated?
Here's the code I'm thinking about. aBAr is an instance variable. The frame specification, as well as specArray are just dummies, as the exact specification mechanism isn't clear just yet, but the idea is to create as many RiserBar objects as there are entries in specArray:
-(void) makeBarChart
{
RiserBar *aBar;
for (int i=0; i<specArray.count; i++)
{
aBar = [[RiserBar alloc]initWithFrame:CGRectZero];
aBar.backgroundColor = [UIColor redColor];
[self.view addSubview:aBar];
[UIView animateWithDuration:1
delay:.2
options: UIViewAnimationCurveEaseOut
animations:^
{
aBar.frame = CGRectMake(50, self.view.frame.origin.y, startingSpec.width, startingSpec.height);
aBar.frame = CGRectMake(50, self.view.frame.origin.y, endSpec.width, endSpec.height);
}
completion:^(BOOL finished)
{
NSLog(#"Done!");
}];
}
}
Please help me straighten out my thinking about this!
Thanks!

UIAlertView addSubview in iOS7

Adding some controls to UIAlertView was deprecated in iOS7 using addSubview method. As I know Apple promised to add contentView property.
iOS 7 is released now and I see that this property is not added. That is why I search for some custom solution with ability to add progress bar to this alertView. Something for example similar to TSAlertView, but more ready for using in iOS 7.
Here is a project on Github to add any UIView to an UIAlertView-looking dialog on iOS7.
(Copied from this StackOverflow thread.)
It took me only 1 day to create my own alert view that looks exactly like Apple's
Take a screenshot of Apple's alert for reference (font sizes, spacings, width)
Create a xib with title, message, custom view and tables for buttons (Apple uses tables instead of UIButton now, default table cell is good enough). Note you need 3 button tables: two for left and right buttons (whenever the number of buttons is 2), another one for the other cases (one button or more than 2 buttons).
Implement all the methods from UIAlertView on your custom alert.
Show/Dismiss - you can create a specific modal window for your alerts but I just put my alerts on top of my root view controller. Register your visible alerts to a static array. If showing the first alert/dismissing the last, change tint mode of your window/view controller to dimmed/to automatic and add/remove a dimming view (black with alpha = 0.2).
Blurred background - use Apple's sample code (I used opaque white)
3D dynamic effects - use Apple's sample code (5 lines of code). If you want a nice effect, take a slightly bigger snapshot in step 5 and add inverse animators for alert background and foreground.
EDIT:
Both blurred background and the paralax effect sample code can be found in "iOS_RunningWithASnap" WWDC 2013 sample code
Paralax effect:
UIInterpolatingMotionEffect* xAxis = [[[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.x"
type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis] autorelease];
xAxis.minimumRelativeValue = [NSNumber numberWithFloat:-10.0];
xAxis.maximumRelativeValue = [NSNumber numberWithFloat:10.0];
UIInterpolatingMotionEffect* yAxis = [[[UIInterpolatingMotionEffect alloc] initWithKeyPath:#"center.y"
type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis] autorelease];
yAxis.minimumRelativeValue = [NSNumber numberWithFloat:-10.0];
yAxis.maximumRelativeValue = [NSNumber numberWithFloat:10.0];
UIMotionEffectGroup *group = [[[UIMotionEffectGroup alloc] init] autorelease];
group.motionEffects = #[xAxis, yAxis];
[self addMotionEffect:group];
The blurred background is the only complicated thing. If you can use an opaque color instead, use it. Otherwise it's a lot of experimenting. Also note that blurred background is not a good solution when the background is dark.
For the show/dismiss animationg, I am using the new spring animation method:
void (^animations)() = ^{
self.alpha = 1.0f;
self.transform = CGAffineTransformIdentity;
};
self.alpha = 0.0f;
self.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
[UIView animateWithDuration:0.3
delay:0.0
usingSpringWithDamping:0.7f
initialSpringVelocity:0.0f
options:UIViewAnimationOptionCurveLinear
animations:animations
completion:^(BOOL completed) {
//calling UIAlertViewDelegate method
}];
I wrote a full implementation of UIAlertView that mimics the complete UIAlertView API, but adds the contentView property we've all wanted for so long: SDCAlertView.
(source: github.io)
For those who love simple and effective methods with out having to write lines of code. Here is a cool solution without using any other private frame works for adding subviews to ios 7 alert views,i.e.
[alertView setValue:imageView forKey:#"accessoryView"];
Sample code for better understanding,
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(180, 10, 85, 50)];
UIImage *wonImage = [UIImage imageNamed:#"image.png"];
[imageView setImage:wonImage];
//check if os version is 7 or above
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
[alertView setValue:imageView forKey:#"accessoryView"];
}else{
[alertView addSubview:imageView];
}
Hope it helps some one,thanks :)
For IOS7
UIAlertView *alertView1 = [[UIAlertView alloc] initWithTitle:#"Enter Form Name"
message:#""
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alertView1.alertViewStyle = UIAlertViewStyleSecureTextInput;
UITextField *myTextField = [alertView1 textFieldAtIndex:0];
[alertView1 setTag:555];
myTextField.keyboardType=UIKeyboardTypeAlphabet;
[alertView1 show];
There wont be UIAlertView with custom views in iOS7, nor contentView which Apple changed its mind about, so addSubview is impossible now in UIAlertView.
A good alternative will be SVProgressHUD, according to many threads in Apple's forum.
Edit:
There is officially no addSubview nor subclassing for UIAlertView in iOS7.
The UIAlertView class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.
Other good alternatives:
ios-custom-alertview by wimagguc
MZFormSheetController.
You can find simple solution without extra classes here
It is based on setting accessoryView for ordinary UIAlertView.
PKAlertController (https://github.com/goodpatch/PKAlertController) is great library. I tested a lot of similar libraries and just this satisfied all my requirements.
Why it is cool:
Supports custom view
Supports iOS7
It is view controller
It behaves and looks like native alert view, including motion effects
Customizable
Similar interface like in UIAlertController

UIAlertView with 3 textfields and 3 labels overlap each other

I'm trying to create an UIAlertView with 3 TextFields and 3 Labels.
But with my current code they just go over each other, I've tried to change the frame of the AlertView and I've tried to use the CGAffineTransform but they both didn't work.
Here's my code:
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Sign in" message:#"\n\n\n\n\n" delegate:self cancelButtonTitle:#"Stop" otherButtonTitles:#"Sign in",nil];
UILabel *customerIdLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 55, 65, 21)];
customerIdLabel.tag =1;
customerIdLabel.text = #"Customer id: ";
[myAlertView customerIdLabel];
UITextField *customerIdField = [[UITextField alloc] initWithFrame:CGRectMake(89, 50, 160, 30)];
customerIdField.tag = 2;
customerIdField.placeholder = #"Fill in your customer id";
[myAlertView customerIdField];
And then there's two more combinations of those.
Here's the transform that I've tried:
CGAffineTransform myTransform = CGAffineTransformMakeScale(1.0, 0.5f);
[myAlertView setTransform:myTransform];
And this is what I get:
I'm pretty sure you aren't supposed to use UIAlertViews like that. You're supposed to set the title, message, etc and use the [alertview show]. The documentation seems to be pretty clear that it is an as-is class.The UIAlertViewStyle may be something you can look at, but the options are 1 text field, 1 secure field, or a username and password field.
Your best option is to use a new UIViewController and use the presentViewController:animated:completion: call.
I get around this by not changing UIAlertView but add a clear view on top of it when it is showing (you can pad with spaces) and add the textfields there at the correct location (note when rotation occurs). Then, let the tap go through the view to the UIAlertView. This has gone through Apple in 3 apps in the store.
Before the new SDK in xcode 5 you where able to add subviews to an alert view but that doesn't work anymore. I had to update an app because of that nasty code. Is better to use uipopovercontroller for ipad or show a UIView or even present a viewcontroller for either ipad or iphone.

Resources