Custom Segmented Control in Swift for iOS - ios

I'm trying to implement a segmented control but it seems so simple in the layout. I want to customize it:
lose the borders for instance
have a custom indicator
What would be the way to do it? I know in Android how to customise an TabLayout but here I'm lost to be honest.

I'm quite late to the party, but here's what I'd do:
Set the background color to .clear
segmentedControlInstance.backgroundColor = UIColor(red:0.13, green:0.16, blue:0.29, alpha:1.0)
Set the background tint color to .clear
segmentedControlInstance.tintColor = .clear
I noticed the selected segment's title is bold. Set the text attributes for the two states (.normal & .selected)
segmentedControlInstance.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.white, NSAttributedStringKey.font: UIFont.systemFont(ofSize: 16)], for: .normal)
segmentedControlInstance.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.white, NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 16)], for: .selected)
Finally, set the two background images. Caution, I have no idea what to set for the barMetrics parameter:
segmentedControlInstance.setBackgroundImage(UIImage(name: "selectedSegment", for: .selected, barMetrics: ?)
segmentedControlInstance.setBackgroundImage(UIImage(name: "normalSegment", for: .normal, barMetrics: ?)
I'll let you play around with the barMetrics parameters.

If what I need to customize wasn't on this list, UISegmentedControl Docs, I'd build my own.
In your image, I'd use two buttons, a view for the indicator, and some logic to respond to user interactions.

Related

iOS 11-12 large title background image for large state

I am trying to set different colors for different navigation bar large title states. For base large title state(when it's large and not scrolled) bar should have grayColor(i am setting barTint color), but when the user scrolls content and bar is attached to top(goes to UIBarPosition.topAttached) it should have white color, so I am setting background image for .topAttached state, and because of that image my barTint color is ignored.
I've tried to set background image for all possible nav bar UIBarPosition's and UIBarMetrics, and for topAttached state image work's well, but for large state it never appeared. Example:
bar.setBackgroundImage(.pixel(color: UIColor.red), for: .any, barMetrics: .default)
bar.setBackgroundImage(.pixel(color: UIColor.green), for: .topAttached, barMetrics: .default)
bar.setBackgroundImage(.pixel(color: UIColor.blue), for: .bottom, barMetrics: .default)
bar.setBackgroundImage(.pixel(color: UIColor.purple), for: .top, barMetrics: .default)
Is there any way to make different colors for different large title states in iOS 11-12?
Finally found solution, works for iOS 11-12:
let observer = navBar.observe(\.frame, changeHandler: { (bar, frame) in
if navBar.frame.height <= 44 {
navBar.barTintColor = UIColor.lightGray
navBar.shadowImage = imageForShadow
}
else {
navBar.barTintColor = UIColor.white
navBar.shadowImage = UIImage()
}
})

How to change the background color of TabBar title string only in swift code

I'd like to put a background color for just the title of TabBar using swift I tried to use NSAttributedString.Key.backgroundColor but it not appears color in the background.
Can anybody help me to change the background color for just the title of TabBar?
I need to add yellow color to the background to title in the normal state not selected.
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.white], for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.gray], for: .selected)
This works for a single item. If you'd like to change the color for all items in the tab bar, try parsing through them like such
for item in self.tabBar.items! {
item.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.white], for: .normal)
item.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.gray], for: .selected)
}
you can add the following code snippet to your viewDidLoad:
UITabBar.appearance().barTintColor = UIColor.black // your color

Change title text color of a specific segment in UISegmentedControl?

How can I change the text color of just one specific segment of a UISegmentedControl? I want to keep them all normal, except for a specific segment which should be a different color, whether it is selected or not.
#IBDesignable
class DesignableSegmentControl: UISegmentedControl{
}
extension UISegmentedControl{
#IBInspectable
var textColor: UIColor{
get {
return self.textColor
}
set {
let unselectedAttributes = [NSAttributedString.Key.foregroundColor: newValue,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: UIFont.Weight.regular)]
self.setTitleTextAttributes(unselectedAttributes, for: .normal)
self.setTitleTextAttributes(unselectedAttributes, for: .selected)
}
}
}
Just change you segment control's class name as shown below:
[change class name]:
[change text color]:
for swift 5:
yourSegment.setTitleTextAttributes( [NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
Updated Swift 4.1
UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.red], for: .selected)
Swift 3.1
UISegmentedControl.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red as Any], for: .selected)
For Earlier Swift Version:
UISegmentedControl.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red], for: .selected)
There isn't any built-in way; as you've probably figured out, setTitleTextAttributes applies to all the segments. You would have to draw your text as an image and use that instead.
Just add this line of code:
UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: .selected)
You can implement your own segmented control for customisation.
Add two buttons with same UI as segmented control.
Round the corners.
On click make the background colour according to your need and clear back ground of other and make it unselected.
In this way there is large scope for customisation.
Also there are many custom segmented control are available at GitHub.
You can try this
https://github.com/gmarm/BetterSegmentedControl

Is it possible to change a UITabBarController text color after it's been loaded?

I'd like to change the UITabBarControllers text color after it's been loaded based on the users actions.
I can call this, and it changes the font and color correctly when it launches.
let appearance = UITabBarItem.appearance()
let attributes: [String: AnyObject] = [NSFontAttributeName:UIFont(name: "American Typewriter", size: 12)!, NSForegroundColorAttributeName: UIColor.green]
appearance.setTitleTextAttributes(attributes, for: .normal)
When I try to call this anytime after the app has fully launched though, nothing happens.
Is this possible, or is it a one time thing you can do at launch?
It looks like if i iterate over all the items and set them manually it works. I then need to re-set the selected items color.
Still not sure why the other way won't work?
for myItem in (tabBar.items)! {
myItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red], for: .normal)
}
tabBar.selectedItem?.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.green], for: .normal)

Swift: Remove a UIButton attributedTitle

If a UIButton has both a title and an attributedTitle set, the attributedTitle is the one that shows.
If I set a button to an attributed title:
myButton.setAttributedTitle(myAttribText, for: .normal)
and later in the app I want to set the button to a regular title:
myButton.setTitle(myRegularText, for: .normal)
Is there a line of code I can use to remove the attributedTitle on the button so that it will not override the new title I have set for the button? Thanks!
You need to set the AttributedTitle to nil before setting using setTitle for your button, Its working i have checked it.
like this
myButton.setAttributedTitle(nil, for: .normal)
myButton.setTitle(myRegularText, for: .normal)
If you use the underline attribute, you should to set the AttributedTitle by this method like this:
myButton.setAttributedTitle(NSAttributedString(string: myRegularText, attributes: nil), for: .normal)

Resources