Skip to content

Instantly share code, notes, and snippets.

@FabiolaRamirez
Created June 6, 2019 19:14
Show Gist options
  • Save FabiolaRamirez/4a758660787b216a1febe2c7a3a32af8 to your computer and use it in GitHub Desktop.
Save FabiolaRamirez/4a758660787b216a1febe2c7a3a32af8 to your computer and use it in GitHub Desktop.
import UIKit
class DGItem:UIButton {
var selectedColor:UIColor = UIColor.creditSesameCyan {
didSet {
self.backgroundColor = selectedColor
}
}
var unSelectedColor:UIColor = .white {
didSet {
self.backgroundColor = unSelectedColor
}
}
override var isSelected: Bool {
didSet {
self.backgroundColor = isSelected ? selectedColor : unSelectedColor
}
}
/** sets gradiant on button if yes , default is no*/
@IBInspectable open var showGradiant:Bool = false {
didSet {
if showGradiant {
setUpLayers()
}
}
}
@IBInspectable var languageButtonColor : UIColor = UIColor.clear {
didSet{
setUpSelctedState()
}
}
@IBInspectable open var makeSelected: Bool = false {
didSet {
setUpSelctedState()
}
}
@IBInspectable open var selectedTitleColor: UIColor = UIColor.white {
didSet {
setUpSelctedState()
}
}
@IBInspectable open var unSelectedTitleColor: UIColor = UIColor.white {
didSet {
setUpSelctedState()
}
}
open var minimumScale: CGFloat = 0.95
open var pressSpringDamping: CGFloat = 0.4
open var releaseSpringDamping: CGFloat = 0.35
open var pressSpringDuration = 0.4
open var releaseSpringDuration = 0.5
open var cornorRadious:CGFloat = 6.0
var shineLayer:CAGradientLayer?
var highlightLayer:CALayer?
open override func awakeFromNib() {
}
public init() {
super.init(frame: CGRect.zero)
}
override init(frame: CGRect) {
super.init(frame:frame)
if showGradiant {
setUpLayers()
}
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if showGradiant {
setUpLayers()
}
}
open override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
shineLayer?.frame = self.bounds
highlightLayer?.frame = self.bounds
}
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
UIView.animate(withDuration: self.pressSpringDuration, delay: 0, usingSpringWithDamping: self.pressSpringDamping, initialSpringVelocity: 0, options: [.curveLinear, .allowUserInteraction], animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: self.minimumScale, y: self.minimumScale)
}, completion: nil)
self.setHighlighted(highlight: true)
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
UIView.animate(withDuration: self.releaseSpringDuration, delay: 0, usingSpringWithDamping: self.releaseSpringDamping, initialSpringVelocity: 0, options: [.curveLinear, .allowUserInteraction], animations: { () -> Void in
self.transform = CGAffineTransform.identity
}, completion: nil)
self.setHighlighted(highlight: false)
}
open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
let location = touches.first!.location(in: self)
if !self.bounds.contains(location) {
UIView.animate(withDuration: self.releaseSpringDuration, delay: 0, usingSpringWithDamping: self.releaseSpringDamping, initialSpringVelocity: 0, options: [.curveLinear, .allowUserInteraction], animations: { () -> Void in
self.transform = CGAffineTransform.identity
}, completion: nil)
}
}
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
UIView.animate(withDuration: self.releaseSpringDuration, delay: 0, usingSpringWithDamping: self.releaseSpringDamping, initialSpringVelocity: 0, options: [.curveLinear, .allowUserInteraction], animations: { () -> Void in
self.transform = CGAffineTransform.identity
}, completion: nil)
}
func setUpLayers() {
self.setUpBorder()
self.addShileLayer()
self.addHighlightLayer()
}
func setUpBorder() {
let layer = self.layer
layer.cornerRadius = 8
layer.masksToBounds = true
layer.borderWidth = 1
layer.borderColor = UIColor.white.withAlphaComponent(0.5).cgColor
}
func addShileLayer() {
self.shineLayer = CAGradientLayer()
self.shineLayer?.frame = self.layer.bounds
shineLayer?.colors = [
UIColor.init(white: 1, alpha: 0.4).cgColor,
UIColor.init(white: 1, alpha: 0.2).cgColor,
UIColor.init(white: 0.75, alpha: 0.2).cgColor,
UIColor.init(white: 0.4, alpha: 0.2).cgColor,
UIColor.init(white: 1, alpha: 0.4).cgColor
]
shineLayer?.locations = [0.0,0.5,0.5,0.8,1.0]
self.layer.addSublayer(shineLayer!)
}
func addHighlightLayer() {
self.highlightLayer = CALayer()
highlightLayer?.backgroundColor = UIColor.black.withAlphaComponent(0.4).cgColor
highlightLayer?.isHidden = true
self.layer.insertSublayer(highlightLayer!, below: self.shineLayer)
}
func setHighlighted(highlight:Bool) {
self.highlightLayer?.isHidden = !highlight
super.isHighlighted = highlight
}
func setUpSelctedState () {
self.tintColor = .clear
self.backgroundColor = .clear
if makeSelected {
self.backgroundColor = languageButtonColor
self.setTitleColor(selectedTitleColor, for: .normal)
} else {
self.layer.borderWidth = 1
self.layer.borderColor = languageButtonColor.cgColor
self.setTitleColor(unSelectedTitleColor, for: .normal)
}
}
}
///Datasource
///DGScrollableSegmentControlDataSource
protocol DGScrollableSegmentControlDataSource:class {
func numbersOfItem()->Int
func itemfor(_ index:Int)->DGItem
}
///Delegate
///DGScrollableSegmentControlDelegate
@objc protocol DGScrollableSegmentControlDelegate:class {
@objc optional func didSelect(_ item:DGItem, atIndex index:Int)
}
class DGScrollableSegmentControl: UIView {
weak var delegate:DGScrollableSegmentControlDelegate?
weak var datasource:DGScrollableSegmentControlDataSource?
var scrollView: UIScrollView = UIScrollView()
var dataArray:[String]?
override init(frame: CGRect) {
super.init(frame: frame)
self.initialSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialSetup()
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.loadScrollView()
}
func reload() {
self.loadItems()
}
func loadScrollView() {
self.scrollView.frame = self.frame
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = UIColor.creditSesameLightGrayBackgroundColor
self.addConstraintsWithFormat("H:|[v0]|", views: scrollView)
self.addConstraintsWithFormat("V:|-2-[v0]|", views: scrollView)
//scrollView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
//scrollView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
//scrollView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
//scrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
self.loadItems()
}
func initialSetup() {
self.addSubview(scrollView)
//self.scrollView.delaysContentTouches = false
self.scrollView.canCancelContentTouches = true
}
override func layoutSubviews() {
super.layoutSubviews()
}
var itemSpacing:CGFloat = 4
private func loadItems(){
buttonArray.removeAll()
for item in self.scrollView.subviews{
item.removeFromSuperview()
}
guard let dataSource = self.datasource else { print("Data source not implemented"); return }
let numbersOfItems = dataSource.numbersOfItem()
guard numbersOfItems > 0 else {return}
var x = itemSpacing, maxHeight = CGFloat(0.0)
for index in 0 ..< numbersOfItems {
guard let item = datasource?.itemfor(index) else {
fatalError("Please implement item for index dataSource method") ;
}
item.addTarget(self, action: #selector(segmentTapped(_:)), for: .touchUpInside)
item.frame.origin.x = x
item.frame.origin.y = 0
item.tag = index
//View configuring
//item.backgroundColor = .red
/*
if DeviceType.IS_IPAD{
button.titleLabel?.font = UIFont(name: (button.titleLabel?.font.fontName)!, size: 26)
} else if DeviceType.IS_IPAD_PRO_12_9{
button.titleLabel?.font = UIFont(name: (button.titleLabel?.font.fontName)!, size: 32)
}else{
button.titleLabel?.font = UIFont(name: (button.titleLabel?.font.fontName)!, size: 13)
}
*/
let size:CGSize = item.intrinsicContentSize
if size.width > self.scrollView.frame.width/4{
item.frame.size = CGSize(width: size.width+10, height: scrollView.frame.height - 3)
}else{
item.frame.size = CGSize(width: self.scrollView.frame.width/4, height: scrollView.frame.height - 3 )
}
scrollView.addSubview(item)
maxHeight = max(maxHeight, item.frame.size.height)
x += item.frame.size.width + itemSpacing
item.layer.cornerRadius = item.frame.height/2
item.layer.masksToBounds = true
buttonArray.append(item)
}
scrollView.frame.size.height = maxHeight
scrollView.contentSize = CGSize(width: x, height:scrollView.frame.size.height)
scrollView.showsHorizontalScrollIndicator = false
//loadLoactionData(buttonTag: 0)
scroll(toIndex: 0)
}
@objc func segmentTapped(_ sender:DGItem) {
for buttonItem in buttonArray{
let btn = sender
if btn == buttonItem {
buttonItem.isSelected = true
buttonItem.setTitleColor(.white, for: .normal)
buttonItem.updateBorder()
}else{
buttonItem.isSelected = false
buttonItem.setTitleColor(.creditSesameCyan, for: .normal)
buttonItem.updateBorder()
}
//loadLoactionData(buttonTag: sender.tag)
}
scroll(toIndex: sender.tag)
guard let delegate = self.delegate else {print("Delegate not implemented"); return }
delegate.didSelect?(sender, atIndex: sender.tag)
}
var buttonArray:[UIButton] = []
func scroll(toIndex index:Int) {
guard self.scrollView.contentSize.width > self.scrollView.frame.width else { return }
let leftSideWidth:CGFloat = buttonArray.reduce(0) { (sum, button) -> CGFloat in
return button.tag < index ? sum + button.frame.size.width + 10 : sum
} + 10
let rightSideWidth:CGFloat = buttonArray.reduce(0) { (sum, button) -> CGFloat in
return button.tag > index ? sum + button.frame.size.width + 10 : sum
}
let selectedButtonWidth:CGFloat = buttonArray[index].frame.size.width + 10
var finalContentOffset = CGPoint.zero
if rightSideWidth < scrollView.frame.width/2{
finalContentOffset = CGPoint(x: scrollView.contentSize.width - scrollView.frame.width, y: 0)
}else if leftSideWidth < scrollView.frame.width/2{
finalContentOffset = CGPoint.zero
}else {
finalContentOffset = CGPoint(x: leftSideWidth - scrollView.frame.size.width/2 + selectedButtonWidth/2, y: 0)
}
UIView.animate(withDuration: 0.2) {
self.scrollView.contentOffset = finalContentOffset
}
}
}
private extension UIView {
func addConstraintsWithFormat(_ format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated() {
let key = "v\(index)"
view.translatesAutoresizingMaskIntoConstraints = false
viewsDictionary[key] = view
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: viewsDictionary))
}
}
extension UIButton {
func updateBorder() {
let layer = self.layer
layer.cornerRadius = 16
layer.masksToBounds = true
layer.borderWidth = self.isSelected ? 0 : 1
layer.borderColor = self.isSelected ? UIColor.clear.cgColor : UIColor.creditSesameGrayBackgroundColor.cgColor
//ESTO AUMENTE YO - FABIOLA PROBANDOOOO
/*let spacing = 10.5 // the amount of spacing to appear between image and title
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: CGFloat(spacing), bottom: 0, right: CGFloat(spacing));
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: CGFloat(spacing), bottom: 0, right: CGFloat(spacing));
self.titleLabel?.lineBreakMode = .byWordWrapping
self.titleLabel?.numberOfLines = 1*/
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment