Last active
July 17, 2018 10:27
-
-
Save KalpeshTalkar/4ad780fabf59c1527a5a894e16331735 to your computer and use it in GitHub Desktop.
IBDesignable tab bar view written in Swift 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright © 2017 Kalpesh Talkar. All rights reserved. | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// | |
// For support: https://gist.github.com/KalpeshTalkar/4ad780fabf59c1527a5a894e16331735 | |
// | |
import UIKit | |
protocol KTabBarDelegate { | |
func didSelectTabItem(tabBar: KTabBar, at index:Int) | |
} | |
@IBDesignable | |
class KTabBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { | |
// MARK: - IBInspectables | |
@IBInspectable var quickSetup: Bool = false { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var items: String = "Item 1;Item 2" { | |
didSet { | |
quickItems = items.components(separatedBy: ";") | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var selectedIndex: Int = 0 { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var selectionIndicatorColor: UIColor = UIColor.white { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var selectedItemColor: UIColor = UIColor.darkGray { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var itemColor: UIColor = UIColor.gray { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var textColor: UIColor = UIColor.white { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
@IBInspectable var minTabBarItemWidth: CGFloat = 80 { | |
didSet { | |
setUpCollectionView() | |
} | |
} | |
var totalTabs: Int { | |
get { | |
return quickItems.count | |
} | |
} | |
// MARK: - variables | |
var delegate: KTabBarDelegate? | |
private var collectionView: UICollectionView? | |
private var quickItems = [String]() | |
//private var items = [String]() | |
// MARK: - init methods | |
#if !TARGET_INTERFACE_BUILDER | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setUpCollectionView() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
setUpCollectionView() | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
if nil != collectionView { | |
collectionView!.frame = bounds | |
collectionView!.layoutSubviews() | |
} | |
} | |
#endif | |
// MARK: - UICollectionView Setup | |
private func setUpCollectionView() { | |
if nil == collectionView { | |
// UICollectionViewLayout | |
let layout = UICollectionViewFlowLayout() | |
layout.minimumLineSpacing = 0 | |
layout.minimumInteritemSpacing = 0 | |
layout.scrollDirection = UICollectionViewScrollDirection.horizontal | |
// UICollectionView | |
collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout) | |
collectionView!.backgroundColor = UIColor.clear | |
collectionView?.showsHorizontalScrollIndicator = false | |
collectionView!.dataSource = self | |
collectionView!.delegate = self | |
collectionView!.register(UINib.init(nibName: String.className(KTabBarCell.self), bundle: nil), forCellWithReuseIdentifier: String.className(KTabBarCell.self)) | |
collectionView!.backgroundColor = UIColor.white | |
} | |
collectionView!.removeFromSuperview() | |
addSubview(collectionView!) | |
collectionView!.reloadData() | |
} | |
// MARK: - UICollectionViewDataSource | |
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
return quickItems.count | |
} | |
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String.className(KTabBarCell.self), for: indexPath) as! KTabBarCell | |
let isSelected = selectedIndex == indexPath.row | |
if isSelected { | |
cell.backgroundColor = selectedItemColor | |
cell.selectionIndicator.backgroundColor = selectionIndicatorColor | |
} else { | |
cell.backgroundColor = itemColor | |
cell.selectionIndicator.backgroundColor = UIColor.clear | |
} | |
cell.itemLabel.textColor = textColor | |
cell.itemLabel.text = quickItems[indexPath.item] | |
return cell | |
} | |
// MARK: - UICollectionViewDelegate | |
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { | |
selectedIndex = indexPath.item | |
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems) | |
collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: true) | |
if nil != delegate { | |
delegate!.didSelectTabItem(tabBar: self, at: selectedIndex) | |
} | |
} | |
// MARK: - UICollectionViewDelegateFlowLayout | |
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | |
let label = UILabel() | |
label.font = UIFont.systemFont(ofSize: 16) | |
label.text = quickItems[indexPath.item] | |
let constrainedSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: KTabBarCell.ItemLabelHeight) | |
let requiredSize = label.sizeThatFits(constrainedSize) | |
var width = requiredSize.width+KTabBarCell.LeftRightMargin | |
if width < minTabBarItemWidth { | |
width = minTabBarItemWidth | |
} | |
return CGSize(width: width, height: collectionView.frame.height) | |
} | |
// MARK: - Helper methods | |
func selectTabItem(at index: Int) { | |
let indexPath = IndexPath(item: index, section: 0) | |
selectedIndex = indexPath.item | |
collectionView!.reloadItems(at: collectionView!.indexPathsForVisibleItems) | |
collectionView!.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: true) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright © 2017 Kalpesh Talkar. All rights reserved. | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// | |
// For support: https://gist.github.com/KalpeshTalkar/4ad780fabf59c1527a5a894e16331735 | |
// | |
import UIKit | |
class KTabBarCell: UICollectionViewCell { | |
static let ItemLabelHeight: CGFloat = 20 | |
static let LeftRightMargin: CGFloat = 16 | |
@IBOutlet weak var selectionIndicator: UIView! | |
@IBOutlet weak var itemLabel: UILabel! | |
override func awakeFromNib() { | |
super.awakeFromNib() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11201" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> | |
<dependencies> | |
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> | |
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |
</dependencies> | |
<objects> | |
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> | |
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | |
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="KTabBarCell" customModule="EduGuru" customModuleProvider="target"> | |
<rect key="frame" x="0.0" y="0.0" width="48" height="44"/> | |
<autoresizingMask key="autoresizingMask"/> | |
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> | |
<rect key="frame" x="0.0" y="0.0" width="48" height="44"/> | |
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> | |
<subviews> | |
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="T2n-ni-Chu"> | |
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> | |
<constraints> | |
<constraint firstAttribute="height" constant="5" id="asK-Cm-Ei3"/> | |
</constraints> | |
</view> | |
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Item" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4qv-7C-8p7"> | |
<fontDescription key="fontDescription" type="system" pointSize="16"/> | |
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/> | |
<nil key="highlightedColor"/> | |
</label> | |
</subviews> | |
</view> | |
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/> | |
<constraints> | |
<constraint firstItem="T2n-ni-Chu" firstAttribute="top" secondItem="4qv-7C-8p7" secondAttribute="bottom" constant="8" id="9MZ-p8-d66"/> | |
<constraint firstItem="4qv-7C-8p7" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="11" id="K87-yd-SEI"/> | |
<constraint firstAttribute="trailing" secondItem="T2n-ni-Chu" secondAttribute="trailing" id="PDx-EW-wPc"/> | |
<constraint firstItem="4qv-7C-8p7" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="8" id="Qee-SX-Ew2"/> | |
<constraint firstAttribute="bottom" secondItem="T2n-ni-Chu" secondAttribute="bottom" id="acB-4D-L3W"/> | |
<constraint firstItem="T2n-ni-Chu" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="lVO-p8-TvD"/> | |
<constraint firstAttribute="trailing" secondItem="4qv-7C-8p7" secondAttribute="trailing" constant="8" id="x7j-mX-1eW"/> | |
</constraints> | |
<connections> | |
<outlet property="itemLabel" destination="4qv-7C-8p7" id="rGm-aP-aID"/> | |
<outlet property="selectionIndicator" destination="T2n-ni-Chu" id="hjX-ef-cPc"/> | |
</connections> | |
<point key="canvasLocation" x="-260" y="-118"/> | |
</collectionViewCell> | |
</objects> | |
</document> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
Using Interface Builder/Storyboard
Programmatically
items
:quickItems
: