mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Stream improvements
This commit is contained in:
@@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import HierarchyTrackingLayer
|
||||
|
||||
private func generateIndefiniteActivityIndicatorImage(color: UIColor, diameter: CGFloat = 22.0, lineWidth: CGFloat = 2.0) -> UIImage? {
|
||||
return generateImage(CGSize(width: diameter, height: diameter), rotatedContext: { size, context in
|
||||
@@ -15,7 +16,7 @@ private func generateIndefiniteActivityIndicatorImage(color: UIColor, diameter:
|
||||
})
|
||||
}
|
||||
|
||||
public final class SolidRoundedButtonTheme {
|
||||
public final class SolidRoundedButtonTheme: Equatable {
|
||||
public let backgroundColor: UIColor
|
||||
public let gradientBackgroundColor: UIColor?
|
||||
public let foregroundColor: UIColor
|
||||
@@ -25,6 +26,19 @@ public final class SolidRoundedButtonTheme {
|
||||
self.gradientBackgroundColor = gradientBackgroundColor
|
||||
self.foregroundColor = foregroundColor
|
||||
}
|
||||
|
||||
public static func ==(lhs: SolidRoundedButtonTheme, rhs: SolidRoundedButtonTheme) -> Bool {
|
||||
if lhs.backgroundColor != rhs.backgroundColor {
|
||||
return false
|
||||
}
|
||||
if lhs.gradientBackgroundColor != rhs.gradientBackgroundColor {
|
||||
return false
|
||||
}
|
||||
if lhs.foregroundColor != rhs.foregroundColor {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public enum SolidRoundedButtonFont {
|
||||
@@ -38,7 +52,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
private var fontSize: CGFloat
|
||||
|
||||
private let buttonBackgroundNode: ASDisplayNode
|
||||
private let buttonGlossNode: SolidRoundedButtonGlossNode?
|
||||
private let buttonGlossView: SolidRoundedButtonGlossView?
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let subtitleNode: ImmediateTextNode
|
||||
@@ -95,9 +109,9 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
self.buttonBackgroundNode.cornerRadius = cornerRadius
|
||||
|
||||
if gloss {
|
||||
self.buttonGlossNode = SolidRoundedButtonGlossNode(color: theme.foregroundColor, cornerRadius: cornerRadius)
|
||||
self.buttonGlossView = SolidRoundedButtonGlossView(color: theme.foregroundColor, cornerRadius: cornerRadius)
|
||||
} else {
|
||||
self.buttonGlossNode = nil
|
||||
self.buttonGlossView = nil
|
||||
}
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
@@ -116,8 +130,8 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.buttonBackgroundNode)
|
||||
if let buttonGlossNode = self.buttonGlossNode {
|
||||
self.addSubnode(buttonGlossNode)
|
||||
if let buttonGlossView = self.buttonGlossView {
|
||||
self.view.addSubview(buttonGlossView)
|
||||
}
|
||||
self.addSubnode(self.buttonNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
@@ -211,7 +225,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
self.theme = theme
|
||||
|
||||
self.buttonBackgroundNode.backgroundColor = theme.backgroundColor
|
||||
self.buttonGlossNode?.color = theme.foregroundColor
|
||||
self.buttonGlossView?.color = theme.foregroundColor
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title ?? "", font: self.font == .bold ? Font.semibold(self.fontSize) : Font.regular(self.fontSize), textColor: theme.foregroundColor)
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitle ?? "", font: Font.regular(14.0), textColor: theme.foregroundColor)
|
||||
|
||||
@@ -237,8 +251,8 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
let buttonSize = CGSize(width: width, height: self.buttonHeight)
|
||||
let buttonFrame = CGRect(origin: CGPoint(), size: buttonSize)
|
||||
transition.updateFrame(node: self.buttonBackgroundNode, frame: buttonFrame)
|
||||
if let buttonGlossNode = self.buttonGlossNode {
|
||||
transition.updateFrame(node: buttonGlossNode, frame: buttonFrame)
|
||||
if let buttonGlossView = self.buttonGlossView {
|
||||
transition.updateFrame(view: buttonGlossView, frame: buttonFrame)
|
||||
}
|
||||
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
|
||||
|
||||
@@ -289,7 +303,257 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private final class SolidRoundedButtonGlossNodeParameters: NSObject {
|
||||
public final class SolidRoundedButtonView: UIView {
|
||||
private var theme: SolidRoundedButtonTheme
|
||||
private var font: SolidRoundedButtonFont
|
||||
private var fontSize: CGFloat
|
||||
|
||||
private let buttonBackgroundNode: UIView
|
||||
private let buttonGlossView: SolidRoundedButtonGlossView?
|
||||
private let buttonNode: HighlightTrackingButton
|
||||
private let titleNode: ImmediateTextView
|
||||
private let subtitleNode: ImmediateTextView
|
||||
private let iconNode: UIImageView
|
||||
private var progressNode: UIImageView?
|
||||
|
||||
private let buttonHeight: CGFloat
|
||||
private let buttonCornerRadius: CGFloat
|
||||
|
||||
public var pressed: (() -> Void)?
|
||||
public var validLayout: CGFloat?
|
||||
|
||||
public var title: String? {
|
||||
didSet {
|
||||
if let width = self.validLayout {
|
||||
_ = self.updateLayout(width: width, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var subtitle: String? {
|
||||
didSet {
|
||||
if let width = self.validLayout {
|
||||
_ = self.updateLayout(width: width, previousSubtitle: oldValue, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var icon: UIImage? {
|
||||
didSet {
|
||||
self.iconNode.image = generateTintedImage(image: self.icon, color: self.theme.foregroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
public var iconSpacing: CGFloat = 8.0 {
|
||||
didSet {
|
||||
if let width = self.validLayout {
|
||||
_ = self.updateLayout(width: width, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(title: String? = nil, icon: UIImage? = nil, theme: SolidRoundedButtonTheme, font: SolidRoundedButtonFont = .bold, fontSize: CGFloat = 17.0, height: CGFloat = 48.0, cornerRadius: CGFloat = 24.0, gloss: Bool = false) {
|
||||
self.theme = theme
|
||||
self.font = font
|
||||
self.fontSize = fontSize
|
||||
self.buttonHeight = height
|
||||
self.buttonCornerRadius = cornerRadius
|
||||
self.title = title
|
||||
|
||||
self.buttonBackgroundNode = UIView()
|
||||
self.buttonBackgroundNode.clipsToBounds = true
|
||||
self.buttonBackgroundNode.backgroundColor = theme.backgroundColor
|
||||
self.buttonBackgroundNode.layer.cornerRadius = cornerRadius
|
||||
|
||||
if gloss {
|
||||
self.buttonGlossView = SolidRoundedButtonGlossView(color: theme.foregroundColor, cornerRadius: cornerRadius)
|
||||
} else {
|
||||
self.buttonGlossView = nil
|
||||
}
|
||||
|
||||
self.buttonNode = HighlightTrackingButton()
|
||||
|
||||
self.titleNode = ImmediateTextView()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
|
||||
self.subtitleNode = ImmediateTextView()
|
||||
self.subtitleNode.isUserInteractionEnabled = false
|
||||
|
||||
self.iconNode = UIImageView()
|
||||
self.iconNode.image = generateTintedImage(image: icon, color: self.theme.foregroundColor)
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.addSubview(self.buttonBackgroundNode)
|
||||
if let buttonGlossView = self.buttonGlossView {
|
||||
self.addSubview(buttonGlossView)
|
||||
}
|
||||
self.addSubview(self.buttonNode)
|
||||
self.addSubview(self.titleNode)
|
||||
self.addSubview(self.subtitleNode)
|
||||
self.addSubview(self.iconNode)
|
||||
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.buttonBackgroundNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.buttonBackgroundNode.alpha = 0.55
|
||||
strongSelf.titleNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.titleNode.alpha = 0.55
|
||||
strongSelf.subtitleNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.subtitleNode.alpha = 0.55
|
||||
strongSelf.iconNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.iconNode.alpha = 0.55
|
||||
} else {
|
||||
if strongSelf.buttonBackgroundNode.alpha > 0.0 {
|
||||
strongSelf.buttonBackgroundNode.alpha = 1.0
|
||||
strongSelf.buttonBackgroundNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||
strongSelf.titleNode.alpha = 1.0
|
||||
strongSelf.titleNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||
strongSelf.subtitleNode.alpha = 1.0
|
||||
strongSelf.subtitleNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||
strongSelf.iconNode.alpha = 1.0
|
||||
strongSelf.iconNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
self.buttonBackgroundNode.layer.cornerCurve = .continuous
|
||||
}
|
||||
}
|
||||
|
||||
required public init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func transitionToProgress() {
|
||||
guard self.progressNode == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
let buttonOffset = self.buttonBackgroundNode.frame.minX
|
||||
let buttonWidth = self.buttonBackgroundNode.frame.width
|
||||
|
||||
let progressFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(buttonOffset + (buttonWidth - self.buttonHeight) / 2.0), y: 0.0), size: CGSize(width: self.buttonHeight, height: self.buttonHeight))
|
||||
let progressNode = UIImageView()
|
||||
progressNode.frame = progressFrame
|
||||
progressNode.image = generateIndefiniteActivityIndicatorImage(color: self.buttonBackgroundNode.backgroundColor ?? .clear, diameter: self.buttonHeight, lineWidth: 2.0 + UIScreenPixel)
|
||||
self.insertSubview(progressNode, at: 0)
|
||||
self.progressNode = progressNode
|
||||
|
||||
let basicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
||||
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
||||
basicAnimation.duration = 0.5
|
||||
basicAnimation.fromValue = NSNumber(value: Float(0.0))
|
||||
basicAnimation.toValue = NSNumber(value: Float.pi * 2.0)
|
||||
basicAnimation.repeatCount = Float.infinity
|
||||
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||
basicAnimation.beginTime = 1.0
|
||||
progressNode.layer.add(basicAnimation, forKey: "progressRotation")
|
||||
|
||||
self.buttonBackgroundNode.layer.cornerRadius = self.buttonHeight / 2.0
|
||||
self.buttonBackgroundNode.layer.animate(from: self.buttonCornerRadius as NSNumber, to: self.buttonHeight / 2.0 as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.2)
|
||||
self.buttonBackgroundNode.layer.animateFrame(from: self.buttonBackgroundNode.frame, to: progressFrame, duration: 0.2)
|
||||
|
||||
self.buttonBackgroundNode.alpha = 0.0
|
||||
self.buttonBackgroundNode.layer.animateAlpha(from: 0.55, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
|
||||
progressNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, removeOnCompletion: false)
|
||||
|
||||
self.titleNode.alpha = 0.0
|
||||
self.titleNode.layer.animateAlpha(from: 0.55, to: 0.0, duration: 0.2)
|
||||
|
||||
self.subtitleNode.alpha = 0.0
|
||||
self.subtitleNode.layer.animateAlpha(from: 0.55, to: 0.0, duration: 0.2)
|
||||
}
|
||||
|
||||
public func updateTheme(_ theme: SolidRoundedButtonTheme) {
|
||||
guard theme !== self.theme else {
|
||||
return
|
||||
}
|
||||
self.theme = theme
|
||||
|
||||
self.buttonBackgroundNode.backgroundColor = theme.backgroundColor
|
||||
self.buttonGlossView?.color = theme.foregroundColor
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title ?? "", font: self.font == .bold ? Font.semibold(self.fontSize) : Font.regular(self.fontSize), textColor: theme.foregroundColor)
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitle ?? "", font: Font.regular(14.0), textColor: theme.foregroundColor)
|
||||
|
||||
self.iconNode.image = generateTintedImage(image: self.iconNode.image, color: theme.foregroundColor)
|
||||
|
||||
if let width = self.validLayout {
|
||||
_ = self.updateLayout(width: width, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
return self.updateLayout(width: width, previousSubtitle: self.subtitle, transition: transition)
|
||||
}
|
||||
|
||||
private func updateLayout(width: CGFloat, previousSubtitle: String?, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
self.validLayout = width
|
||||
|
||||
let buttonSize = CGSize(width: width, height: self.buttonHeight)
|
||||
let buttonFrame = CGRect(origin: CGPoint(), size: buttonSize)
|
||||
transition.updateFrame(view: self.buttonBackgroundNode, frame: buttonFrame)
|
||||
if let buttonGlossView = self.buttonGlossView {
|
||||
transition.updateFrame(view: buttonGlossView, frame: buttonFrame)
|
||||
}
|
||||
transition.updateFrame(view: self.buttonNode, frame: buttonFrame)
|
||||
|
||||
if self.title != self.titleNode.attributedText?.string {
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title ?? "", font: self.font == .bold ? Font.semibold(self.fontSize) : Font.regular(self.fontSize), textColor: self.theme.foregroundColor)
|
||||
}
|
||||
|
||||
let iconSize = self.iconNode.image?.size ?? CGSize()
|
||||
let titleSize = self.titleNode.updateLayout(buttonSize)
|
||||
|
||||
let iconSpacing: CGFloat = self.iconSpacing
|
||||
|
||||
var contentWidth: CGFloat = titleSize.width
|
||||
if !iconSize.width.isZero {
|
||||
contentWidth += iconSize.width + iconSpacing
|
||||
}
|
||||
var nextContentOrigin = floor((buttonFrame.width - contentWidth) / 2.0)
|
||||
transition.updateFrame(view: self.iconNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX + nextContentOrigin, y: floor((buttonFrame.height - iconSize.height) / 2.0)), size: iconSize))
|
||||
if !iconSize.width.isZero {
|
||||
nextContentOrigin += iconSize.width + iconSpacing
|
||||
}
|
||||
|
||||
let spacingOffset: CGFloat = 9.0
|
||||
let verticalInset: CGFloat = self.subtitle == nil ? floor((buttonFrame.height - titleSize.height) / 2.0) : floor((buttonFrame.height - titleSize.height) / 2.0) - spacingOffset
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: buttonFrame.minX + nextContentOrigin, y: buttonFrame.minY + verticalInset), size: titleSize)
|
||||
transition.updateFrame(view: self.titleNode, frame: titleFrame)
|
||||
|
||||
if self.subtitle != self.subtitleNode.attributedText?.string {
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitle ?? "", font: Font.regular(14.0), textColor: self.theme.foregroundColor)
|
||||
}
|
||||
|
||||
let subtitleSize = self.subtitleNode.updateLayout(buttonSize)
|
||||
let subtitleFrame = CGRect(origin: CGPoint(x: buttonFrame.minX + floor((buttonFrame.width - subtitleSize.width) / 2.0), y: buttonFrame.minY + floor((buttonFrame.height - titleSize.height) / 2.0) + spacingOffset + 2.0), size: subtitleSize)
|
||||
transition.updateFrame(view: self.subtitleNode, frame: subtitleFrame)
|
||||
|
||||
if previousSubtitle == nil && self.subtitle != nil {
|
||||
self.titleNode.layer.animatePosition(from: CGPoint(x: 0.0, y: spacingOffset / 2.0), to: CGPoint(), duration: 0.3, additive: true)
|
||||
self.subtitleNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -spacingOffset / 2.0), to: CGPoint(), duration: 0.3, additive: true)
|
||||
self.subtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
}
|
||||
|
||||
return buttonSize.height
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
self.pressed?()
|
||||
}
|
||||
}
|
||||
|
||||
private final class SolidRoundedButtonGlossViewParameters: NSObject {
|
||||
let gradientColors: NSArray?
|
||||
let cornerRadius: CGFloat
|
||||
let progress: CGFloat
|
||||
@@ -301,7 +565,7 @@ private final class SolidRoundedButtonGlossNodeParameters: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
public final class SolidRoundedButtonGlossNode: ASDisplayNode {
|
||||
public final class SolidRoundedButtonGlossView: UIView {
|
||||
public var color: UIColor {
|
||||
didSet {
|
||||
self.updateGradientColors()
|
||||
@@ -313,14 +577,19 @@ public final class SolidRoundedButtonGlossNode: ASDisplayNode {
|
||||
private let buttonCornerRadius: CGFloat
|
||||
private var gradientColors: NSArray?
|
||||
|
||||
private let trackingLayer: HierarchyTrackingLayer
|
||||
|
||||
public init(color: UIColor, cornerRadius: CGFloat) {
|
||||
self.color = color
|
||||
self.buttonCornerRadius = cornerRadius
|
||||
|
||||
super.init()
|
||||
self.trackingLayer = HierarchyTrackingLayer()
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.layer.addSublayer(self.trackingLayer)
|
||||
|
||||
self.isOpaque = false
|
||||
self.isLayerBacked = true
|
||||
|
||||
var previousTime: CFAbsoluteTime?
|
||||
self.animator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
||||
@@ -347,41 +616,48 @@ public final class SolidRoundedButtonGlossNode: ASDisplayNode {
|
||||
})
|
||||
|
||||
self.updateGradientColors()
|
||||
|
||||
self.trackingLayer.didEnterHierarchy = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.animator?.isPaused = false
|
||||
}
|
||||
|
||||
self.trackingLayer.didExitHierarchy = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.animator?.isPaused = true
|
||||
}
|
||||
}
|
||||
|
||||
required public init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func updateGradientColors() {
|
||||
let transparentColor = self.color.withAlphaComponent(0.0).cgColor
|
||||
self.gradientColors = [transparentColor, transparentColor, self.color.withAlphaComponent(0.12).cgColor, transparentColor, transparentColor]
|
||||
}
|
||||
|
||||
override public func willEnterHierarchy() {
|
||||
super.willEnterHierarchy()
|
||||
self.animator?.isPaused = false
|
||||
}
|
||||
|
||||
override public func didExitHierarchy() {
|
||||
super.didExitHierarchy()
|
||||
self.animator?.isPaused = true
|
||||
}
|
||||
|
||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
return SolidRoundedButtonGlossNodeParameters(gradientColors: self.gradientColors, cornerRadius: self.buttonCornerRadius, progress: self.progress)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
|
||||
override public func draw(_ rect: CGRect) {
|
||||
let parameters = SolidRoundedButtonGlossViewParameters(gradientColors: self.gradientColors, cornerRadius: self.buttonCornerRadius, progress: self.progress)
|
||||
guard let gradientColors = parameters.gradientColors else {
|
||||
return
|
||||
}
|
||||
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if let parameters = parameters as? SolidRoundedButtonGlossNodeParameters, let gradientColors = parameters.gradientColors {
|
||||
let path = UIBezierPath(roundedRect: bounds, cornerRadius: parameters.cornerRadius)
|
||||
context.addPath(path.cgPath)
|
||||
context.clip()
|
||||
|
||||
var locations: [CGFloat] = [0.0, 0.15, 0.5, 0.85, 1.0]
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
||||
|
||||
let x = -4.0 * bounds.size.width + 8.0 * bounds.size.width * parameters.progress
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: x, y: 0.0), end: CGPoint(x: x + bounds.size.width, y: 0.0), options: CGGradientDrawingOptions())
|
||||
}
|
||||
let path = UIBezierPath(roundedRect: bounds, cornerRadius: parameters.cornerRadius)
|
||||
context.addPath(path.cgPath)
|
||||
context.clip()
|
||||
|
||||
var locations: [CGFloat] = [0.0, 0.15, 0.5, 0.85, 1.0]
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
||||
|
||||
let x = -4.0 * bounds.size.width + 8.0 * bounds.size.width * parameters.progress
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: x, y: 0.0), end: CGPoint(x: x + bounds.size.width, y: 0.0), options: CGGradientDrawingOptions())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user