123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- //
- // 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()
- }
- }
- }
|