Non Standart UITabBarItem Action - swift

I have UITabBarController with view
So on every TabBar I have ViewController. But on my center UITabBarItem I need to call something like modal UIViewController. And It should be like this
My UITabBarController class look like
class PlanetTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.tintColor = kTintColor
var items = self.tabBar.items as! [UITabBarItem]
let centredTabBar:UITabBarItem = items[2]
self.tabBar.layer.borderWidth = 0.50
centredTabBar.image = ktabCentredBarImage
self.tabBar.layer.borderColor = UIColor.clearColor().CGColor
self.tabBar.layer.borderWidth = 0
self.tabBar.shadowImage = UIImage()
// self.tabBar.backgroundImage = ktabBarImage
self.tabBar.backgroundImage?.imageWithAlignmentRectInsets
print( UIDevice.currentDevice().modelName)
if( UIDevice.currentDevice().modelName != "iPhone 6" && UIDevice.currentDevice().modelName != "iPhone 6 Plus") {
self.tabBar.backgroundImage = ktabBarImage
}
if( UIDevice.currentDevice().modelName == "iPad 2" ) {
self.tabBar.backgroundImage = ktabBarImage
}
if let font = UIFont(name: "Avenir-Black", size: 10) {
let appearance = UITabBarItem.appearance()
let attributes = [NSFontAttributeName:font]
appearance.setTitleTextAttributes(attributes, forState: UIControlState.Normal)
}
}
}
I really have no idea how to override standart calling of UIViewController and call modal like this =) Please give me advice where I need to search

You can either place a UIButton in the same area as the UITabBarItem and fire an action or you can simply fire an action when the selectedSegmentIndex changes("value changed" in IB) for the UITabBar after creating a center UITabBarItem. The design choice is yours. The first step is to understand the objects you're working with. It would probably be easier to just add a button, center aligned, over top of the standard UITabBar at the bottom so you don't deal with a custom UITabBarController to handle that non-uniform image above the tab bar.
Or just create your own TabBar down there. It's very simply to setup a few UIButtons or UIViews next to one another that don't have a static height such as a UITabBarController which would allow for that center object.
UITabBarController
UIViewController
Presenting a ViewController

Related

How to make UITabBar blurry, in Swift

I am trying to make UITabBar look blur.
I am trying to make something like this in this image
But my view now looks like this
This is my view for tabbar
I tried this code in UITabbarController -
Code:
class TabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
configureTabbar()
}
func configureTabbar(){
let blurEffect = UIBlurEffect(style: .dark)
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect)
let vibrancyView = UIVisualEffectView()
vibrancyView.frame = tabBar.bounds
vibrancyView.autoresizingMask = .flexibleWidth
vibrancyView.effect = vibrancyEffect
tabBar.insertSubview(vibrancyView, at: 0)
tabBar.isTranslucent = true
tabBar.backgroundImage = UIImage()
tabBar.backgroundColor = .clear
tabBar.barStyle = UIBarStyle.black
tabBar.barTintColor = UIColor.clear
}
System bars such as UINavigationBar, UITabBar & UIToolbar are translucent by default and you don't need to add anything extra to get that effect.
You just need to make sure that your view extends it's content under system bars. You can go to storyboard and make sure the Extend Edges - Under Bottom Bars is checked for your UIViewController that you plan to see this effect on.

TabBar controls the NavigationBar

I added 2 ViewControllers into a TabBar, but now, the TabBar's NavigationBar 'took over' each view's NavigationBar.
I can't set a title for each one of them, I can't add buttons, nothing.
I tried a few solutions to solve it that I found on the internet, but nothing worked.
I need control over the NavigationBar of each one of the views, as I need them to be different, with different title, etc.
This is my TabBar code:
class TabBar: UITabBarController {
let homeVC = HomeVC()
let followingVC = FollowingVC()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.appColors.mainWhite]
navigationController?.navigationBar.tintColor = UIColor.appColors.mainWhite
navigationItem.setHidesBackButton(true, animated: false)
homeVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 0)
followingVC.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let tabBarList = [homeVC, followingVC]
viewControllers = tabBarList
}
}
I really need the option to configure each NavigationBar from it's own ViewController, or atleast from the TabBar class.
You should add UINavigationController to each of your ViewControllers not your UITabBarController
First remove the UINavigationController of your TabBar, Either you have done this pragmatically or in the storyboard remove that first.
Second add UINavigationController to you ViewControllers
class TabBar: UITabBarController {
let homeVC = HomeVC()
let followingVC = FollowingVC()
override func viewDidLoad() {
super.viewDidLoad()
homeVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 0)
followingVC.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let homeNavigationController = UINavigationController(rootViewController: homeVC)
let followingNavigationController = UINavigationController(rootViewController: followingVC)
let tabBarList = [homeNavigationController, followingNavigationController]
viewControllers = tabBarList
}
}
Now if you change any properties like title and barButtons it will reflect accordingly.
Figured it out, the solution is:
The NavigationBar was not the TabBar navigation bar, but the screen that lead to the TabBar (Login Screen for example), I fixed it by hidding the navigation bar of the login screen when transfering to the TabBar controller, now the navigation bar of each view controller is shown and not blocked by the Login Viewcontrolelr navigationbar.

