UIAlertView with 3 buttons > spacing on third button - iphone

I am creating a simple alert view with 3 buttons, each button has equal importance, there is no cancel button or anything like that:
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:#"msg" delegate:self cancelButtonTitle:nil otherButtonTitles:#"button1",#"button2",#"button3",nil];
[alert show];
The third button has extra space above it, as if it was a cancel button.
I would like the space to be identical in between buttons.
Any idea?

Unfortunately, there is no easy way to do so (you'd have to literally reinvent the wheel, subclassing UIAlertView not necessarily being a very viable option).
However, you might be interested by the BlockAlertsAnd-ActionSheets library, that would give you nice, block based, alert views that do offer a consistent spacing between buttons.

Related

Highlight Top Button in UIAlertView

I've got a UIAlertView with 3 buttons displayed vertically by default in the UIAlertView. I'd like the top button to be bold/highlighted. From my understanding and testing, the 'cancel' button is the one that is highlighted. The problem is no matter how I set the cancel button, it is placed last in this row. I cannot get it to be the first button.
I've tried setting the cancel button explicitly
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"Top Button"
otherButtonTitles:#"Middle Button", #"Bottom Button", nil];
as well as setting the index of the cancel button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Top Button", #"Middle Button", #"Bottom Button", nil];
alert.cancelButtonIndex = 0;
This problem is actually caused by changes Apple made in iOS 7. Prior to iOS 7 we were able to access the subviews of an UIAlertView by calling [alertView subviews]. But since iOS 7 doesn't give us access to any subviews ([alertView subviews].count will always return zero) we can't customize UIAlertViews the way we used to.
So the only way to achive your goal under iOS 7 is to build a custom view that looks like UIAlertView and then customize it as you like.
But if you're coding for an iOS version prior to iOS 7 than you could use this easy hack to access a button:
UIAlertView *alertView = [[UIAlertView alloc] init];
[alertView addButtonWithTitle:#"Yes"];
UIButton *yesButton = [alertView.subviews lastObject]; //is nil under iOS 7
This way you would get access to the first button. After that you can customize your UIAlertView as usual.
By the way: Apple did not only want to give all UIAlertViews the same design by changing the way we can customize them. The reason lies in HCI researches (Human-Computer-Interaction). People tend to think the bottom button is always the 'default' answer if that is the way it is implemented throughout all apps.
Also the bottom button is the only highlighted button in a UIAlertView. So its visual weight is stronger than the visual weight of the button with about the same amount of text. That's another factor why people tend to choose this one. And that is also the reason why the highlighted button never should cause disastrous and irreversible actions ('You wanna delete all your saved games' should always highlight the button 'Keep my saved games' and not the one telling 'Delete everything').
Therefore Apple always makes the Cancel Button the bottom one no matter in which order you added the buttons. So if your app doesn't make use of a fully custom interface and uses many User Interface Elements provided by Apple than I highly recommend you to not try to change that behavior and make the bottom button your 'default' button.
There is a customer alert view DTAlertView.
I hope it can help you.

How to set identical appeareance to buttons for an UIAlertView?

By default, a UIAlertView with two buttons has different alpha for each button.
Is there a way to make them look identical with different text, without subclassing UIAlertView, or making a custom alert view?
Here is what i used:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:
kAlertTitleOrderType message:kAlertMessageOrderType delegate:delegate
cancelButtonTitle:nil otherButtonTitles:#"Collection", #"Delivery", nil];
If you set the cancel button to nil when calling initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles: then no cancel button will be added (this is the one that looks different). You can then add other buttons as you require.

change position of cancel button in UIAlertView?

I noticed that when I delete an app from my iPhone home screen, the alert view that appears shows a Delete button on the left and Cancel on the right. However, when I build a delete function within my app using UIAlertView, the buttons only seem to display with Cancel on the left and Delete on the right.
I'd like my app to be consistent with the OS, but I can't figure out how to make the Cancel button appear first. Does anyone know?
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Delete Song"
message:#"Are you sure you want to delete this song? This will permanently remove it from your database."
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
I tried setting alert.cancelButtonIndex = 1, but that had no effect.
Ah, I just figured out how to change this. The cancelButtonTitle argument is optional, so you can add a custom button in whatever position you want and then designate that as the cancel button, like this:
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Delete Song"
message:#"Are you sure you want to delete this song? This will permanently remove it from your database."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Delete", #"Cancel", nil];
alert.cancelButtonIndex = 1;
That puts the Delete button the left and the Cancel button on the right and highlights the Cancel button.
A possible reason Apple used an alert view on the home screen was because it once asked users to rate the apps they were removing (not anymore). They likely made the Cancel button the lighter-colored one because this was considered a destructive action (deletes an app and its data).
I guess you could reverse the titles (cancelButtonTitle:#"Delete" otherButtonTitles:#"Cancel", nil) and handle clicks on those buttons the other way around (not sure if Apple did the same). That would be a little awkward though; how about using an action sheet instead?

Change the color of a button on a standard pop-up action

I am using a standard pop up action in my iphone app (the pop up at the bottom of the screen). This has 2 buttons "ok" and "cancel". It seems the standard colour scheme is to have the top button red. I want to change this so the top button is green. I have been googling forever and can't find the solution. Any ideas would be great. Thanks
You can browse through ActionSheet ( I assume you use UIActionSheet class) subviews - like that:
NSArray* subViews = [aSheet subviews];
for (UIView* sView in subViews)
{
...
}
And change subviews properties there as you like.
You can also create UIActionSheet without any buttons at all:
UIActionSheet* aSheet = [[UIActionSheet alloc] initWithTitle:#"\n\n\n" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
And afterward create your own custom buttons and add them to the ActionSheet view. (put more \n to the title to enlarge Sheet height)
I assume you're referring to a UIActionSheet. In a UIActionSheet, you can define a button that cancels the action and has a black background, a button that marks a destructive action and has a red background, and all other buttons which have white backgrounds. Which option corresponds to which class of actions can be specified in the initialization of the UIActionSheet using – initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:.
The design of a UIActionSheet, including why you should only use these colors for your buttons, is explained in the iPhone Human Interface Guidelines. I'd follow Apple's suggestions in this regard, as they will make your application easier to use.
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:#""
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil,#"Mail",#"Facebook",#"Twitter",nil
otherButtonTitles:nil];
NSArray *buttons = [action subviews];

Bug in AlertView on iPhone?

I write a piece of code to "do something->show alert1->do something->show alert2".
//do something
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Alert 1"
message:nil
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
//do something
UIAlertView *alert2 = [[UIAlertView alloc]
initWithTitle:#"Alert 2"
message:nil
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert2 show];
[alert2 release];
And suddenly a strange thing happened to multiple AlertViews: It shows "Alert 1"->"Alert 2"(Press 'OK')->"Alert 1". Why "Alert 1" shows again? I haven't written any delegate method yet. Maybe a bug?(Thanks to cobbal, alert1 is still there when alert2 appears.)
I find -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex works well. Is the delegate method a common way to show multiple alertViews?
I would guess that alert 1 is shown and then covered by alert 2 since show isn't modal. When alert 2 is closed, alert 1 is still open.
To your second question, alertView:didDismissWithButtonIndex: may work better, but I haven't actually tested that.
The delegate is so that you can be notified when the alert is dismissed, and which button was used to dismiss it. It doesn't impact whether the alert is dismissed at all.
The alert will remain visible until it is dismissed either by you tapping a button (if any - they are not required) or you call either [UIAlertView dismissWithClickedButtonIndex:animated] or the (undocumented) dismiss method of the alert instance.
It looks like (as Cobbal suggested), alert 2 is popping up over alert 1, you dismiss alert 2, and alert 1 remains there (until it itself is dismissed).
Is there a particular reason you want to show a new alert while another is still showing? Perhaps some more context would help us to get to the root of the issue, which I suspect may be a design issue.
[edit] coming back to this and reading again, I wonder if what you are asking about with the delegate method is whether you should be showing alert 2 from there? In which case that's probably what you want - whether directly or indirectly. By indirectly I mean that you may have some state set elsewhere that determines whether alert 2 should be shown (or the circumstances that lead to it). That state (a flag, perhaps) could be set when you show the first alert, and cleared when the alert is dismissed (from the delegate method).
The reason this happens is because UIAlertView doesn't block while it's showing. Any code written after showing an alertview will run straight after the alert is shown.
What you should have is two different methods. One that does something and then shows an alert, and then another that does something and shows another alert.
Kick off the first method to do something and show an alert, and then hook into the alert's delegate method, and when you get the callback from the alertview, run the other method.
This way, the second part of the process won't happen until the user has pressed OK on the alert in first part of the process.