создать прогрсс бар с яркостью и тусклым светом? - PullRequest
0 голосов
/ 10 февраля 2020

«программа обмена» Класс A {let a = 5 let b = 10

   b = (a + b) - (a = b)
   print(a,b)
}

1 Ответ

0 голосов
/ 10 февраля 2020
Create Knob class to design progress bar with dim light brightness

class Knob: UIControl {
  /** Contains the minimum value of the receiver. */
  var minimumValue: Float = 0

  /** Contains the maximum value of the receiver. */
  var maximumValue: Float = 1

  /** Contains the receiver’s current value. */
  private (set) var value: Float = 0

  /** Sets the receiver’s current value, allowing you to animate the change visually. */
  func setValue(_ newValue: Float, animated: Bool = false) {
    value = min(maximumValue, max(minimumValue, newValue))

    let angleRange = endAngle - startAngle
    let valueRange = maximumValue - minimumValue
    let angleValue = CGFloat(value - minimumValue) / CGFloat(valueRange) * angleRange + startAngle
    renderer.setPointerAngle(angleValue, animated: animated)
  }

  /** Contains a Boolean value indicating whether changes
   in the sliders value generate continuous update events. */
  var isContinuous = true

  private let renderer = KnobRenderer()

  /** Specifies the width in points of the knob control track. Defaults to 2 */
  var lineWidth: CGFloat {
    get { return renderer.lineWidth }
    set { renderer.lineWidth = newValue }
  }

  /** Specifies the angle of the start of the knob control track. Defaults to -11π/8 */
  var startAngle: CGFloat {
    get { return renderer.startAngle }
    set { renderer.startAngle = newValue }
  }

  /** Specifies the end angle of the knob control track. Defaults to 3π/8 */
  var endAngle: CGFloat {
    get { return renderer.endAngle }
    set { renderer.endAngle = newValue }
  }

  /** Specifies the length in points of the pointer on the knob. Defaults to 6 */
  var pointerLength: CGFloat {
    get { return renderer.pointerLength }
    set { renderer.pointerLength = newValue }
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    commonInit()
  }

  private func commonInit() {
    renderer.updateBounds(bounds)
    renderer.color = .red
    renderer.setPointerAngle(renderer.startAngle)

    layer.addSublayer(renderer.trackLayer)
    layer.addSublayer(renderer.pointerLayer)

    let gestureRecognizer = RotationGestureRecognizer(target: self, action: #selector(Knob.handleGesture(_:)))
    addGestureRecognizer(gestureRecognizer)
  }

  @objc private func handleGesture(_ gesture: RotationGestureRecognizer) {
    // 1
    let midPointAngle = (2 * CGFloat(Double.pi) + startAngle - endAngle) / 2 + endAngle
    // 2
    var boundedAngle = gesture.touchAngle
    if boundedAngle > midPointAngle {
      boundedAngle -= 2 * CGFloat(Double.pi)
    } else if boundedAngle < (midPointAngle - 2 * CGFloat(Double.pi)) {
      boundedAngle -= 2 * CGFloat(Double.pi)
    }

    // 3
    boundedAngle = min(endAngle, max(startAngle, boundedAngle))

    // 4
    let angleRange = endAngle - startAngle
    let valueRange = maximumValue - minimumValue
    let angleValue = Float(boundedAngle - startAngle) / Float(angleRange) * valueRange + minimumValue

    // 5
    setValue(angleValue)

    if isContinuous {
      sendActions(for: .valueChanged)
    } else {
      if gesture.state == .ended || gesture.state == .cancelled {
        sendActions(for: .valueChanged)
      }
    }
  }
}

private class KnobRenderer {
  var color: UIColor = .blue {
    didSet {
      trackLayer.strokeColor = UIColor.red.cgColor
      pointerLayer.strokeColor = UIColor.yellow.cgColor
    }
  }

  var lineWidth: CGFloat = 2 {
    didSet {
      trackLayer.lineWidth = lineWidth
      pointerLayer.lineWidth = 20
      updateTrackLayerPath()
      updatePointerLayerPath()
    }
  }

  var startAngle: CGFloat = CGFloat(-Double.pi)  {
    didSet {
      updateTrackLayerPath()
    }
  }

  var endAngle: CGFloat = CGFloat(Double.pi)  / 180 {
    didSet {
      updateTrackLayerPath()
    }
  }

  var pointerLength: CGFloat = 6 {
    didSet {
      updateTrackLayerPath()
      updatePointerLayerPath()
    }
  }

  private (set) var pointerAngle: CGFloat = CGFloat(-Double.pi)

