Using UISegmentedControl as button - iphone

In my code I am using a UISegmentedControl as a "button" with only ONE segment and the momentary property set to YES. In versions of the SDK prior to iOS 4, this was not a problem, but it appears that now iOS 4 requires that there be at least 2 segments. The following code throws an exception:
NSArray *titles = [NSArray arrayWithObject:#"Button Title"];
myButton = [[UISegmentedControl alloc] initWithItems:titles];
and now in Interface Builder you cannot even create a UISegmentedControl with less than 2 segments. It logs the following error when building:
"The number of segments property of a segmented control must be greater than or equal to 2."
I'm kinda stumped. Any work arounds for this? I tried to create a UISegmentedControl with two buttons and then remove one programmatically and that "works" as it doesn't cause the app to crash. I get a button in iOS 3 and nothing in iOS 4. Any ideas?

Have you tried this:
[myButton removeAllSegments];
[myButton insertSegmentWithTitle:#"Press this" atIndex:0 animated:NO];

Really strange. It still works fine for me both in iOS4 simulator and device (this is a real working snippet from my code):
NSArray *laterContent = [NSArray arrayWithObjects: #"Maybe later", nil];
UISegmentedControl *later = [[UISegmentedControl alloc] initWithItems:laterContent];
CGRect frame = CGRectMake( 20,
98,
self.alert.bounds.size.width/2 - 30,
30);
later.frame = frame;
later.selectedSegmentIndex = -1;
[later addTarget:self action:#selector(laterAction:) forControlEvents:UIControlEventValueChanged];
later.segmentedControlStyle = UISegmentedControlStyleBar;
later.tintColor = [UIColor colorWithRed:130.0f/255.0f green:74.0f/255.0f blue:54.0f/255.0f alpha:0.8f];
later.momentary = YES;
later.alpha = 0.9;

It's not exactly a code-related solution but: I hit a similar issue and ended up drawing my own similar looking resources in Photoshop. It was not terribly difficult to do and removed a particular bad "code smell", IMO.

I found if you have a previous project with a single-segment UISegmentedControl, you can open both that project and your new one in Interface Builder and drag (or copy/paste) the single-segment UISegmentedControl to your new view controller. It will work fine in both your app and Interface Builder, just don't change the number of segments from 1 to anything else as it won't let you go back. I'm using Xcode 4.6.2 and iOS 6.

The editor in Interface Builder won't let you change the number of segments to be less than 1, but you can make a segmented control in IB by editing the .xib xml manually.
Right click on the .xib containing the segmented control
Choose Open As -> Source Code from the popup menu.
Find "<segments> which is the beginning of the xml array of segments. The whole thing should look like:
<segments>
<segment title="Segment 1 Title"/>
<segment title="Segment 2 Title"/>
</segments>
Just delete <segment title="Segment 2 Title"/> so there is only one segment element.
Right click the .xib again and choose Open As -> Interface Builder - iOS to go back to interface builder.
You should also probably set the segmented control to "momentary" mode.
I don't get any errors compiling or running this. Of course, this is a hack, and may break things in some circumstances or in a future iOS release.

Well two possibilities:
1) Create a button and the set background image as the single dot of the UISegmentedControl
If your SegmentedControl is a class variable just replace the #property
#property (nonatomic, retain) IBOutlet UIButton *button;
In the viewDidLoad-function add the following
-(void) viewDidLoad
{
[super viewDidLoad];
...
self.button = [UIButton alloc] init];
[self.button setBackgroundImage:[UIImage imageNamed:#"segmentedDot.png"] forState:(UIControlState)UIControlStateNormal];
}
2) Set the amount of segments to three of your UISegmentedControl and afterwards set the width to 20 - now only the dot in the middle will be shown.
Dont forget, if the user interacts with the UISegmentedControl, set the currentElement again to the second segment, else the dot will be in light grey instead of white state.
3) Place a button or a small view over the unwanted second dot of the UISegmentedControl in InterfaceBuilder. Make sure the backgroundcolor is even.
When you are using a button set the state for "user interaction" in attribute inspector to disabled. As type I would chose "custom" since you won't have some borders in your button ;)
Now male again sure, that always the first dot is the active Element.
However I think solution one should be the way you should go, since Apple thought something about it, when they disabled the 1-dot-SegmentedControl. Since you are using the Control as a button the Element you are looking fpr should be a button. ;)

There's no workaround in iOS 4. If you need this functionality, file a bug (enhancement request) at bugreport.apple.com.

You can also use removeSegmentAtIndex:animated:. If you create a segmented control in a storyboard or xib with two segments, you can remove one like this:
[self.sortButton removeSegmentAtIndex:1 animated:NO];

Related

Make a UITextView object editable

This is obviously an extremely "noobish" question. I'm aware that UITextView has a Boolean editable property, (since I'm not entirely illiterate) so the answer to my question seems really straightforward. But...
I create a UITextView programatically like this:
UITextView* input = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 100, 30)];
input.backgroundColor = [UIColor whiteColor];
input.editable = YES;
input.text = #"Type something here...";
[input setUserInteractionEnabled: YES];
....
[mainView addSubview: input];
But when I run the iPhone simulator with Xcode, clicking on the input field doesn't do anything. I can't input any text, the virtual keyboard doesn't appear, etc.
So, what am I doing wrong here? Why isn't the UITextView object actually editable in the Xcode iPhone emulator?
I just ran your code in the viewDidLoad command of a sample app that I test code in and it works fine. In my case, I have a UIWebView that I added via Interface Builder which your UITextView pops on top of. I click it and the keyboard pops up.
Is it possible that you may be creating some other object that is begin added to the view after your textfield that is covering it up? Any other view objects being added in the .... part of your sample code?

