Is this iOS app using segmented control? - ios

In this photo (AirBnB iOS app), where it saids Upcoming and Previous, what do you guys think how this is implemented? Do you guys think this is developed using segmented control or two different buttons reversing (on/off, off/on) each other?
Is there an easy way(preferably using Swift) or a library to implement this feature in the app?
Sorry if this is a very naive question. It's my 3rd day learning iOS development :Face With Tears Of Joy:

Yes, it's probably a segmented control. You can having something like the following:
UIImage *segmentSelected =
[[UIImage imageNamed:#"segcontrol_sel.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected =
[[UIImage imageNamed:#"segcontrol_uns.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected =
[UIImage imageNamed:#"segcontrol_sel-uns.png"];
UIImage *segUnselectedSelected =
[UIImage imageNamed:#"segcontrol_uns-sel.png"];
UIImage *segmentUnselectedUnselected =
[UIImage imageNamed:#"segcontrol_uns-uns.png"];
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected
forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance]
setDividerImage:segUnselectedSelected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];
Quoted from RayWenderlich:
http://www.raywenderlich.com/21703/user-interface-customization-in-ios-6

There is no right answer since we don't have the source code.
However it could be one of those proposition :
Using a UISegmentedControl and customize it's appearance ;
Using two UIButton and change there appearance depending on which one is currently selected ;
Creating your own component : IBDesignable (that you'll be able to see directly while building your interface).
Since you are at your 3rd day learning iOS development, you might want to give a look at all the proposition above.
The IBDesignable solution could be the better one. Indeed, if you build it properly you would be able to reuse it easily on different screen size and in multiple apps. But, it might not be easy for you to create it in the first place.

Related

UISegmentedControl messed up after customization

So after I customize the UISegmentedControl, everything got messed up, the label got shifted and there is a white vertical line which I don't know where it came from. The divider also got off-center, I have checked that the black line is at 40-41px of a 80px image, so it must be centered. Want am I doing wrong or have anybody experience this before?
Before Customization:
After Customization:
note: the divider images is a horizontal flip of each other.
Code:
UIImage *un_sel = [UIImage imageNamed:#"divider-un-sel"];
UIImage *sel_un = [UIImage imageNamed:#"divider-sel-un"];
[_segmentControl setDividerImage:un_sel forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[_segmentControl setDividerImage:sel_un forLeftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
UIImage *normal = [[UIImage imageNamed:#"segment-normal"] stretchableImageWithLeftCapWidth:20 topCapHeight:0];
UIImage *selected = [[UIImage imageNamed:#"segment-selected"] stretchableImageWithLeftCapWidth:20 topCapHeight:0];
[_segmentControl setBackgroundImage:normal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[_segmentControl setBackgroundImage:selected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
Solved the problem by using
[[UIImage imageNamed:#"segment-normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
instead of stretchableImageWithLeftCapWith:topCapHeight

UISegmentedControl wrong dividerImage

I am custumizing all segmented controls in my app with the following code.Initially I set the selected segment to index 2.
Everything works perfect in IOS 6.While I was testing the app on IOS5, I realised that the initial setting of segmented control had a bug.The separation image between selected and unselected state is not set right.Due to that it looks like this.
If i change the selected segments by tapping the segmentedcontrol behaves normal.It is very weird.What elsse shall i do to prevent this strange behaviour?
UISegmentedControl *localSegmentedControl = [[UISegmentedControl alloc] init];
if ([localSegmentedControl respondsToSelector:#selector(setBackgroundImage:forState:barMetrics:)]) {
UIImage *segmentUnselectedSelectedDivider = [UIImage imageNamed:#"segmentedControlSeperatorNS.png"];
UIImage *segmentSelectedUnselectedDivider = [UIImage imageNamed:#"segmentedControlSeperatorSN.png"];
UIImage *segmentUnselectedUnselectedDivider = [UIImage imageNamed:#"segmentedControlSeperatorNN.png"];
UIImage *segmentUnselected = [[UIImage imageNamed:#"barButtonPlain.png"] stretchableImageWithLeftCapWidth:7 topCapHeight:0];
UIImage *segmentSelected = [[UIImage imageNamed:#"doneButton.png"] stretchableImageWithLeftCapWidth:7 topCapHeight:0];
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected
forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselectedDivider
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselectedDivider
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedSelectedDivider
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];
}
After trying all relevant approached explained in Customizing UISegmentedControl in iOS 5
i figured out that the problem is related with the width of the separation line.The tutorial about segmented control customisation in http://www.raywenderlich.com/4344/user-interface-customization-in-ios-5 assumes that the separation images are wider than 2px (in Retina).
I made them exactly 2px wide and the problem is resolved.
I think it is a known bug.
It is the same here with a workaround, may work for you.
Customizing UISegmentedControl in iOS 5
When i use segment control I was very tired the same problem. I solved that code
UIImage *segmentSelected =
[[UIImage imageNamed:#"ikisiSecildiKirmizi.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 5, 15)];
UIImage *segmentUnselected =
[[UIImage imageNamed:#"ikisiSecilmediGri.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 5, 15)];
UIImage *segmentSelectedUnselected =
[[UIImage imageNamed:#"solSecili.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 5, 15)];
UIImage *segUnselectedSelected =
[[UIImage imageNamed:#"sagSecili.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 5, 15)];
UIImage *segmentUnselectedUnselected =
[[UIImage imageNamed:#"ikisideSecilmemis.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 5, 15)];
[fiyatSaat setBackgroundImage:segmentUnselected
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[fiyatSaat setBackgroundImage:segmentSelected
forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[fiyatSaat setDividerImage:segmentUnselectedUnselected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[fiyatSaat setDividerImage:segmentSelectedUnselected
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[fiyatSaat setDividerImage:segUnselectedSelected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:[UIColor blackColor]
forKey:UITextAttributeTextColor];
[fiyatSaat setTitleTextAttributes:attributes
forState:UIControlStateNormal];
NSDictionary *attributes2 = [NSDictionary dictionaryWithObject:[UIColor whiteColor]
forKey:UITextAttributeTextColor];
[fiyatSaat setTitleTextAttributes:attributes2
forState:UIControlStateHighlighted];

iOS navigationbar setBackBarButtonItem to custom button

I need some assistance with how to customize 'backBarButtonItem'
And no I dont want to use the LeftBarButtomItem since I want to inherit the style and keep the transition from the 'BackBarButtom'
Okey, so what I got is:
UIBarButtonItem* barbtnItem = [[UIBarButtonItem alloc]initWithCustomView: [ArrivalProto ArrivalBtnTypeBack]];
[ArrivalProto ArrivalBtnTypeBack] gives me back a custom UIbutton with both a setBackgroundImage an a setImage.
And then all I want to do is to add this to customize the BackBarButton:
[self.navigationItem setBackBarButtonItem: barbtnItem];
But nooo. Just the the plain normal backbutton :(((
While this seems to work:
//self.navigationItem setLeftBarButtonItem:barbtnItem];
And this as well:
UIImage *btnTrnspBgrImg30 = [[UIImage imageNamed:#"trspBlackBtn30"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:btnTrnspBgrImg30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Info:
[self.navigationItem setBackBarButtonItem: <#(UIBarButtonItem *)#>];
[self.navigationItem setLeftBarButtonItem:<#(UIBarButtonItem *)#>]
As of iOS5 we have an excellent new way of customizing the appearance of almost any control using the appearance proxy, i.e. [UIBarButtonItem appearance]. The appearance proxy allows you to create application wide changes to the look of controls. Below is an example of a custom back button created with the appearance proxy.
Use the example code below to create a back button with custom images for normal and highlighted states. Call the following method from you appDelegate's application:didFinishLaunchingWithOptions:
- (void) customizeAppearance {
UIImage *i1 = [[UIImage imageNamed:#"custom_backButton_30px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
UIImage *i2 = [[UIImage imageNamed:#"custom_backButton_24px"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 6)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateNormal
barMetrics:UIBarMetricsLandscapePhone];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
forState:UIControlStateHighlighted
barMetrics:UIBarMetricsLandscapePhone];
}
This is just a quick example. Normally you would want to have separate images for normal and highlighted (pressed) state.
If you are interested in customizing the appearance of other controls, some good examples can be found here: http://ios.biomsoft.com/2011/10/13/user-interface-customization-in-ios-5/

UISegmentedControl background image strange behavior

I'm working on an iOS project and came across this strange issue. I have a UISegmentedControl element of bar style. It has 3 segments. The segments have fixed sizes of 80. I also have 3 images with each segment selected to set as background. Here is one of them`
When view is loaded, one of the segments is set as selected and this image is set as background like this:
[self.genderSelectionButton setBackgroundImage:[UIImage imageNamed:#"gender-switch01.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Now when I run the project on 5.1 Simulator, I get this distorted view for segmented button:
As you can see, the middle segment keeps the size I gave, but the image is kind of stretched from the middle to the edges.
Also selected segment is highlighted even though I have set it to NO.
In the method that listens to button selection, I change background image and get the following:
(background image is stretched again...)
Almost the same happens on iOS6.
Now am I doing something wrong, or is there a way to fix this??
EDIT
Found a better implementation with separate images for normal button, selected button and dividers. See the answer below.
It appears that setting full background image is not the best way to handle custom segmented button. Example found here.
Here is the basic code that does everything:
UIImage *segmentSelected =
[[UIImage imageNamed:#"segcontrol_sel.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected =
[[UIImage imageNamed:#"segcontrol_uns.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected =
[UIImage imageNamed:#"segcontrol_sel-uns.png"];
UIImage *segUnselectedSelected =
[UIImage imageNamed:#"segcontrol_uns-sel.png"];
UIImage *segmentUnselectedUnselected =
[UIImage imageNamed:#"segcontrol_uns-uns.png"];
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected
forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance]
setDividerImage:segUnselectedSelected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];

setBackgroundImage for UIBarButtonItem via appearance not working for other UIControlStates

I'm trying to customize a UIBarButtonItem using the appearance method (>iOS 5.0). It works fine for the UIControlStateNormal, but not for highlighted or disabled. See images
Here's the code I use to set those:
// now configure the UIBarButtonItems
UIImage *buttonBGInactive = [[UIImage imageNamed:#"button-navbar-30-inactive.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *buttonBGActive = [[UIImage imageNamed:#"button-navbar-30-pressed.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
[[UIBarButtonItem appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBackgroundImage: buttonBGInactive forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBackgroundImage: buttonBGActive forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
Any ideas? The images themselves are 30x30px and I'm not requiring landscape mode.
I found the solution to the problem. My images are 30x30px and I set the resizable endcaps to
UIEdgeInsetsMake(0, 15, 0, 15)
by setting those 15's to 14's, the problem went away. So best not to make endcaps the exact half of the image width.

Resources