Remove Uisegmentedcontrol Separators Completely. (Iphone)

Remove UISegmentedControl separators completely. (iphone)

No, there is not. You should look into creating the UISegmentedControl functionality manually. Maybe use two UIButtons.

How to remove border from segmented control

What you must understand is the backgroundColor property is not stateful.
Hence you have to use setBackgroundImage(_:for:barMetrics:).

We can easily remove both borders and dividers using the below function.

For Swift 3 & 4+:

extension UISegmentedControl {
func removeBorders() {
setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}

// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}

For Swift 2.2:

extension UISegmentedControl {
func removeBorders() {
setBackgroundImage(imageWithColor(backgroundColor!), forState: .Normal, barMetrics: .Default)
setBackgroundImage(imageWithColor(tintColor!), forState: .Selected, barMetrics: .Default)
setDividerImage(imageWithColor(UIColor.clearColor()), forLeftSegmentState: .Normal, rightSegmentState: .Normal, barMetrics: .Default)
}

// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image
}
}

Call the above function.

segmentedControl.removeBorders()

Reference: Remove UISegmentedControl separators completely. (iphone)

Thanks to https://stackoverflow.com/users/3921490/amagain for Swift 3 version.

UISegmentedControl iOS 13 clear color

Here's a way to replicate that plain segmented control in iOS 13:

import UIKit
import PlaygroundSupport

class PlainSegmentedControl: UISegmentedControl {
override init(items: [Any]?) {
super.init(items: items)

setup()
}

override init(frame: CGRect) {
super.init(frame: frame)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// Used for the unselected labels
override var tintColor: UIColor! {
didSet {
setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
}
}

// Used for the selected label
override var selectedSegmentTintColor: UIColor? {
didSet {
setTitleTextAttributes([.foregroundColor: selectedSegmentTintColor ?? tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
}
}

private func setup() {
backgroundColor = .clear

// Use a clear image for the background and the dividers
let tintColorImage = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
setBackgroundImage(tintColorImage, for: .normal, barMetrics: .default)
setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

// Set some default label colors
setTitleTextAttributes([.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
}
}

Here's some test code to put in a playground:

// Create a dark green view as a test background
let bg = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
bg.backgroundColor = UIColor(red: 0.224, green: 0.408, blue: 0.467, alpha: 1)

// The plain segmented control
let seg = PlainSegmentedControl(items: ["Number One", "Number Two", "Number Three"])
seg.tintColor = .white
seg.selectedSegmentTintColor = .green
seg.selectedSegmentIndex = 0
bg.addSubview(seg)
PlaygroundPage.current.liveView = bg

Here's the UIImage extension to create a sized image from a color:

extension UIImage {
convenience init(color: UIColor, size: CGSize) {
UIGraphicsBeginImageContextWithOptions(size, false, 1)
color.set()
let ctx = UIGraphicsGetCurrentContext()!
ctx.fill(CGRect(origin: .zero, size: size))
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()

self.init(data: image.pngData()!)!
}
}

Remove frame of UISegmentedControl

First, create three images and add them your your Image Assets.

  • Blank (a transparent png of any size)
  • Highlight (a png of any color and size)
  • Select (a png of any color and size)

Xcode Image Assets Catalog showing Blank, Highlight, and Select image sets added

Then add this code:

UIImage *backgroundImage = [UIImage imageNamed:@"Blank"];
UIImage *highlightedImage = [UIImage imageNamed:@"Highlight"];
UIImage *selectedImage = [UIImage imageNamed:@"Select"];
UIImage *dividerImage = [[UIImage alloc] init];
[segmentedControl setBackgroundImage:backgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[segmentedControl setBackgroundImage:highlightedImage forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[segmentedControl setBackgroundImage:selectedImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[segmentedControl setDividerImage:dividerImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

UISegmentedControl with clear background and no frame. Selected color is blue. Highlighted color is light blue.

UISegmentedControl does not respect divider images set for UIControlStateDisabled

I've decided that this must be an iOS bug and have filed a radar with Apple. My solution to the problem for now is to remove segments, rather than disabling them.

UISegmentedControl with custom color: separator line bug

Wow... When we write were in stackoverflow, we can calm down and think better. I write the answer in my ow question:

If I go from right to left it not happens.

This is the solution! What I have to do? Simulate this.

BOOL inside = FALSE;
- (void)changeColor{
int old = segmentedControl.selectedSegmentIndex;
for (int i=0; i<3; i++) {
[segment[i] setTintColor:[UIColor lightGrayColor]];
}
/**/inside = TRUE;
/**/for (int i=3; i>0; i--) {
/**/ //When I do this, it call "segmentedControl:"
/**/ [segmentedControl setSelectedSegmentIndex:i];
/**/}

/**/int select = old;
[segment[select] setTintColor:[UIColor blueColor]];
[segmentedControl setSelectedSegmentIndex:select];
/**/inside = FALSE;
}

- (void)segmentedControl:(id)sender
{
/**/if (inside==TRUE) return; //Ignore this calls.
//do some thing
[self changeColor];
}

UISegmentedControl in iOS 7 divider image is wrong during animation

I solved this in a way similar to what user2128193 describes, but instead of adding a target for the value changed event, I subclassed UISegmentedControl and added these two methods:

- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents
{
[super sendActionsForControlEvents:controlEvents];

if (controlEvents & UIControlEventValueChanged) {
[self removeAnimationsRecursivelyForView:self];
}
}

- (void)removeAnimationsRecursivelyForView:(UIView *)view
{
[view.layer removeAllAnimations];

for (UIView *subview in [view subviews]) {
[self removeAnimationsRecursivelyForView:subview];
}
}

Obviously this is still not a perfect solution, in that it relies on the internals of UISegmentedControl, but at least it will keep your code a bit cleaner.



Related Topics



Leave a reply



Submit