How to replace UINavigationBar with CustomHeader in iOS7

I would like to use a Custom header instead of default UINavigationBar. I am able to do it well, until I encountered a condition to keep the backward compatibility with iOS6 too. I have my previous question here ,un-answered.
Recently for Facebook App, I can see in iOS7, the blue-color header bar well aligned. To me it looks like its a custom header, I am not sure. FaceBook-Header
Now the problem is that, I am stuck with implementation of my custom app header. My Custom header height is 48px which goes behind the "network status bar" on top & I am getting only approx 35pixel as the rest is behind the "network status bar" like this.
Here are my goals to achieve.
I want a custom header. - Done
I don't want to use UINavigationBar. - Done
I want the support for iOS 5.0 till 7.0 - Stuck
Here is what it looks when I am using Custom header
Here is what it looks with UINavigationBar
How I can make app headers to appear like "FaceBook header" with "Custom Header" without getting underneath the "top network Header bar". If I Increase the height of Status Bar, it will look odd in iOS6 & older, but fits well in iOS7. I want to choose the right approach.
Any expert help is highly appreciated.
You need to place UIToolbar in xib,
and add background image in toolbar,
self.navigationController.navigationBarHidden = YES;
[self.toolBar setBackgroundImage:[UIImage imageNamed:#"background.png"] forToolbarPosition:UIToolbarPositionAny barMetrics: UIBarMetricsDefault];
add bar button,
UIButton *facebookButton = [UIButton buttonWithType:UIButtonTypeCustom];
[facebookButton setImage:[UIImage imageNamed:#"facbookBarImage.png"] forState:UIControlStateNormal];
[facebookButton addTarget:self action:#selector(action:)forControlEvents:UIControlEventTouchUpInside];
[facebookButton setFrame:CGRectMake(0, 0, 53, 31)];
UIBarButtonItem *facebookBarButton = [[UIBarButtonItem alloc] initWithCustomView: facebookButton];
self.toolBar.items = [NSArray arrayWithObjects: facebookBarButton,nil];
After some Research on Compatibility, I have come across a working solution to make a Custom header with no UINavigationBar & achieving what I was looking for. Feel free to use this approach.
Here are my results : iOS7 and Older iOS.
The approach is to figure out edgesForExtendedLayout (available in iOS 7). If we are on iOS7 then decide the height of "Custom Header" (probably 10Pixel more than what we keep in older version, so as to pad the extra 10Pixel underneath the "Top Network status bar").
Figure out the iOS7 compatibility for edgesForExtendedLayout here
CGFloat y;
if ([self respondsToSelector:#selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
y= 58;
}else {
y = 48;
}
Make Custom header with height of y here
self.customHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, appDimensions.width, y)];
Custom buttons on customHeaderView here
self.sideMenuButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.sideMenuButton setFrame:CGRectMake(0, y-45, 45, 45)];
So Now if I run this on iOS7, I see my header with enough height of 48pixel (more than what we have in Human Interface Guidelines for Touch Area (44 x 44)) even being 10 pixel is underneath the "Top network status bar).
If I run this in iOS < iOS7, I will have my custom header of 48 Pixel, starting right beneath the "Top network status bar"
Hope this helps other.

iPhone the beginner's application [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Short pre-introduction to a problem:
I applied to a position of iOS developer. For this position they don't require knowledge of Objective-C or iOS development. The requisites are a good experience with C/C++ and development for Linux platform.
Problem:
After the end of interview I got a task (with words that it's easy to impelement, is it?) and I can't understand whether it's so.
Interviewer has showed me an application on his iPhone that looked like:
Pressing/dragging that button leads to appearance of such bar:
He could scroll it and drag on the screen. When he had pressed the control button, bar disappeared.
I want to ask for excuse in advance, because I feel myself like a person who wants his job to be done by others. But I just want understand how I can approach to this problem. Cocoa library is a big and a new beast to me. Which classes/elements from it is it better to use to reach this aim? I programmed before with Qt, Tkinter, WinAPI (gui programming) for desktop but it doesn't help me a lot here.
I need to code something similar like the interviewer has showed me. I tried to find something in the internet similar to this, but without success.
So, I just want to know for which classes it's better to look for in Cocoa library.
And, if I failed to take something into consideration I would be glad (happy) to hear your notes.
Thanks in advance for any replies!
SOLVED
I want to thank everyone who replied and didn't leave me to sink into this unknown sea.
After a week of exploring I got what I wanted:
Source code: (I apologize, but I can't copy-paste code from virtual mac os machine)
Now I understand how too-wide and silly is my question, but anyway perhaps it helps someone to start out. Also one book helped me a lot.
There is no required understanding of Objective-C, but the interviewer wants you to create a simple application and return it to him? Interesting interview.
As for your question. The classes I see being needed here (aside the AppDelegate and a UIViewController of your choice) are:
UIButton
UIScrollView
UIImageView
The button's use here is obvious. The scrollview is again obvious. The imageview would be the icons inside the scrollview.
Allright - just to give you some guidance on what to start with and how to proceed so that you don't get lost in the great wide world of cocoa ...
And assuming that you are familiar with programming and have some decent experience in the c++ and java worlds ...
Open xcode.
Go for blank view based app. Single view application would do. Go for Automatic Reference Counting (ARC).
xcode creates a template for you with an application delegate (which you would not need for this task)
A view controller is created and a xib/nib file for an iPhone view. (ignore the ipad view if any).
Add to your view controllers so called IBAction methods. One for the top button and one for the others. An action is supposed to be called when a button is pressed (and other events which you don't need).
Properly defined you will see that action in the interface builde when editing the xib file. Add a button and connect it with this action (touch up inside would be best I think).
Compile this. When your button is pressed the action is executed. Set a breakpoint there to make sure that it got called.
Now, in this action, you either call a newly created method showScroller and hideScroller. And create those methods.
Now it gets a bit more complicated.
In showScroller you would have to ...
create a UIScrollView. (alloc it and init it)
create a number of UIButtons. (no alloc withot its init in objective-c)
set your second IBAction method as target for the buttons.
Position the buttons within the UIScrollView accordingly.
Position the UIScrollView nicely under the top button.
add the UIButtons as subview to the contentview of the Scroll view.
add the scroll view as subview to self.view (that is the underlying view, the grey thing in the interface builder).
In hideScroller you would have to ...
remove the UIScrolView from the view. For that you could either remove all subviews from self.view or you would have to keep a reference to the scroll view within your view controller in some instance variable. Pretty similar to C++ and Java which you know already.
Alternative to the scenario described above you could create all views within interface builder and pre-define the scroll view as hidden in IB (interface builder) and in showScroller and hideScroller you would just have to set its .hidden property to YES or NO. But I've got a guts feelting that with your background you should and could do this programmatically instead of hasseling with how IB connects into your code.
In the event that you really run into that trap and don't get the top most button properly connected to your code, then create that button programmatically too.
Ah, I forgot. The right place to create all those UI elements would be the viewDidLoad method of the ViewController class. There is an empty one generated already in your empty xcode template. Just enance it following the [super viewDidLoad]; call.
Have a look at this:
http://www.cocoacontrols.com/platforms/ios/controls/aurosetteview
When you press a button, the items show up and when you press again, it closes.
The source code is within the library. Use it to read up.
For your case, you need to include the scrollview as well.
Here you go:
Open XCode and create a new project. Choose iOS Empty Application template.
Go to menu, choose File, New File, Objective-C class. Name it RootViewController and choose a subclass to be UIViewController
Go to your app delegate .m file (If your project name was Test, this file is TestAppDelegate.m). At the top of the file, below the line where it says #import "TestAppDelegate.h" add another line that says #import "RootViewController.h"
In the same file there is a method named:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
at the end of the method but before return YES; statement add the following line:
self.window.rootViewController = [[RootViewController alloc] init];
Now go to your RootViewController.m file that you created in the step 2. and at the top of the file edit the interface to have this one instance variable:
#interface RootViewController ()
{
UIView *menuView;
}
#end
In the same file locate the method named - (void)viewDidLoad and add the following code in it: - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor =[UIColor blackColor];
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
menuButton.frame = CGRectMake(100, 60, 50, 50);
[menuButton setBackgroundImage:[UIImage imageNamed:#"menu.png"] forState:UIControlStateNormal];
[menuButton addTarget:self action:#selector(menuButtonTapped:) forControlEvents:UIControlEventTouchDown];
CGRect menuFrame = CGRectMake(20, menuButton.frame.origin.y + 50, 300, 60);
menuView = [[UIView alloc] initWithFrame:menuFrame];
menuView.backgroundColor = [UIColor purpleColor];
menuView.hidden = YES;
UIButton *menuButtonA = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonA.frame = CGRectMake(5, 5, 50, 50);
[menuButtonA setTitle:#"A" forState:UIControlStateNormal];
[menuView addSubview:menuButtonA];
UIButton *menuButtonB = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonB.frame = CGRectMake(65, 5, 50, 50);
[menuButtonB setTitle:#"B" forState:UIControlStateNormal];
[menuView addSubview:menuButtonB];
UIButton *menuButtonC = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonC.frame = CGRectMake(125, 5, 50, 50);
[menuButtonC setTitle:#"C" forState:UIControlStateNormal];
[menuView addSubview:menuButtonC];
UIButton *menuButtonD = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonD.frame = CGRectMake(185, 5, 50, 50);
[menuButtonD setTitle:#"D" forState:UIControlStateNormal];
[menuView addSubview:menuButtonD];
UIButton *menuButtonE = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButtonE.frame = CGRectMake(245, 5, 50, 50);
[menuButtonE setTitle:#"E" forState:UIControlStateNormal];
[menuView addSubview:menuButtonE];
[self.view addSubview:menuButton];
[self.view addSubview:menuView];
}
Below that method add a new method:- (void)menuButtonTapped:(id)sender
{
if (menuView.hidden)
menuView.hidden = NO;
else
menuView.hidden = YES;
}
Find some nice png image on the internet that will represent your menu button. Name it menu.png and drag and drop it in your project(inside the "file" menu on the left side)
That's it run the project ;)
just read the iphone's beginner book. you have to read some book first. first try to understand basic controls in iphone & basic manipulation in objective c
your above work is very basic.now just you are away from one step and that is read a book, you will get lots of free pdf on net

Strange behaviour of simulator & device when adding rightBarButtonItems to a UINavigationItem

In my application I am added two button at right of a UINavigationItem, its working fine on simulator, but when I testing it on device its gives me error of SIGABRT, along with unrecognized selector sent to NSArray. I tried to add one button at right side, it was added successfully, and works fine on device as well. Here my question is, whats the problem?
I am adding right buttons using following code,
NSArray *buttons=[[NSArray alloc] initWithObjects:btnOne,btnTwo,nil]];
myNavItem.rightBarButtonItems=buttons; //Error on device, but works fine on simulator.
Please, point me what is I doing wrong?
Thanks!
It appears that myNavItem is not an instance of UINavigationItem, but rather an instance of NSArray (which does not support setRightBarButtonItems). Could you show us more lines concerning myNavItem?
My suspicion is that myNavItem did not correctly retain the navigation item that it was originally pointing to. And that it points to an NSArray now by coincidence. This error might not occur in a debug setting if all objects are retained indefinitely for better logging.
If this code runs from an instance of a view controller try to use this line instead:
self.navigationItem.rightBarButtonItems = buttons;
On iOS prior to version 5: if you receive unrecognized selector sent to NSArray logs there is something wrong with your memory management. The log should read unrecognized selector sent to UINavigationItem on iOS prior to iOS 5.
Once the memory issue is fixed you should use a UIBarButtonItem with a custom view containing two UIButtons.
try adding these buttons to a UIBarButtonItem and add UIBarButtonItem to myNavItem like myNavItem.rightBarButtonItem = barButtonItem;
Your first line
NSArray *buttons=[[NSArray alloc] initWithObjects:btnOne,btnTwo,nil]];
has an extra right bracket at the end. Not sure if this would cause that error but it should cause some error.
You can use the UISegmentedControl. Check the UICatalog code sample to check its usage in the navigation bar.
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:btn1,btn2,nil]];
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.frame = CGRectMake(0, 0, 90, 35);
segmentedControl.segmentedControlStyle=UISegmentedControlStyleBar;
segmentedControl.momentary = YES;
UIBarButtonItem *segmentBarItem = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];
[segmentedControl release];
self.navigationItem.rightBarButtonItem = segmentBarItem;
[segmentBarItem release];
}
This is the best way of adding as many number of buttons in your bar as you desire.Hope it gonna help u.
Thanks :)

Which UI object to do this?

I have seen many times waiting panels (panels with a uiactivityindicatorview) black/dark with some transparency and white labels.
Like this one :
I guess it is a standard element.
Where can I find it?
Try This. it's the best solution I came across to show the activity. MBProgressHUD
MBProgressHUD looks nice. You might want to check out http://code.google.com/p/toast-notifications-ios/ too.
There's no iOS component that does this.
If you don't want to include an external library just for this one component then you can do it using UI components.
/* Warning, typed from memory */
// Create the UIView that's the background
UIView *pleaseWaitView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
[pleaseWaitView setBackgroundColor:[UIColor colorWithWhite:0.5 alpha:0.5]];
[[pleaseWaitView layer] setCornerRadius:5.0f];
// And create an activity indicator
UIActivityIndicator *i = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[i startAnimating];
[pleaseWaitView addSubview:i];
[i release];
// Add it to the main view (in the middle)
[pleaseWaitView setCenter:CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2)];
[self.view addSubview:pleaseWaitView];
You can add a UILabel with whatever text you want (in your case, 'Authenticating') in the same way as you added the activity indicator.
The tricky part is setting the corner radius - you will probably need this at the top of your .m file :
#import <QuartzCore/QuartzCore.h>
NB You can do this in interface builder as well if you want (apart from the corner radius bit!) ;)
I answered a question that included an overlay like this. I included the code and the overlay image you need to do it with. Take a look at this answer and take a look at the screen shot it created. I use this overlay as I send email in the background so you will want to edit the code to do your function but the overlay code is already in place.
Locking the Fields in MFMailComposeViewController
Happy Coding!
Check out DSActivityView. I've successfully used it in a few of my projects.
As by now there is no standard UIElement for that in iOS.
But checkout this library: