Giter Site home page Giter Site logo

sdsegmentedcontrol's Introduction

Segmented Control

A drop-in remplacement for UISegmentedControl that mimic iOS 6 AppStore tab controls.

The only good piece of UI to extract for this terrible app

Features

  • Segments with image, image and text or text only
  • Interface Builder support (just throw a UISegmentedControl and change its class SDSegmentedControl)
  • Animated segment selection
  • Content aware dynamic segment width
  • Scrollable if there are too many segments for width
  • Animated segment selection, with animated arrow
  • Appearance customization thru UIAppearance
  • UIControl events for value changes
  • Enable or disable specific segments
  • Indiviual customizable segment width

TODO

  • Shadow effect / arrows, which show that the segment control is scrollable

Usage

Import SDSegmentedControl.h and SDSegmentedControl.m into your project and add QuartzCore framework to Build Phases -> Link Binary With Libraries.

You can then use SDSegmentedControl class as you would use normal UISegmentedControl.

Licenses

All source code is licensed under the MIT-License.

The icons in the example project are taken from Glypish Free Iconscreated by Joseph Wain and licensed under the Creative Commons Attribution 3.0 United States License.

Authors

sdsegmentedcontrol's People

Contributors

adamcumiskey avatar akhenakh avatar chadpod avatar davidobfuscator avatar exalted avatar idpaterson avatar imgokul avatar josephlin avatar kmcbride avatar mrackwitz avatar myell0w avatar nsmutablestring avatar rs avatar sbandol avatar sdarlington avatar weiran avatar zedenem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sdsegmentedcontrol's Issues

Rotation animation is broken

The animation of the frame when autorotating is broken.

AFAIK the problem is due to all animations being removed in drawPathsFromPosition.
Removing both lines re-enables the expected smooth transition of the frame.

However, another problem is that the animation duration is not in sync with the
rotation animation duration. Temporarily setting the proper duration in willRotateToInterfaceOrientation:duration: and reseting it to the default in didRotateFromInterfaceOrientation is a workaround, but I think the problem is that the animation duration is used for both the animation of the selection and the path of the whole layer. It should only be used for the selection and the layer animation should be somehow in sync with whatever animation is currently occuring, but I couldn't figure out a proper fix.

NSFoundationVersionNumber_iOS_6_1 does not exists on iOS 6

Hello !

My app won't build on XCode 4, because of SDSegmentedControl.m:105:45: Use of undeclared identifier 'NSFoundationVersionNumber_iOS_6_1'

NSFoundationVersionNumber_iOS_6_1 exists only on iOS 7, you should replace it with 993.00.

Last segment is out of view

Hello,
My segment control is made of 14 segments and I want the last one to be the first selected segment. I did so by using [segmentControl setSelectedSegmentIndex:13];
My problem is that when the view is loaded a part of the last segment is out of the borders of the view and I want it to be completely visible from the start. Can I have some help?

Fires valueChanged even when segment not changed.

With the ValueChanged event with the action

  • (IBAction)segmentChanged:(SDSegmentedControl *)sender {
    NSLog(@"Segment has changed");
    }

This action is called even when the currently selected segment is touched. The usual behaviour with UISegmentedControl is that unless a different segment is touched this ValueChanged event should not occur.

Any ideas? Thanks.

Segment titles positioned incorrectly when segmented control is in view embedded in navigation controller

I'm not sure if this the intended behavior of the segmented control, but when I place the object in a view that is embedded in a Navigation Controller, the segment titles don't show up. I discovered that if I scrolled up within the area where the title should be, the titles eventually showed up, so it seems that the titles are being incorrectly positioned.

I also tried embedding a UIView inside a container view, but I still had the same issue.

Any ideas?

Disable Segement should add check selectedSegmentIndex

When I run SDSegmentedControl Demo, I try click Disable Segement Button, At last, The app will crash. I found this code don't check selectedSegmentIndex.

  • (void)setEnabled:(BOOL)enabled forSegmentAtIndex:(NSUInteger)index
    {
    [self segmentAtIndex:index].enabled = enabled;

    if (index == self.selectedSegmentIndex)
    {
    self.selectedSegmentIndex = [self firstEnabledSegmentIndexNearIndex:index];
    }
    }

The Demo App Crash Log is:

2013-11-11 23:11:46.110 Example[70636:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: index >= 0 && index < self._items.count'
*** First throw call stack:
(
0 CoreFoundation 0x01b195e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x017088b6 objc_exception_throw + 44
2 CoreFoundation 0x01b19448 +[NSException raise:format:arguments:] + 136
3 Foundation 0x010dbfee -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 Example 0x0000745b -[SDSegmentedControl segmentAtIndex:] + 363
5 Example 0x00006305 -[SDSegmentedControl setEnabled:forSegmentAtIndex:] + 69
6 Example 0x000033af -[ViewController disableSegment:] + 191
7 libobjc.A.dylib 0x0171a874 -[NSObject performSelector:withObject:withObject:] + 77
8 UIKit 0x0026b0c2 -[UIApplication sendAction:to:from:forEvent:] + 108
9 UIKit 0x0026b04e -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
10 UIKit 0x003630c1 -[UIControl sendAction:to:forEvent:] + 66
11 UIKit 0x00363484 -[UIControl _sendActionsForEvents:withEvent:] + 577
12 UIKit 0x00362733 -[UIControl touchesEnded:withEvent:] + 641
13 UIKit 0x002a851d -[UIWindow _sendTouchesForEvent:] + 852
14 UIKit 0x002a9184 -[UIWindow sendEvent:] + 1232
15 UIKit 0x0027ce86 -[UIApplication sendEvent:] + 242
16 UIKit 0x0026718f _UIApplicationHandleEventQueue + 11421
17 CoreFoundation 0x01aa283f CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 15
18 CoreFoundation 0x01aa21cb __CFRunLoopDoSources0 + 235
19 CoreFoundation 0x01abf29e __CFRunLoopRun + 910
20 CoreFoundation 0x01abeac3 CFRunLoopRunSpecific + 467
21 CoreFoundation 0x01abe8db CFRunLoopRunInMode + 123
22 GraphicsServices 0x031689e2 GSEventRunModal + 192
23 GraphicsServices 0x03168809 GSEventRun + 104
24 UIKit 0x00269d3b UIApplicationMain + 1225
25 Example 0x000022cd main + 141
26 Example 0x00002235 start + 53
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Buttons not centred correctly

Buttons are not centred correctly or the stainView isn't...

It is highly noticeable when changing the font of the buttons to a smaller point size, then you can also notice that the button items horizontal spacing doesn't take into account the real size of the button

Alignment fixes

Some adjustments :

  • Height of the tab container
  • Top positionning and height of the active tab background

Unable to set two unique themes in the same application?

I'd like to have two separate color schemes for color stain and text color. Is there a way to do this in the same application? I'm able to set the new one after initializing the first, but when I try to set it back to the original scheme, nothing happens.

Support for custom fonts

First off, thanks for this great control. It would be very helpful, if we could customize the titleLabel font for this control.

Shadow is being shown on top

On the native component, shadow is only shown on the bottom part of the view. I'm trying to fix it but with no luck

Strange issue regarding release

Release shows version 1.0.2, and when compared with master repo it is totally different. Also the source is not updated for cocoapods too.

Selection Indicator and its animation not working properly when control is subview of viewForHeaderInSection

I made a comment on issue 18, asking for it to be reopened, but I will also post it here new in case those do not get looked at. As in issue 18, I am also using SDSegmentedContol in viewForHeaderInSection; if you return the control itself as the entire view, there is no problem; but if you add it as a subview to a view (that will also contain other components) - the problem remains; specifically, when there is action on the SDSegmentedContol, I have it reload the entire tableview; SDSegmentedContol itself is a PART of the tableview in viewForHeaderInSection; viewForHeaderInSection gets called and while SDSegmentedContol does not get recreated, it gets added to the view that is returned for the header in the section. This is how I MUST do this to achieve the tableview effect that I need. So each time a 'segment' is selected, the tableview is reloaded and this control is added to the viewForHeaderInSection, and the arrow fails to animate properly - it does not move to the correct segment. If I do the same thing with a regular UISegmentedControl, it works perfectly.

Warnings

any chance to fix these warnings?

schermata 2013-05-23 alle 18 17 35

Problem under IOS8 for borderColor and borderWidth

This works fine under IOS7 and lower, under IOS8 the first time we push the view containing he SDSegmentControl all is ok. the next time around (Go back to previous view and back to this view) the segmentControl looses appearance setting we push it see below code for the border color and width.

SDSegmentedControl *segmentedControlAppearance = SDSegmentedControl.appearance;
segmentedControlAppearance.backgroundColor = [UIColor colorWithHex:@"#453e34" alpha:alpha];
segmentedControlAppearance.borderColor = [UIColor whiteColor];
segmentedControlAppearance.arrowSize = 10;
segmentedControlAppearance.arrowHeightFactor = 1;
segmentedControlAppearance.arrowPosition = SDSegmentedArrowPositionTop;
segmentedControlAppearance.borderWidth = 1;

we see the black defaults being drawn in black if we are on IOS8
which is inited under commonInits as

// Init border bottom layer
[self.layer addSublayer:_borderBottomLayer = CAShapeLayer.layer];
if (!SD_IS_IOS7) {
self.borderColor = UIColor.whiteColor;
self.borderWidth = .5;
} else {
self.borderColor = UIColor.blackColor;
self.borderWidth = .25;
}

The fix I used was to directly set the color to withe and the width to 1 under this init bypassing the usage of the appearance setter.

This was the way I initially was setting in my viewDidLoad of the view being pushed as follows

- (void)segmentControlInit {
// self.segmentControl.backgroundColor = [UIColor colorWithHex:@"#453e34" alpha:alpha];

SDSegmentedControl *segmentedControlAppearance = SDSegmentedControl.appearance;
segmentedControlAppearance.backgroundColor = [UIColor colorWithHex:@"#453e34" alpha:alpha];
segmentedControlAppearance.borderColor = [UIColor whiteColor];
segmentedControlAppearance.arrowSize = 10;
segmentedControlAppearance.arrowHeightFactor = 1;
segmentedControlAppearance.arrowPosition = SDSegmentedArrowPositionTop;
segmentedControlAppearance.borderWidth = 1;

SDSegmentView *segmenteViewAppearance = SDSegmentView.appearance;`

[segmenteViewAppearance setTitleColor:[UIColor colorWithRed:0.71 green:0.7 blue:0.7 alpha:1] forState:UIControlStateNormal];
[segmenteViewAppearance setTitleColor:[UIColor colorWithHex:@"#70ae47" alpha:1] forState:UIControlStateSelected];
segmenteViewAppearance.titleShadowOffset = CGSizeZero;

`SDStainView *stainViewAppearance = SDStainView.appearance;`

stainViewAppearance.backgroundColor = [UIColor clearColor];
stainViewAppearance.shadowColor = [UIColor colorWithHex:@"#453e34" alpha:1];
stainViewAppearance.shadowBlur = 0;
stainViewAppearance.shadowOffset = CGSizeZero;
}

Crashes when disabling a segment

When disabling a segment:

[self.typeSegmentedControl setEnabled:NO forSegmentAtIndex:PlaySegmentIndex];

Crashes with:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds for empty array'

Control not displayed properly after rotating in another view controller

I'm not sure if it is linked to issue #44, but I have found another bug: when rotating the device when the segmented control is not visible (i.e. in another view controller) and then returning to the view controller again, the paths aren't drawn correctly.

To reproduce:

Create an empty iOS application, add SDSegmentedControl and use this as the application: didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    UIViewController *firstVC = [[UIViewController alloc] init];
    firstVC.title = @"Segment";
    UIViewController *secondVC = [[UIViewController alloc] init];
    secondVC.title = @"Dummy";

    SDSegmentedControl *segmentController = [[SDSegmentedControl alloc] initWithItems:@[@"1", @"2"]];
    segmentController.frame = CGRectMake(0, 0, self.window.frame.size.width, segmentController.frame.size.height);

    [firstVC.view addSubview:segmentController];

    UITabBarController *rootController = [[UITabBarController alloc] init];
    [rootController addChildViewController:firstVC];
    [rootController addChildViewController:secondVC];
    self.window.rootViewController = rootController;
    [self.window makeKeyAndVisible];
    return YES;
}

Now start the application. The following scenario works as expected:

  • Switch to second tab
  • Rotate device to landscape
  • Switch back to first tab

But the following does not work as expected:

  • Rotate the device to landscape and back to portrait
  • Switch to second tab
  • Rotate device to landscape
  • Switch back to first tab

In this second case, the paths that are drawn only occupy the 320 points of the portrait mode.

I already found that it goes wrong in the function that draws the paths and only when the duration > 0. But then I got stuck trying to fix it...

SDSegmentedControl init from nib, how sizing works?

It is not entirely clear to me how SDSegmentedControl's width is setup. I dropped an UISegmentedControl to iPhone sized view which is used in an universal app and changed it class to be SDSegmentedControl, then in viewDidLoad I add various segments by '- insertSegmentWithTitle:atIndex:animated:'. At the end segmented control's view is way larger than expected.

How to make it respect sizing and auto–resizing specified in xib, so that users would scroll horizontally to tap on additional segments please?

Thanks.

Podfile - not usable with cocoapods?

For some reason, I can't find SDSegmentedControl using

pod search sdseg

When I put it in my Podfile. it comes back with:

Unable to find a pod named `SDSegmentedControl'

... when I try to install or update.

Request: Arrow color

Im trying to make it look like the segment control is part of a UINavigation bar but since the arrow is clear i can still see the navigation bar bit under it, but if it were white it would look like its built into it.

SDSegmentedControl hard-freezes iOS devices

SDSegmentedControl manages to hard-freeze iOS (6.x), so that only a forced shutdown makes it work again. I have created a minimal example that puts the blame on a combination of arrowSize = 0.0 and adding segments at runtime. My theory is that one of the UIKit and/or CoreGraphics library functions is called with an excessive parameter (CGFLOAT_MAX anywhere?) that makes the graphics card go havoc. Here is the minimal example. Note that the simulator handles this case without problems, just the devices (tested on multiple phones and pods) hard-freeze.

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [_segmentedControl removeAllSegments];
    _segmentedControl.arrowSize = 0.0;

    [self performSelector:@selector(createMoreSegments:) withObject:nil afterDelay:2.0];

}

- (void)createMoreSegments:(id)sender
{
    for ( int i = 0; i < 5; ++i )
    {
        [_segmentedControl insertSegmentWithTitle:[NSString     stringWithFormat:@"Segment %u", i] atIndex:i animated:NO];
    }
}

@end

Center segment

Hi all, can I center selected segment programmatically?

For example, after I set Selected Index, can I center selected segment into scrollable nav bar?

[self.segmentedControl setSelectedSegmentIndex:5];
???

Thanks

Luca

Issue with Swift

According to the example I created a sample project in swift targeting iOS 8.1 but it didn't work out as expected. I couldn't get the sample control to be visible even though view debugging showed the view does exist. There must be something wrong with the default appearance...

Crash in iOS8

Hi, I get Crash log as below:

Crashed: com.apple.main-thread
SIGABRT ABORT at 0x00000001956cf270
raw
libsystem_kernel.dylib
__pthread_kill + 8
libsystem_c.dylib
basename
CoreGraphics
CG::Path::move_to_point(CGPoint const&, CGAffineTransform const*)
UIKit
+[UIBezierPath _continuousRoundedRectBezierPath:withRoundedCorners:cornerRadii:segments:smoothPillShapes:] +
UIKit
+[UIBezierPath _continuousRoundedRectBezierPath:withRoundedCorners:cornerRadius:segments:] +
SDSegmentedControl.m line 1316
-[SDStainView drawRect:]

Support cocoapods

Have you got plans to add your project to CocoaPods?
It will be very useful :)

iOS 7 desaturation

Any chance to have the controller responding to tintColorDidChange (like the UISegmentedControl does)?

Crashed on IOS 7 beta...

and I tested my app with XCode5 beta1,below is the error info:
2013-06-13 10:58:03.867 ...... *** Assertion failure in -[SDSegmentedControl setSelectedSegmentIndex:], ...../SDSegmentedControl/SDSegmentedControl.m:269
2013-06-13 10:58:03.980 ..... *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: selectedSegmentIndex < (NSInteger)self._items.count'

so the problem:

  • (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex
    {
    if (_selectedSegmentIndex != selectedSegmentIndex)
    {
    NSParameterAssert(selectedSegmentIndex < (NSInteger)self._items.count);
    _lastSelectedSegmentIndex = _selectedSegmentIndex;
    _selectedSegmentIndex = selectedSegmentIndex;
    [self setNeedsLayout];
    }
    }

after removed " NSParameterAssert(selectedSegmentIndex <(NSInteger)self._items.count);"
the error info:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]'

cannot set selected segment from NIB other than 1st (crash)

I have two view controller that is to be switched by the SegmentControl, so for the 2nd VC I need to set the selected index to be the 2nd item,

and when I do that in NIB, it crashes
'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: selectedSegmentIndex < (NSInteger)self._items.count'
because self._items is null when this is called.
NSParameterAssert(selectedSegmentIndex < (NSInteger)self._items.count);

and if set "selectedIndex" in viewDidLoad code, then it doesn't show the arrow correctly, the title highlight animate to the right selection, but arrow remains unchanged..

net net, I cannot set the initial selectedIndex to anything other than 1

iOS 7 Issue - selectedSegmentIndex < (NSInteger)self._items.count

I get following error on iOS 7, which is working fine for iOS5,6

*** Assertion failure in -[SDSegmentedControl setSelectedSegmentIndex:]

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: selectedSegmentIndex < (NSInteger)self._items.count'

SDStainView backgroundColor is broken on iOS6

it appears black (because when it reaches drawRect self.backgroundColor is nil for some reasons).

even changing it from the uiappeareance protocol doesn't make any difference.

it looks like this a0ff092 doesn't work on iOS6 when compiled with the new sdk (xcode 5).

Scrolling with bigger items is wrong

After having 5 items in the Example project named 'Big Segment x' I found out the the scrolling is not correct.
Even with fewer items that result to a width bigger than the view bounds, the scrolling is not enabled, although it should have been.
I had a look at the code and it seems that the items' frames are correctly set. Could not locate the error though, most probably it is a wrong setting of the scrolling offset.

Could you please take a look at the issue?

Image support

Hi,
do you plan to implement the image support? The UISegmentedControl can be initialised with a list of images instead of strings.

cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.