// // JXSegmentedIndicatorGradientView.swift // JXSegmentedView // // Created by jiaxin on 2019/1/16. // Copyright © 2019 jiaxin. All rights reserved. // import UIKit /// 整个背景是一个渐变色layer,通过gradientMaskLayer遮罩显示不同位置,达到不同文字底部有不同的渐变色。 open class JXSegmentedIndicatorGradientView: JXSegmentedIndicatorBaseView { @available(*, deprecated, renamed: "indicatorWidthIncrement") open var gradientViewWidthIncrement: CGFloat = 20 { didSet { indicatorWidthIncrement = gradientViewWidthIncrement } } /// 渐变colors open var gradientColors = [CGColor]() /// 渐变CAGradientLayer,通过它设置startPoint、endPoint等其他属性 open var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer } public let gradientMaskLayer: CAShapeLayer = CAShapeLayer() open class override var layerClass: AnyClass { return CAGradientLayer.self } private var gradientMaskLayerFrame = CGRect.zero open override func commonInit() { super.commonInit() indicatorWidthIncrement = 20 indicatorHeight = 26 indicatorPosition = .center verticalOffset = 0 gradientColors = [UIColor(red: 194.0/255, green: 229.0/255, blue: 156.0/255, alpha: 1).cgColor, UIColor(red: 100.0/255, green: 179.0/255, blue: 244.0/255, alpha: 1).cgColor] gradientLayer.startPoint = CGPoint(x: 0, y: 0) gradientLayer.endPoint = CGPoint(x: 1, y: 0) layer.mask = gradientMaskLayer } open override func refreshIndicatorState(model: JXSegmentedIndicatorSelectedParams) { super.refreshIndicatorState(model: model) gradientLayer.colors = gradientColors let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth) let height = getIndicatorHeight(itemFrame: model.currentSelectedItemFrame) let x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2 var y: CGFloat = 0 switch indicatorPosition { case .top: y = verticalOffset case .bottom: y = model.currentSelectedItemFrame.size.height - height - verticalOffset case .center: y = (model.currentSelectedItemFrame.size.height - height)/2 + verticalOffset } gradientMaskLayerFrame = CGRect(x: x, y: y, width: width, height: height) let path = UIBezierPath(roundedRect: gradientMaskLayerFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame)) CATransaction.begin() CATransaction.setDisableActions(true) gradientMaskLayer.path = path.cgPath CATransaction.commit() if let collectionViewContentSize = model.collectionViewContentSize { frame = CGRect(x: 0, y: 0, width: collectionViewContentSize.width, height: collectionViewContentSize.height) } } open override func contentScrollViewDidScroll(model: JXSegmentedIndicatorTransitionParams) { super.contentScrollViewDidScroll(model: model) guard canHandleTransition(model: model) else { return } let rightItemFrame = model.rightItemFrame let leftItemFrame = model.leftItemFrame let percent = model.percent var targetWidth = getIndicatorWidth(itemFrame: leftItemFrame, itemContentWidth: model.leftItemContentWidth) let leftWidth = targetWidth let rightWidth = getIndicatorWidth(itemFrame: rightItemFrame, itemContentWidth: model.rightItemContentWidth) let leftX = leftItemFrame.origin.x + (leftItemFrame.size.width - leftWidth)/2 let rightX = rightItemFrame.origin.x + (rightItemFrame.size.width - rightWidth)/2 let targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat(percent)) if indicatorWidth == JXSegmentedViewAutomaticDimension { targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: rightWidth, percent: CGFloat(percent)) } gradientMaskLayerFrame.origin.x = targetX gradientMaskLayerFrame.size.width = targetWidth let path = UIBezierPath(roundedRect: gradientMaskLayerFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: leftItemFrame)) CATransaction.begin() CATransaction.setDisableActions(true) gradientMaskLayer.path = path.cgPath CATransaction.commit() } open override func selectItem(model: JXSegmentedIndicatorSelectedParams) { super.selectItem(model: model) let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth) var toFrame = gradientMaskLayerFrame toFrame.origin.x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2 toFrame.size.width = width let path = UIBezierPath(roundedRect: toFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame)) if canSelectedWithAnimation(model: model) { gradientMaskLayer.removeAnimation(forKey: "path") let animation = CABasicAnimation(keyPath: "path") animation.fromValue = gradientMaskLayer.path animation.toValue = path.cgPath animation.duration = scrollAnimationDuration animation.timingFunction = CAMediaTimingFunction(name: .easeOut) gradientMaskLayer.add(animation, forKey: "path") gradientMaskLayer.path = path.cgPath }else { CATransaction.begin() CATransaction.setDisableActions(true) gradientMaskLayer.path = path.cgPath CATransaction.commit() } } }