117 lines
5.0 KiB
Swift
117 lines
5.0 KiB
Swift
//
|
||
// JXSegmentedIndicatorLineView.swift
|
||
// JXSegmentedView
|
||
//
|
||
// Created by jiaxin on 2018/12/26.
|
||
// Copyright © 2018 jiaxin. All rights reserved.
|
||
//
|
||
|
||
import UIKit
|
||
|
||
public enum JXSegmentedIndicatorLineStyle {
|
||
case normal
|
||
case lengthen
|
||
case lengthenOffset
|
||
}
|
||
|
||
open class JXSegmentedIndicatorLineView: JXSegmentedIndicatorBaseView {
|
||
open var lineStyle: JXSegmentedIndicatorLineStyle = .normal
|
||
/// lineStyle为lengthenOffset时使用,滚动时x的偏移量
|
||
open var lineScrollOffsetX: CGFloat = 10
|
||
|
||
open override func commonInit() {
|
||
super.commonInit()
|
||
|
||
indicatorHeight = 3
|
||
}
|
||
|
||
open override func refreshIndicatorState(model: JXSegmentedIndicatorSelectedParams) {
|
||
super.refreshIndicatorState(model: model)
|
||
|
||
backgroundColor = indicatorColor
|
||
layer.cornerRadius = getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame)
|
||
|
||
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
|
||
}
|
||
frame = CGRect(x: x, y: y, width: width, height: 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 targetX: CGFloat = leftItemFrame.origin.x
|
||
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
|
||
|
||
switch lineStyle {
|
||
case .normal:
|
||
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat(percent))
|
||
if indicatorWidth == JXSegmentedViewAutomaticDimension {
|
||
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: rightWidth, percent: CGFloat(percent))
|
||
}
|
||
case .lengthen:
|
||
//前50%,只增加width;后50%,移动x并减小width
|
||
let maxWidth = rightX - leftX + rightWidth
|
||
if percent <= 0.5 {
|
||
targetX = leftX
|
||
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: maxWidth, percent: CGFloat(percent*2))
|
||
}else {
|
||
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat((percent - 0.5)*2))
|
||
targetWidth = JXSegmentedViewTool.interpolate(from: maxWidth, to: rightWidth, percent: CGFloat((percent - 0.5)*2))
|
||
}
|
||
case .lengthenOffset:
|
||
//前50%,增加width,并少量移动x;后50%,少量移动x并减小width
|
||
let maxWidth = rightX - leftX + rightWidth - lineScrollOffsetX*2
|
||
if percent <= 0.5 {
|
||
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: leftX + lineScrollOffsetX, percent: CGFloat(percent*2))
|
||
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: maxWidth, percent: CGFloat(percent*2))
|
||
}else {
|
||
targetX = JXSegmentedViewTool.interpolate(from:leftX + lineScrollOffsetX, to: rightX, percent: CGFloat((percent - 0.5)*2))
|
||
targetWidth = JXSegmentedViewTool.interpolate(from: maxWidth, to: rightWidth, percent: CGFloat((percent - 0.5)*2))
|
||
}
|
||
}
|
||
|
||
self.frame.origin.x = targetX
|
||
self.frame.size.width = targetWidth
|
||
}
|
||
|
||
open override func selectItem(model: JXSegmentedIndicatorSelectedParams) {
|
||
super.selectItem(model: model)
|
||
|
||
let targetWidth = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth)
|
||
var toFrame = self.frame
|
||
toFrame.origin.x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - targetWidth)/2
|
||
toFrame.size.width = targetWidth
|
||
if canSelectedWithAnimation(model: model) {
|
||
UIView.animate(withDuration: scrollAnimationDuration, delay: 0, options: .curveEaseOut, animations: {
|
||
self.frame = toFrame
|
||
}) { (_) in
|
||
}
|
||
}else {
|
||
frame = toFrame
|
||
}
|
||
}
|
||
|
||
}
|