| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- //
- // LevelMaskView.swift
- // Loop
- //
- // Created by Nate Racklyeft on 8/28/16.
- // Copyright © 2016 Nathan Racklyeft. All rights reserved.
- //
- import UIKit
- // Displays a variable-height level indicator, masked by an image.
- // Inspired by https://github.com/carekit-apple/CareKit/blob/master/CareKit/CareCard/OCKHeartView.h
- public class LevelMaskView: UIView {
- var firstDataUpdate = true
- var value: Double = 1.0 {
- didSet {
- animateFill(duration: firstDataUpdate ? 0 : 1.25)
- firstDataUpdate = false
- }
- }
- private var clampedValue: Double {
- return value.clamped(to: 0...1.0)
- }
- @IBInspectable var maskImage: UIImage? {
- didSet {
- fillView?.removeFromSuperview()
- mask?.removeFromSuperview()
- maskImageView?.removeFromSuperview()
- guard let maskImage = maskImage else {
- fillView = nil
- mask = nil
- maskImageView = nil
- return
- }
- mask = UIView()
- maskImageView = UIImageView(image: maskImage)
- maskImageView!.frame = CGRect(origin: .zero, size: frame.size)
- maskImageView!.contentMode = .scaleAspectFit
- mask!.addSubview(maskImageView!)
- clipsToBounds = true
- fillView = UIView()
- fillView!.backgroundColor = tintColor
- addSubview(fillView!)
- }
- }
- private var fillView: UIView?
- private var maskImageView: UIView?
- override public func layoutSubviews() {
- super.layoutSubviews()
- guard let maskImageView = maskImageView else { return }
- let maskImageViewSize = maskImageView.frame.size
- mask?.frame = CGRect(origin: .zero, size: maskImageViewSize)
- mask?.center = CGPoint(x: bounds.midX, y: bounds.midY)
- self.maskImageView?.frame = mask?.bounds ?? bounds
- if (fillView?.layer.animationKeys()?.count ?? 0) == 0 {
- updateFillViewFrame()
- }
- }
- override public func tintColorDidChange() {
- super.tintColorDidChange()
- fillView?.backgroundColor = tintColor
- }
- private func animateFill(duration: TimeInterval) {
- UIView.animate(withDuration: duration, delay: 0, options: .beginFromCurrentState, animations: {
- self.updateFillViewFrame()
- }, completion: nil)
- }
- private func updateFillViewFrame() {
- guard let maskViewFrame = mask?.frame else { return }
- var fillViewFrame = maskViewFrame
- fillViewFrame.origin.y = maskViewFrame.maxY
- fillViewFrame.size.height = -CGFloat(clampedValue) * maskViewFrame.height
- fillView?.frame = fillViewFrame
- }
- }
|