  func setPointerAngle(_ newPointerAngle: CGFloat, animated: Bool = false) {
    CATransaction.begin()
    CATransaction.setDisableActions(true)

    pointerLayer.transform = CATransform3DMakeRotation(newPointerAngle, 0, 0, 1)

    if animated {
      let midAngleValue = (max(newPointerAngle, pointerAngle) - min(newPointerAngle, pointerAngle)) / 2 +  min(newPointerAngle, pointerAngle)
      let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
      animation.values = [pointerAngle, midAngleValue, newPointerAngle]
      animation.keyTimes = [0.0, 0.5, 1.0]
        animation.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)]
      pointerLayer.add(animation, forKey: nil)
    }

    CATransaction.commit()

    pointerAngle = newPointerAngle
  }

  let trackLayer = CAShapeLayer()
  let pointerLayer = CAShapeLayer()

  init() {
    trackLayer.fillColor = UIColor.clear.cgColor
    pointerLayer.fillColor = UIColor.clear.cgColor
  }

  private func updateTrackLayerPath() {
    let bounds = trackLayer.bounds
    let center = CGPoint(x: bounds.midX , y: bounds.midY)
    let offset = max(pointerLength, lineWidth)
    let radius = min(bounds.width, bounds.height)  - offset 

    let ring = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
    trackLayer.path = ring.cgPath
  }

  private func updatePointerLayerPath() {
    let bounds = trackLayer.bounds

    let pointer = UIBezierPath()
    pointer.move(to: CGPoint(x: pointerLayer.frame.size.width / 2 + 100, y: bounds.midY))
    pointer.addLine(to: CGPoint(x: bounds.width - 40, y: bounds.midY))
    pointerLayer.path = pointer.cgPath
  }

  func updateBounds(_ bounds: CGRect) {
    trackLayer.bounds = bounds
    trackLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
    updateTrackLayerPath()

    pointerLayer.bounds = trackLayer.bounds
    pointerLayer.position = trackLayer.position
    updatePointerLayerPath()
  }
}

import UIKit.UIGestureRecognizerSubclass

private class RotationGestureRecognizer: UIPanGestureRecognizer {
  private(set) var touchAngle: CGFloat = 0

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesBegan(touches, with: event)
    updateAngle(with: touches)
  }

  override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesMoved(touches, with: event)
    updateAngle(with: touches)
  }

  private func updateAngle(with touches: Set<UITouch>) {
    guard
      let touch = touches.first,
      let view = view
    else {
      return
    }
    let touchPoint = touch.location(in: view)
    touchAngle = angle(for: touchPoint, in: view)
  }

  private func angle(for point: CGPoint, in view: UIView) -> CGFloat {
    let centerOffset = CGPoint(x: point.x - view.bounds.midX, y: point.y - view.bounds.midY)
    return atan2(centerOffset.y, centerOffset.x)
  }

  override init(target: Any?, action: Selector?) {
    super.init(target: target, action: action)

    maximumNumberOfTouches = 1
    minimumNumberOfTouches = 1
  }
}


Now  write code in viewController class

  @IBOutlet var animateSwitch: UISwitch!
    @IBOutlet var knob: Knob!
    @IBOutlet weak var img: UIImageView!

    var val = CGFloat()

    @IBOutlet weak var progressBar: UISlider!
    override func viewDidLoad() {
        super.viewDidLoad()

        knob.lineWidth = 100
        knob.pointerLength = 4
        knob.setValue(0)
        knob.addTarget(self, action: #selector(ViewController.handleValueChanged(_:)), for: .valueChanged)

        updateLabel()
    }

    @IBAction func handleValueChanged(_ sender: Any) {
//        if sender is UISlider {
//            knob.setValue(valueSlider.value)
//        } else {
//            valueSlider.value = knob.value
//        }
        updateLabel()
    }

    @IBAction func handleRandomButtonPressed(_ sender: Any) {
//        let randomValue = Float(arc4random_uniform(101)) / 100.0
//        knob.setValue(randomValue, animated: animateSwitch.isOn)
//        valueSlider.setValue(Float(randomValue), animated: animateSwitch.isOn)
        updateLabel()
    }

    private func updateLabel() {
//        valueLabel.text = String(format: "%.2f", knob.value)

        if val < CGFloat(knob.value)
        {
            img.backgroundColor = img.backgroundColor?.lighter(by: CGFloat(knob.value))
        }
        else
        {
            img.backgroundColor = img.backgroundColor?.darker(by: CGFloat(knob.value))
        }
        val = CGFloat(knob.value)
    }
}

extension UIColor {

    func lighter(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: abs(percentage) )
    }

    func darker(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: -1 * abs(percentage) )
    }

    func adjust(by percentage: CGFloat = 30.0) -> UIColor? {
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
        if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {
            return UIColor(red: min(red + percentage/100, 1.0),
                           green: min(green + percentage/100, 1.0),
                           blue: min(blue + percentage/100, 1.0),
                           alpha: alpha)
        } else {
            return nil
        }
    }

}
...