From 3227d06c2a33e926e1ddeb6685a645a7ad4f5556 Mon Sep 17 00:00:00 2001 From: AmrAngry Date: Sat, 6 Feb 2021 00:04:59 +0400 Subject: [PATCH 1/2] code lint --- FloatRatingView.swift | 72 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/FloatRatingView.swift b/FloatRatingView.swift index b46a8b3..b3e5e13 100644 --- a/FloatRatingView.swift +++ b/FloatRatingView.swift @@ -11,7 +11,7 @@ import UIKit @objc public protocol FloatRatingViewDelegate { /// Returns the rating value when touch events end @objc optional func floatRatingView(_ ratingView: FloatRatingView, didUpdate rating: Double) - + /// Returns the rating value as the user pans @objc optional func floatRatingView(_ ratingView: FloatRatingView, isUpdating rating: Double) } @@ -24,13 +24,13 @@ open class FloatRatingView: UIView { // MARK: Properties open weak var delegate: FloatRatingViewDelegate? - + /// Array of empty image views private var emptyImageViews: [UIImageView] = [] - + /// Array of full image views private var fullImageViews: [UIImageView] = [] - + /// Sets the empty image (e.g. a star outline) @IBInspectable open var emptyImage: UIImage? { didSet { @@ -41,7 +41,7 @@ open class FloatRatingView: UIView { refresh() } } - + /// Sets the full image that is overlayed on top of the empty image. /// Should be same size and shape as the empty image. @IBInspectable open var fullImage: UIImage? { @@ -53,10 +53,10 @@ open class FloatRatingView: UIView { refresh() } } - + /// Sets the empty and full image view content mode. open var imageContentMode: UIView.ContentMode = .scaleAspectFit - + /// Minimum rating. @IBInspectable open var minRating: Int = 0 { didSet { @@ -67,7 +67,7 @@ open class FloatRatingView: UIView { } } } - + /// Max rating value. @IBInspectable open var maxRating: Int = 5 { didSet { @@ -81,10 +81,10 @@ open class FloatRatingView: UIView { } } } - + /// Minimum image size. @IBInspectable open var minImageSize = CGSize(width: 5.0, height: 5.0) - + /// Set the current rating. @IBInspectable open var rating: Double = 0 { didSet { @@ -93,12 +93,12 @@ open class FloatRatingView: UIView { } } } - + /// Sets whether or not the rating view can be changed by panning. @IBInspectable open var editable = true - + // MARK: Type - + @objc public enum FloatRatingViewType: Int { /// Integer rating case wholeRatings @@ -106,13 +106,13 @@ open class FloatRatingView: UIView { case halfRatings /// Double rating case floatRatings - + /// Returns true if rating can contain decimal places func supportsFractions() -> Bool { return self == .halfRatings || self == .floatRatings } } - + /// Float rating view type @IBInspectable open var type: FloatRatingViewType = .wholeRatings @@ -131,12 +131,12 @@ open class FloatRatingView: UIView { } // MARK: Helper methods - + private func initImageViews() { guard emptyImageViews.isEmpty && fullImageViews.isEmpty else { return } - + // Add new image views for _ in 0..= Double(i+1) { imageView.layer.mask = nil imageView.isHidden = false @@ -204,13 +204,13 @@ open class FloatRatingView: UIView { return CGSize(width: size.width, height: height) } } - + // Calculates new rating based on touch location in view private func updateLocation(_ touch: UITouch) { guard editable else { return } - + let touchLocation = touch.location(in: self) var newRating: Double = 0 for i in stride(from: (maxRating-1), through: 0, by: -1) { @@ -218,10 +218,10 @@ open class FloatRatingView: UIView { guard touchLocation.x > imageView.frame.origin.x else { continue } - + // Find touch point in image view let newLocation = imageView.convert(touchLocation, from: self) - + // Find decimal value for float or half rating if imageView.point(inside: newLocation, with: nil) && (type.supportsFractions()) { let decimalNum = Double(newLocation.x / imageView.frame.size.width) @@ -235,31 +235,31 @@ open class FloatRatingView: UIView { } break } - + // Check min rating rating = newRating < Double(minRating) ? Double(minRating) : newRating - + // Update delegate delegate?.floatRatingView?(self, isUpdating: rating) } - - + + // MARK: UIView // Override to calculate ImageView frames override open func layoutSubviews() { super.layoutSubviews() - + guard let emptyImage = emptyImage else { return } - + let desiredImageWidth = frame.size.width / CGFloat(emptyImageViews.count) let maxImageWidth = max(minImageSize.width, desiredImageWidth) let maxImageHeight = max(minImageSize.height, frame.size.height) let imageViewSize = sizeForImage(emptyImage, inSize: CGSize(width: maxImageWidth, height: maxImageHeight)) let imageXOffset = (frame.size.width - (imageViewSize.width * CGFloat(emptyImageViews.count))) / - CGFloat((emptyImageViews.count - 1)) + CGFloat((emptyImageViews.count - 1)) for i in 0.., with event: UIEvent?) { guard let touch = touches.first else { return } updateLocation(touch) } - + override open func touchesMoved(_ touches: Set, with event: UIEvent?) { guard let touch = touches.first else { return From 4853caf7c94d493597617eab551e72a835e0319b Mon Sep 17 00:00:00 2001 From: AmrAngry Date: Sat, 6 Feb 2021 00:05:54 +0400 Subject: [PATCH 2/2] RTL Support --- FloatRatingView.swift | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/FloatRatingView.swift b/FloatRatingView.swift index b3e5e13..7066315 100644 --- a/FloatRatingView.swift +++ b/FloatRatingView.swift @@ -185,6 +185,8 @@ open class FloatRatingView: UIView { imageView.isHidden = true } } + + flipViewIfNeeded() } // Calculates the ideal ImageView size in a given CGSize @@ -301,3 +303,29 @@ open class FloatRatingView: UIView { delegate?.floatRatingView?(self, didUpdate: rating) } } + +// MARK: - StarRatingView+RTLSupport +public extension FloatRatingView { + /// Flip the View to support Right to Left Languages based on the view semantic + func flipViewIfNeeded() { + var direction: UIUserInterfaceLayoutDirection + if #available(iOS 10.0, *) { + direction = self.effectiveUserInterfaceLayoutDirection + } else { // Fallback on earlier versions + if #available(iOS 9.0, *) { + // The view is shown in right-to-left mode right now. + direction = UIView.userInterfaceLayoutDirection(for: self.semanticContentAttribute) + } else { // Fallback on earlier versions + direction = UIApplication.shared.userInterfaceLayoutDirection + } + } + + if case .rightToLeft = direction { + flip() + } + } + + private func flip() { + self.transform = CGAffineTransform(scaleX: -1.0, y: 1.0); + } +}