Created
July 14, 2015 12:57
-
-
Save mingsai/3d27db100fb2d0bb78fc to your computer and use it in GitHub Desktop.
Star rating control is the code behind a custom view to produce a number of stars that respond to touch. The stars become highlighted when touched and change a rating property.
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
// | |
// StarRatingControl.swift | |
// ths | |
// | |
// Created by Tommie Carter on 7/13/15. | |
// Copyright © 2015 MING Technology. All rights reserved. | |
// | |
import UIKit | |
protocol StarRatingDelegate { | |
func starRatingControl(control:StarRatingControl, didUpdateRating:Float) | |
func starRatingControl(control:StarRatingControl, willUpdateRating:Float) | |
} | |
class StarRatingControl: UIControl { | |
let kDefaultNumberOfStars = 5 | |
let kStarPadding:Float = 5.0 | |
var delegate:StarRatingDelegate! | |
var rating:Float! { | |
set { | |
currentIdx = Int(round(self.rating)) | |
for (idx, _star) in stars!.enumerate() { | |
(_star as! UIImageView | |
).highlighted = (idx < currentIdx) | |
} | |
} | |
get { | |
return Float (currentIdx) | |
} | |
} | |
var star:UIImage! | |
var highlightedStar:UIImage! | |
var currentIdx:Int! | |
var numberOfStars:Int! | |
var stars:[AnyObject]? | |
//MARK: View Initialization | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
self.numberOfStars = kDefaultNumberOfStars | |
setupView() | |
} | |
convenience init(frame: CGRect, numberOfStars:Int) { | |
self.init(frame: frame) | |
self.numberOfStars = kDefaultNumberOfStars | |
setupView() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
self.numberOfStars = kDefaultNumberOfStars | |
setupView() | |
} | |
//MARK: View Layout | |
func setupView () { | |
self.clipsToBounds = true | |
currentIdx = -1 | |
//let normal = UIImage.imageFromText("★", fontname: "Chalkduster", fontSize: CGFloat(60.0))?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) | |
//let highlightedImage = UIImage.imageFromText("★", fontname: "Chalkduster", fontSize: CGFloat(60.0))?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) | |
star = UIImage.imageFromText("★", fontname: "Chalkduster", fontSize: CGFloat(60.0))?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) | |
//UIImage(named: "star.png") | |
highlightedStar = UIImage.imageFromText("★", fontname: "Chalkduster", fontSize: CGFloat(60.0))?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) | |
var s = Array<AnyObject>() | |
s.reserveCapacity(self.numberOfStars) | |
for (var i = 0; i < numberOfStars; i = i + 1) { | |
let v = UIImageView(image: star, highlightedImage: highlightedStar) | |
v.tintColor = UIColor.yellowColor() | |
self.addSubview(v) | |
s.append(v) | |
} | |
stars = s | |
} | |
/* | |
// Only override drawRect: if you perform custom drawing. | |
// An empty implementation adversely affects performance during animation. | |
override func drawRect(rect: CGRect) { | |
// Drawing code | |
} | |
*/ | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
let width = CGFloat((Float(self.frame.size.width) - (kStarPadding * Float(numberOfStars + 1))) / Float(numberOfStars)) | |
let cellWidth = min(self.frame.size.height, width) | |
// We need to align the stars in the center of the view | |
let totalCellWidth = (Float(self.frame.size.width) - (Float(cellWidth) * Float(numberOfStars))) | |
let padding = totalCellWidth + (kStarPadding * (Float(numberOfStars) + 1)) / Float(2.0) | |
for (idx, _star) in stars!.enumerate() { | |
let paddedValue = padding + kStarPadding + Float(idx) * Float(cellWidth) + Float(idx) * kStarPadding | |
let frame = CGRectMake(CGFloat(paddedValue) * CGFloat(kStarPadding), 0, cellWidth, cellWidth) | |
(_star as! UIImageView | |
).frame = frame | |
} | |
} | |
func starForPoint(point:CGPoint) -> UIImageView? { | |
for star in stars! { | |
if let imageView = star as? UIImageView { | |
(CGRectContainsPoint(star.frame, point)) | |
return imageView | |
} | |
} | |
return nil | |
} | |
func indexForStar(atPoint:CGPoint) -> Int { | |
let _stars = stars as! [UIImageView] | |
return _stars.indexOf(self.starForPoint(atPoint)!)! | |
} | |
//MARK: Touch Events | |
override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool { | |
//super.beginTrackingWithTouch(touch, withEvent: event) | |
let _star = stars![0] as! UIImageView | |
let point = touch.locationInView(self) | |
let index = self.indexForStar(point) | |
if (index != NSNotFound) { | |
self.rating = Float ( index+1 ) | |
//if (self.delegate?.starRatingControl:willUpdateRating) ///{ | |
let pointOffset = Int(point.x) | |
let firstStarPoint = Int ( _star.frame.origin.x ) | |
if ( pointOffset < firstStarPoint ) { | |
self.delegate.starRatingControl(self, willUpdateRating: self.rating) | |
} else { | |
self.rating = 0 | |
self.delegate.starRatingControl(self, willUpdateRating:self.rating) | |
} | |
} | |
return true | |
} | |
override func cancelTrackingWithEvent(event: UIEvent?) { | |
super.cancelTrackingWithEvent(event) | |
} | |
override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool { | |
let point = touch.locationInView(self) | |
let index = self.indexForStar(point) | |
let _star = stars![0] as! UIImageView | |
if (index != NSNotFound) { | |
self.rating = Float( index + 1 ) | |
let pointOffset = Int(point.x) | |
let firstStarPoint = Int ( _star.frame.origin.x ) | |
if ( pointOffset < firstStarPoint ) { | |
self.delegate.starRatingControl(self, willUpdateRating: self.rating) | |
} else { | |
self.rating = 0 | |
self.delegate.starRatingControl(self, willUpdateRating:self.rating) | |
} | |
} | |
return true | |
} | |
override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) { | |
self.delegate.starRatingControl(self, didUpdateRating: self.rating) | |
super.endTrackingWithTouch(touch, withEvent: event) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment