Multiple view states in Interface Builder
I'm working on a screen that has 3 states:
- Validating
- Loading
- Error
The first two are quite easy, since there is only a label text change. The third one is trickier tho, because I need to show an error message a开发者_开发技巧nd have a Retry button on it.
Also, I would like to have all this under one Controller (which is the easy part, I guess.)
The question is: how do I do multiple view states within Interface Builder? Has anyone done this before? Or am I going about this in the wrong way?
You might try adding additional views that you add or remove as required. In the window with "File's Owner", "First Responder", "View", etc, add three UIView's from the Library. You may want to change their names from "View" to "Validating", "Loading" and "Error".
Now open up each one and customize it as you like by adding buttons and labels and other such things.
Back in XCode, declare the new views:
IBOutlet UIView *validView;
IBOutlet UIView *loadView;
IBOutlet UIView *errorView;
and be sure to make the appropriate connections in the InterfaceBuilder. Any actions that you wish to link up from any of these views should work great.
Now, to switch, create an action (or three different ones). This can be an IBAction or not as you like. In the header:
-(void)showError;
Now for the implementation, you may want something like this.
-(void)showError {
// skip this if you always arrive from the validView
if ([validView superview]) {
[validView removeFromSuperview];
}
[self.view addSubview:errorView];
}
You can get fancier with animations, if you like:
-(void)toggleErrorWithFlip {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationTransition:([errorView superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight)
forView:[self view]
cache:YES];
if ([errorView superview]) {
[errorView removeFromSuperview];
} else {
[[self view] addSubview:errorView];
}
[UIView commitAnimations];
}
The "Retry" button may trigger an action along the lines of the following:
-(IBAction)retryLoad {
[errorView removeFromSuperview];
[self.view addSubview:validView];
// do some stuff that retries whatever was tried and failed
}
Again, this can happen with or without animations.
If there is a default view, one that you always fall back on (e.g. validatingView), then make that the original "View" and just add the other two views (e.g. loadView and errorView) on top of it. This may save a bit of work depending on how you want things to go.
Your error seems like a great candidate for a UIAlertView
//wherever error is detected
UIAlertView *alert = [[UIAlert View alloc] initWithTitle:@"Error" message:@"An error occured" delegate:self cancelButtonTitle:@"Forget It" otherButtonTitles:@"Retry", nil];
[alert show];
[alert release];
//implement the delgate method
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
switch(buttonIndex) {
case 0:
break;
case 1:
break;
default
break;
}
}
You'll also have to implement UIAlertViewDelegate in your header!
Exactly what you do depends on the layout involved. The easiest approach I've used a number of times is to lay out all controls, and just mark groups of them as hidden/not hidden in methods like:
- (void) showErrorModeControls
{
self.errorLabel.hidden = NO;
self.errorButton.hidden = NO;
self.regularLabel.hidden = YES;
self.regularButton.hidden = YES;
}
you can also do animations, fade in/out, etc. That's one way.
Another way is to group your controls into subviews of the main view, and show/hide these subviews as a whole. That only works if you can manage to arrange all the views so that when more than one is visible that you can see the contents of the other views. You can use clearColor backgrounds to accomplish that. The advantage to this approach is that you can lay out the controls in the individual subviews separately in interface builder (you do this with a neat trick: just set the X coordinate of the frames of the other views to 320 (or whatever is appropriate for your view) to "get them out of the way" of the view you want to edit. Then you move them back to X coord 0 when you're done.
Yet another approach I've used is to have entire "pages" of views like a mini-navigationviewcontroller, and slide in and out these views myself by animating their frames "onscreen" and "offscreen". You can use the same trick in interface builder above to work on these "page" subviews one at a time.
If you need custom alerts, you can actually use TSAlertView class. It works pretty nicely and it's easy to deploy. It looks like an UIAlertView but you can actually customize it with UITextView's, multiple buttons with legends, etc.
精彩评论