setting custom icons in tabbar for highlighted/not highlighted

I have icons in my assets that I want to use for my tab bar, 2 for each tab (one representing not highlighted i.e just an outline, and one representing highlighted i.e all filled in). The idea is to use the outlined icons for the tabs that aren't currently selected, and the filled in one for the tab that is currently selected. How can I go about doing this?
Just make an Class for your Tabbar, for example:
class MainTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
for item in self.tabBar.items! as [UITabBarItem] {
// loop through all of your elements in TabBar
if let image = item.image {
item.selectedImage = your Selected Image
item.image = your base Image
}
}
}
You could store all your images in an Array containing UIImage, like:
let TabImages = [UIImage]()
let HighlightedImages = [UIImage]()
And then set them in your for each loop.
var tabBarController = self.window!.rootViewController as UITabBarController
let tabItems = tabBarController.tabBar.items as [UITabBarItem]
tabItems[2].selectedImage = UIImage(named: "tabImage1_Selected")

Swift Navigation Bar Button and Title don't appear

I'd like to create a Navigation bar on top of my App. I created an Navigation Controller -> Tab Bar Controller -> Navigation Controller -> Table Controller
I dragged a Bar Button Item on the upper right side.
I double clicked the title in the middle of the Table Controller and wrote a text.
I also tried it with this code in the viewDidLoad() of my controller:
self.navigationController.navigationBar.topItem.title = "some title"
self.navigationItem.setRightBarButtonItem(UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "barButtonItemClicked:"), animated: true)
self.navigationItem.title = "YourTitle"
Non of it worked - what am I doing wrong? :/
You can try something like this:
self.title = "Your Title"
var homeButton : UIBarButtonItem = UIBarButtonItem(title: "LeftButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
var logButton : UIBarButtonItem = UIBarButtonItem(title: "RigthButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
I believe you are looking for a titleView.
Try:
var navBarTitleView = UIView(frame: CGRectMake(0.0, 0.0, self.view.frame.width, 44.0))
navBarTitleView.backgroundColor = UIColor.brownColor()
self.navigationItem.titleView = navBarTitleView
I am pretty sure that you can just set the title of your table controller, in its viewDidLoad, which is the title displayed in your navigation bar.
this answer explains a slightly different question, but the concept is the same:
https://stackoverflow.com/a/25167491/2070902
if you want to set your "UINavigationBar" according to your wish Please follow this very safely ,its so simple in swift language ,hope it will help you a lot .
STEP 1:-
Create a category class in swift just go on "New file" and add "Simple swift class " and given it name "MyCustomNavBarCategory.swift"
STEP 2:-
Just "Clean the class (remove all code from this class)" and "Paste my give code below" :-
//class will Start from below line start copy from here
let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
import UIKit
extension UINavigationBar {
//First increase navigation bar height .
override public func sizeThatFits(size: CGSize) -> CGSize {
NSLog("%f", SCREEN_HEIGHT*0.06);
let newSize:CGSize = CGSizeMake(self.frame.size.width, SCREEN_HEIGHT*0.10)
return newSize;
}
//then set layOut of your Custom Nav for several objects like titleview,buttons and all
public override func layoutSubviews() {
for var view in self.subviews
{
NSLog("view %#", view);
let str :String = view.classForCoder.description();
if(str == "UILabel")
{
//play with title view frame
var f = view.frame;
f.origin.y = self.frame.size.height/2 - view.bounds.size.height/2 ;
view.frame = f;
view.backgroundColor = UIColor.greenColor();
}
else if(str == "UIButton")
{
//play with buttons of navigation bar view frame
var f = view.frame;
f.origin.y = (self.frame.size.height/2) - (view.bounds.size.height/2) ;
view.frame = f;
view.backgroundColor = UIColor.greenColor();
}
}
}
}
//class will end on above stop copy code on above line and just past this in to your "MyCustomNavBarCategory.swift". that's it enjoy ;).
STEP 3:-
Now you can set any frame to any object of UINavigationBar in this class "It's very powerful category of UINavigationBar if you will implement it carefuly".

Menu from tab bar in storyboarding

At the moment I have a standard tab bar, when tapped goes to its corresponding viewController. But I want to make a menu pop out from tab bar when more tab is selected, as shown in below image.
Is any suggestion to implement this?
Thanks in advance.
I would recommend you do so:
First, you should think of all the tab types that could be in tab bar. On your screenshot there are tabs, that present controller, and tab, that presents menu. So we could create enum with all these types:
enum TabType {
case controller
case menu
}
After that you can store array of tab types in order they are shown in tab bar, for your screenshot like so
let tabTypes: [TabType] = [.controller, .controller, .controller, .controller, .menu]
Then you should implement UITabBarControllerDelegate's func tabBarController(_:, shouldSelect:) -> Bool method, which returns true if tab bar is allowed to select the passed controller, and false otherwise.
If you return true than all other work (like presenting view controller and other stuff) tab bar controller will do for you.
In your case you want to execute custom action on tab click, so you should return false. Before returning you should present your menu.
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let index = tabBarController.viewControllers?.index(of: viewController),
index < tabBarTypes.count {
let type = tabBarTypes[index]
switch type {
case .menu:
// perform your menu presenting here
return false
case .controller:
// do nothing, just return true, tab bar will do all work for you
return true
}
}
return true
}
In this implementation you can easily change tab types order or add some another tab type and handle it appropriate.
Its not good UI but although if you want.
First You have to implement delegate method of UITabbarControllerDelegate as below
func tabBarController(_ tabBarController: UITabBarController, shouldSelect
viewController: UIViewController) -> Bool {
if viewController.classForCoder == moreViewController.self
{
let popvc = MoreSubMenuViews(nibName: "MoreSubMenuViews", bundle: Bundle.main)
self.addChildViewController(popvc)
let tabbarHeight = tabBar.frame.height
let estimatedWidth:CGFloat = 200.0
let estimatedHeight:CGFloat = 300.0
popvc.view.frame = CGRect(x:self.view.frame.width - estimatedWidth, y: self.view.frame.height - estimatedHeight - tabbarHeight, width: estimatedWidth, height: estimatedHeight)
self.view.addSubview(popvc.view)
popvc.didMove(toParentViewController: self)
print("sorry stop here")
return true // if you want not to select return false here
}else{
//remove popup logic here if opened
return true
}
}
Here moreViewController is last tab controller & MoreSubMenuViews is nib/xib file which contains buttons shown in you image.
Instead of showing a menu, you could use a scrollable tabs view for a better UI. If you prefer using a library, here's a simple scrollable tab-bar you could implement.
This is an abuse of the UI patterns layout in Apples HIG. Specifically:
Use a tab bar strictly for navigation. Tab bar buttons should not be used to perform actions. If you need to provide controls that act on elements in the current view, use a toolbar instead.
This control should be used to flatten your app hierarchy. It seems that in this case you are mixing functionality of the button. Sometimes it selects a separate view controller, sometimes it displays a action list. This is a confusing situation for users and should be avoided.
A way you could achieve this and still adhere to HIG is by using navigation or tool bars. Imbed this control in a toolbar button. The most simple case would be to invoke a UIActionController with the .actionSheet style selected.
As per my understanding what you want is that, tab 1 is selected and user goes to tab 5 then background will be tab 1 & vice-versa for tab 2,3 & 4 and there should be pop up like buttons as shown in your image. please correct me if I'm wrong.
For this you have to capture the image while user navigate through tabs.
Please find below code in AppDelegate,
var currentImage: UIImage! //It will be public variable
Tabbar delegate methods,
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 4 {
let moreVC = tabBarController.selectedViewController as! MoreVC
moreVC.currentImage = currentImage
}
}
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.selectedIndex != 4 {
let navController = tabBarController.selectedViewController as! UINavigationController
let viewController = navController.viewControllers.last
currentImage = Common.imageWithView(inView: (viewController?.navigationController?.view)!) //UIImage(view: (viewController?.navigationController?.view)!)
}
return true
}
Here I've taken static 4 as last tab index & MoreVC will be the associated ViewController of tab index 4.
Common class to get image from view,
class Common {
static func imageWithView(inView: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(inView.bounds.size, inView.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
inView.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
return nil
}
}
Please find MoreVC,
#IBOutlet weak var imageView: UIImageView!
var currentImage: UIImage! {
didSet {
imageView.image = currentImage
}
}
Please find below image for MoreVC Storyboard. Look it does not contain NavigationController like all other ViewControllers.
Let me know in case of any queries.
1)
Create a "Tab5ViewController" and use this:
static func takeScreenshot(bottomPadding padding: CGFloat = 0) -> UIImage? {
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(CGSize(width: layer.frame.size.width, height: layer.frame.size.height - padding), false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
layer.render(in: context)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
Use the screenshot as a background image for your "Tab5ViewController"
2) In your "Tab5ViewController" you can have the stack component (the additional tabs) and then just add/remove child view controllers based on the selection
3)
fix edge cases (like tab selection highlight and so on...)