18

I have been using UITabbar in an app. There is an upper border line coming in top of the UITabbar. Refer below image :-

I Googled it and tried the suggested code like :-

[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];

Also

[[UITabBar appearance] setShadowImage:nil];

self.navigationController.toolbar.clipsToBounds = YES;

But none of them is working. Any solution?

enter image description here

Awesome.Apple
  • 1,316
  • 1
  • 11
  • 24

11 Answers11

23

tabBar.clipsToBounds = YES; works for me.

Bill
  • 44,502
  • 24
  • 122
  • 213
Allen
  • 6,745
  • 5
  • 41
  • 59
13
[self.tabBar setValue:@(YES) forKeyPath:@"_hidesShadow"];

or you can use

[[UITabBar appearance] setShadowImage:[UIImage imageNamed:@"transparentShadow.png"]];

or

 [[UITabBar appearance] setShadowImage:nil];
Usama
  • 548
  • 3
  • 12
13

Working solution with iOS 13 & Swift 5:

/** 
 * A custom subclass of `UITabBarController` to use whenever you want 
 * to hide the upper border of the `UITabBar`.
 */
class TabBarController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tabBar.backgroundColor = UIColor.white

        // Removing the upper border of the UITabBar.
        // 
        // Note: Don't use `tabBar.clipsToBounds = true` if you want 
        // to add a custom shadow to the `tabBar`!
        // 
        if #available(iOS 13, *) {
            // iOS 13:
            let appearance = tabBar.standardAppearance
            appearance.configureWithOpaqueBackground()
            appearance.shadowImage = nil
            appearance.shadowColor = nil
            tabBar.standardAppearance = appearance
        } else {
            // iOS 12 and below:
            tabBar.shadowImage = UIImage()
            tabBar.backgroundImage = UIImage()
        }
    } 
}
Baran
  • 2,710
  • 1
  • 23
  • 23
7

This worked for me for iOS 11, XCode 9.4

UITabBar.appearance().shadowImage = UIImage()
UITabBar.appearance().backgroundImage = UIImage()
UITabBar.appearance().backgroundColor = UIColor.white
Miha Hribar
  • 5,776
  • 3
  • 26
  • 24
5

Swift 5 Works for me

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        myTabBar.clipsToBounds = true


    }
omar alfawzan
  • 51
  • 1
  • 2
3

Improving on one of the answers above - still a bit of a hack but works better. The answer above would hide the imageView with custom image.

    for tabBarSubview in self.tabBar.subviews {
        let tabBarSubviewName = String(describing: type(of: tabBarSubview))
        guard tabBarSubviewName == "_UIBarBackground" else { continue }
        tabBarSubview.clipsToBounds = true
    }
videolist
  • 219
  • 3
  • 4
1

You need to add only this two line of code for remove border from your UITabbar:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {


    [[UITabBar appearance] setBackgroundImage:[[UIImage alloc] init]];
    [[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
    // Override point for customization after application launch.
    return YES;
}

Before:

enter image description here

After:

enter image description here

UPDATE: You canset background image as well and set shadow as a nil like following code

    UIImage* tabBarBackground = [UIImage imageNamed:@"tabbar.png"];
    [[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
    [[UITabBar appearance] setBackgroundImage:tabBarBackground];

OUTPUT:

enter image description here

Nitin Gohel
  • 49,482
  • 17
  • 105
  • 144
1

shadowImage property of UITabbar is responsible for this border line (gray colored shadow) on UITabbar. Update value of this property to remove it.

Try this, ** Objective-C **

//Remove shadow image by assigning nil value.
[[UITabBar appearance] setShadowImage: nil];

// or 

// Assing UIImage instance without image reference
[[UITabBar appearance] setShadowImage: [[UIImage alloc] init]];

** Swift **

//Remove shadow image by assigning nil value.
UITabBar.appearance().shadowImage = nil

// or 

// Assing UIImage instance without image reference
UITabBar.appearance().shadowImage = UIImage()


Here is apple guideline for shadowImage

@available(iOS 6.0, *)
open var shadowImage: UIImage?

Default is nil. When non-nil, a custom shadow image to show instead of the default shadow image. For a custom shadow to be shown, a custom background image must also be set with -setBackgroundImage: (if the default background image is used, the default shadow image will be used).

Krunal
  • 77,632
  • 48
  • 245
  • 261
0

I could not find an answer without clipping to bounds. And the way using UITabBar.appearance().shadowImage seems to be outdated

So I made a not perfect but working and safe solution to remove UITabBar shadow for iOS10 and iOS11 without clipping to bounds. Works on iPhone X too (would be strange if it did not ;) )

The code below runs through the UITabBarController hierarchy and looks for a shadow view. Which (for now) is UIImageView that is a subview of _UIBarBackground

extension UITabBarController {
    public func hideTopShadow() {
        // looking for tabBar
        for subview in self.view.subviews {
            let tabBarSubviewName = String(describing: type(of: subview))
            guard tabBarSubviewName == "UITabBar" else { continue }

            // looking for _UIBarBackground. The other subivews are UITabBarButtons
            for tabBarSubview in subview.subviews {
                let tabBarSubviewName = String(describing: type(of: tabBarSubview))
                guard tabBarSubviewName == "_UIBarBackground" else { continue }

                // looking for UIImageView. This is the only subview
                for shadowView in tabBarSubview.subviews where shadowView is UIImageView {
                    shadowView.isHidden = true
                    return
                }
            }
        }
        print(" **** ERROR: Could not find the shadow view \(self.self) \(#function)")
    }
}

Possible usage. I have a subclass of UITabBarController so I did following:

// to avoid excessive runs through the hierarchy after the shadow was hidden
fileprivate var hasHiddenShadow: Bool = false

override open func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    guard !hasHiddenShadow else { return }

    hasHiddenShadow = true
    DispatchQueue.main.asyncAfter(deadline: .now()) {
        self.hideTopShadow()
    }
}
Pavel Stepanov
  • 891
  • 8
  • 13
0

update your controller method

override func viewDidLoad() {
    super.viewDidLoad()
    self.tabBar.clipsToBounds = true
    if #available(iOS 13, *) {
        self.tabBar.standardAppearance.shadowImage = nil
        self.tabBar.standardAppearance.shadowColor = nil
    }
}
0

self.navigationController?.setNavigationBarHidden(true, animated: true)

worked for me