-
Notifications
You must be signed in to change notification settings - Fork 223
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implementation of cardpart icon label * Added readme for cardpartIcon Label * Updsted set up to handle corner radius aspect * Added ninding for icon adopted review comment
- Loading branch information
1 parent
42e659a
commit 3c9fa78
Showing
6 changed files
with
314 additions
and
1 deletion.
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
CardParts/src/Classes/Card Parts/CardPartIconLabel.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
// | ||
// CardPartIconLabel.swift | ||
// CardParts | ||
// | ||
// Created by Venkatnarayansetty, Badarinath on 8/20/19. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
import RxSwift | ||
import RxCocoa | ||
|
||
public class CardPartIconLabel: UILabel, CardPartView { | ||
|
||
public enum HorizontalPosition { | ||
case left | ||
case right | ||
} | ||
|
||
public enum VerticalPosition { | ||
case top | ||
case center | ||
case bottom | ||
} | ||
|
||
public var margins: UIEdgeInsets = CardParts.theme.cardPartMargins | ||
|
||
/// provides vertical and horizontal spacing | ||
public var verticalPadding:CGFloat = 2.0 | ||
public var horizontalPadding:CGFloat = 2.0 | ||
public var padding:CGFloat = 10.0 | ||
|
||
public var iconView: UIImageView? { | ||
didSet { | ||
guard let image = iconView?.image else { return } | ||
self.icon = image | ||
} | ||
} | ||
|
||
/// Horizontal and vertical position | ||
public typealias Position = (horizontal: CardPartIconLabel.HorizontalPosition, vertical: CardPartIconLabel.VerticalPosition) | ||
open var iconPosition: Position = (.left , .top) | ||
|
||
/// additional spacing between text and the image | ||
public var iconPadding: CGFloat = 0 | ||
|
||
public var icon:UIImage? { | ||
didSet { | ||
if icon == nil { | ||
iconView?.removeFromSuperview() | ||
} | ||
setNeedsDisplay() | ||
} | ||
} | ||
|
||
public var labelText: String? { | ||
didSet { | ||
guard let text = labelText else { return } | ||
self.text = text | ||
} | ||
} | ||
|
||
override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
setup() | ||
} | ||
|
||
required init?(coder aDecoder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
fileprivate func setup() { | ||
self.clipsToBounds = true | ||
} | ||
|
||
open override func drawText(in rect: CGRect) { | ||
guard let text = text as NSString? else { return } | ||
|
||
guard let icon = icon else { | ||
super.drawText(in: rect) | ||
return | ||
} | ||
|
||
//remove from view if it's present before adding it. | ||
iconView?.removeFromSuperview() | ||
iconView = UIImageView(image: icon) | ||
|
||
//calculate frame of the text based on content. | ||
let size = text.boundingRect(with: CGSize(width: frame.width - icon.size.width - iconPadding, height: .greatestFiniteMagnitude), | ||
options: NSStringDrawingOptions.usesLineFragmentOrigin, | ||
attributes: [.font : font as Any ], | ||
context: nil).size | ||
|
||
var newRect = CGRect.zero | ||
guard let iconView = iconView else { return } | ||
|
||
/// calculate the icon y position | ||
let iconYPosition = (frame.height - iconView.frame.height) / 2 | ||
let height = frame.height | ||
|
||
// set the frame positions according to text alignment and icon horizontal positions. | ||
switch iconPosition.horizontal { | ||
case .left: | ||
if textAlignment == .left { | ||
iconView.frame = iconView.frame.offsetBy(dx: padding, dy: iconYPosition) | ||
newRect = CGRect(x: iconView.frame.width + iconPadding + padding, y: 0, width: frame.width - (iconView.frame.width + iconPadding), height: height) | ||
}else if textAlignment == .right { | ||
iconView.frame = iconView.frame.offsetBy(dx: frame.width - size.width - iconPadding - iconView.frame.width - padding, dy: iconYPosition) | ||
newRect = CGRect(x: frame.width - size.width - iconPadding - padding , y: 0, width: size.width + iconPadding, height: height) | ||
}else if textAlignment == .center { | ||
iconView.frame = iconView.frame.offsetBy(dx: (frame.width - size.width) / 2 - iconPadding - iconView.frame.width, dy: iconYPosition) | ||
newRect = CGRect(x: (frame.width - size.width) / 2 , y: 0, width: size.width + iconPadding, height: height) | ||
} | ||
case .right: | ||
if textAlignment == .left { | ||
iconView.frame = iconView.frame.offsetBy(dx: size.width + iconPadding + padding, dy: iconYPosition) | ||
newRect = CGRect(x: 10, y: 0, width: size.width, height: height) | ||
}else if textAlignment == .right { | ||
iconView.frame = iconView.frame.offsetBy(dx: frame.width - iconView.frame.width - padding , dy: iconYPosition) | ||
newRect = CGRect(x: frame.width - size.width - iconView.frame.width - iconPadding - 2 * padding, y: 0, width: size.width + iconPadding, height: height) | ||
}else if textAlignment == .center { | ||
iconView.frame = iconView.frame.offsetBy(dx: frame.width / 2 + size.width / 2 + iconPadding, dy: iconYPosition) | ||
newRect = CGRect(x: (frame.width - size.width) / 2, y: 0, width: size.width, height: height) | ||
} | ||
} | ||
|
||
// set the frame positions of the icon vertically i.e., top, bottom or center | ||
switch iconPosition.vertical { | ||
case .top: iconView.frame.origin.y = (frame.height - size.height) / 2 | ||
|
||
case .center: iconView.frame.origin.y = (frame.height - iconView.frame.height) / 2 | ||
|
||
case .bottom: iconView.frame.origin.y = frame.height - (frame.height - size.height) / 2 - iconView.frame.size.height | ||
} | ||
|
||
addSubview(iconView) | ||
super.drawText(in: newRect) | ||
setup() | ||
} | ||
|
||
/// returns new size with updated vertical and horizantal padding. | ||
public override var intrinsicContentSize: CGSize { | ||
let superSize = super.intrinsicContentSize | ||
let newWidth = superSize.width + superSize.height + (2 * horizontalPadding) | ||
let newHeight = superSize.height + (2 * verticalPadding) | ||
let size = CGSize(width: newWidth, height: newHeight) | ||
return size | ||
} | ||
} | ||
|
||
// MARK: - Reactive binding for label's text , vertical & horizontal padding. | ||
extension Reactive where Base: CardPartIconLabel { | ||
|
||
public var labelText: Binder<String?>{ | ||
return Binder(self.base) { (label, labelText) -> () in | ||
label.text = labelText | ||
} | ||
} | ||
|
||
public var verticalPadding: Binder<CGFloat> { | ||
return Binder(self.base) { (label, verticalPadding) -> () in | ||
label.verticalPadding = verticalPadding | ||
} | ||
} | ||
|
||
public var horizontalPadding: Binder<CGFloat> { | ||
return Binder(self.base) { (label, horizontalPadding) -> () in | ||
label.horizontalPadding = horizontalPadding | ||
} | ||
} | ||
|
||
public var iconView: Binder<UIImageView> { | ||
return Binder(self.base) { (imageView, iconView) -> () in | ||
imageView.iconView = iconView | ||
} | ||
} | ||
} |
This file contains 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
110 changes: 110 additions & 0 deletions
110
Example/CardParts/CardPartIconLabelCardController.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// | ||
// CardPartIconLabelCardController.swift | ||
// CardParts_Example | ||
// | ||
// Created by Venkatnarayansetty, Badarinath on 8/21/19. | ||
// Copyright © 2019 CocoaPods. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import CardParts | ||
import RxSwift | ||
import RxCocoa | ||
|
||
class CardPartIconLabelCardController: CardPartsViewController { | ||
|
||
var viewModel = ReactiveCardPartIconViewModel() | ||
|
||
override func viewDidLoad() { | ||
|
||
let alignment: CardPartIconLabel.VerticalPosition = .center | ||
|
||
let stackView = CardPartStackView() | ||
stackView.axis = .vertical | ||
stackView.spacing = 10 | ||
|
||
for index in 0...5 { | ||
|
||
let iconLabel = CardPartIconLabel() | ||
iconLabel.verticalPadding = 10 | ||
iconLabel.horizontalPadding = 10 | ||
iconLabel.backgroundColor = UIColor(red: 16.0 / 255.0, green: 128.0 / 255.0, blue: 0, alpha: 0.16) | ||
iconLabel.font = UIFont.systemFont(ofSize: 12) | ||
iconLabel.textColor = UIColor.black | ||
iconLabel.numberOfLines = 0 | ||
iconLabel.iconPadding = 5 | ||
iconLabel.layer.cornerRadius = 8.0 | ||
iconLabel.icon = UIImage(named: "themeIcon") | ||
|
||
switch index { | ||
case 0: | ||
iconLabel.text = "Card icon on left,text is left" | ||
iconLabel.textAlignment = .left | ||
iconLabel.iconPosition = ( .left, alignment ) | ||
|
||
case 1: | ||
iconLabel.text = "Card icon on right,text is left" | ||
iconLabel.textAlignment = .left | ||
iconLabel.iconPosition = ( .right, alignment ) | ||
|
||
case 2: | ||
iconLabel.text = "Card icon on left,text is right" | ||
iconLabel.textAlignment = .right | ||
iconLabel.iconPosition = (.left, alignment) | ||
|
||
case 3: | ||
iconLabel.text = "Card icon on right,text is right" | ||
iconLabel.textAlignment = .right | ||
iconLabel.iconPosition = (.right, alignment) | ||
|
||
case 4: | ||
iconLabel.text = "Card icon on left,text is center" | ||
iconLabel.textAlignment = .center | ||
iconLabel.iconPosition = (.left, alignment) | ||
|
||
case 5: | ||
iconLabel.text = "Card icon on right,text is center" | ||
iconLabel.textAlignment = .center | ||
iconLabel.iconPosition = (.right, alignment) | ||
|
||
default: | ||
break | ||
} | ||
|
||
stackView.addArrangedSubview(iconLabel) | ||
|
||
if index == 1 { | ||
viewModel.labelText.asObservable().bind(to: iconLabel.rx.labelText).disposed(by: bag) | ||
viewModel.iconView.asObservable().bind(to: iconLabel.rx.iconView).disposed(by: bag) | ||
invalidateLayout(onChanges: [viewModel.iconView]) | ||
} | ||
} | ||
|
||
setupCardParts([stackView]) | ||
} | ||
} | ||
|
||
class ReactiveCardPartIconViewModel { | ||
|
||
var labelText = BehaviorRelay(value: "Defaul Label") | ||
var iconView = BehaviorRelay(value: UIImageView(image: UIImage(named: ""))) | ||
|
||
init() { | ||
startTimer() | ||
} | ||
|
||
func startTimer() { | ||
iconView.accept( UIImageView(image: UIImage(named: "cardIcon"))) | ||
Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(self.randomise), userInfo: nil, repeats: true) | ||
} | ||
|
||
@objc func randomise() { | ||
switch arc4random() % 1 { | ||
case 0: | ||
labelText.accept("CardParts is reactive based library") | ||
default: | ||
return | ||
} | ||
} | ||
|
||
} |
This file contains 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
This file contains 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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.