Skip to content

Commit

Permalink
refactor: use Core Graphics instead of UIViews to draw overlay indica…
Browse files Browse the repository at this point in the history
…tor lines (#291)

* refactor: use Core Graphics instead of UIViews to draw overlay indicator lines

* refactor: use one path instead of two paths when drawing indicator lines

* refactor: rename helpLine to indicatorLine
  • Loading branch information
guoyingtao authored Mar 13, 2023
1 parent f432e36 commit 88f09a2
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 119 deletions.
120 changes: 39 additions & 81 deletions Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,19 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {

private var hintLine = UIView()
private var tappedEdge: CropViewAuxiliaryIndicatorHandleType = .none
private var gridColor = UIColor(white: 0.8, alpha: 1)
private var gridMainColor = UIColor.white
private var gridSecondaryColor = UIColor.lightGray

var cropBoxHotAreaUnit: CGFloat = 42

var gridHidden = true

var gridLineNumberType: GridLineNumberType = .crop {
var gridHidden = true {
didSet {
setupGridLines()
layoutGridLines()
setNeedsDisplay()
}
}

var gridLineNumberType: GridLineNumberType = .crop

private var horizontalGridLines: [UIView] = []
private var verticalGridLines: [UIView] = []
private var borderLine: UIView = UIView()
private var cornerHandles: [UIView] = []
private var edgeLineHandles: [UIView] = []
Expand All @@ -52,12 +50,14 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
init(frame: CGRect, cropBoxHotAreaUnit: CGFloat) {
super.init(frame: frame)
clipsToBounds = false
backgroundColor = .clear
self.cropBoxHotAreaUnit = cropBoxHotAreaUnit
setup()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
backgroundColor = .clear
}

private func createNewLine() -> UIView {
Expand All @@ -82,7 +82,6 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
edgeLineHandles.append(createNewLine())
}

setupGridLines()
hintLine.backgroundColor = boarderHintColor

setupAccessibilityHelperViews()
Expand All @@ -107,6 +106,33 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
return result
}

override func draw(_ rect: CGRect) {
if !gridHidden {
let indicatorLineNumber = gridLineNumberType.getIndicatorLineNumber()

for index in 0..<indicatorLineNumber {
if gridLineNumberType == .rotate && (index + 1) % 3 != 0 {
gridSecondaryColor.setStroke()
} else {
gridMainColor.setStroke()
}

let indicatorLinePath = UIBezierPath()
indicatorLinePath.lineWidth = 1

let horizontalY = CGFloat(index + 1) * frame.height / CGFloat(indicatorLineNumber + 1)
indicatorLinePath.move(to: CGPoint(x: 0, y: horizontalY))
indicatorLinePath.addLine(to: CGPoint(x: frame.width, y: horizontalY))

let horizontalX = CGFloat(index + 1) * frame.width / CGFloat(indicatorLineNumber + 1)
indicatorLinePath.move(to: CGPoint(x: horizontalX, y: 0))
indicatorLinePath.addLine(to: CGPoint(x: horizontalX, y: frame.height))

indicatorLinePath.stroke()
}
}
}

private func layoutLines() {
guard bounds.isEmpty == false else {
return
Expand All @@ -115,55 +141,9 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
layoutOuterLines()
layoutCornerHandles()
layoutEdgeLineHandles()
layoutGridLines()
setGridShowStatus()
layoutAccessibilityHelperViews()
}

private func setGridShowStatus() {
horizontalGridLines.forEach { $0.alpha = gridHidden ? 0 : 1 }
verticalGridLines.forEach { $0.alpha = gridHidden ? 0 : 1 }
}

private func layoutGridLines() {
let helpLineNumber = gridLineNumberType.getHelpLineNumber()
for index in 0..<helpLineNumber {
horizontalGridLines[index].frame = CGRect(x: 0,
y: CGFloat(index + 1) * frame.height / CGFloat(helpLineNumber + 1),
width: frame.width,
height: 1)
verticalGridLines[index].frame = CGRect(x: CGFloat(index + 1) * frame.width / CGFloat(helpLineNumber + 1),
y: 0,
width: 1,
height: frame.height)
}
}

private func setupGridLines() {
setupVerticalGridLines()
setupHorizontalGridLines()
}

private func setupHorizontalGridLines() {
horizontalGridLines.forEach { $0.removeFromSuperview() }
horizontalGridLines.removeAll()
for _ in 0..<gridLineNumberType.getHelpLineNumber() {
let view = createNewLine()
view.backgroundColor = gridColor
horizontalGridLines.append(view)
}
}

private func setupVerticalGridLines() {
verticalGridLines.forEach { $0.removeFromSuperview() }
verticalGridLines.removeAll()
for _ in 0..<gridLineNumberType.getHelpLineNumber() {
let view = createNewLine()
view.backgroundColor = gridColor
verticalGridLines.append(view)
}
}


private func layoutOuterLines() {
borderLine.frame = CGRect(x: -borderThickness,
y: -borderThickness,
Expand Down Expand Up @@ -238,37 +218,15 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
}
}
}

func setGrid(hidden: Bool, animated: Bool = false) {
self.gridHidden = hidden

func setGridLinesShowStatus () {
horizontalGridLines.forEach { $0.alpha = hidden ? 0 : 1 }
verticalGridLines.forEach { $0.alpha = hidden ? 0 : 1}
}

if animated {
let duration = hidden ? 0.35 : 0.2
UIView.animate(withDuration: duration) {
setGridLinesShowStatus()
}
} else {
setGridLinesShowStatus()
}
}

func hideGrid() {
gridLineNumberType = .none
}


func handleIndicatorHandleTouched(with tappedEdge: CropViewAuxiliaryIndicatorHandleType) {
guard tappedEdge != .none else {
return
}

self.tappedEdge = tappedEdge

setGrid(hidden: false, animated: true)
gridHidden = false
gridLineNumberType = .crop

func handleHintLine() {
Expand Down Expand Up @@ -310,7 +268,7 @@ class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
}

func handleEdgeUntouched() {
setGrid(hidden: true, animated: true)
gridHidden = true
hintLine.removeFromSuperview()
tappedEdge = .none
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/Mantis/CropView/CropView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@ class CropView: UIView {
case .touchImage:
cropMaskViewManager.showDimmingBackground(animated: true)
cropAuxiliaryIndicatorView.gridLineNumberType = .crop
cropAuxiliaryIndicatorView.setGrid(hidden: false, animated: true)
cropAuxiliaryIndicatorView.gridHidden = false
case .touchCropboxHandle(let tappedEdge):
cropAuxiliaryIndicatorView.handleIndicatorHandleTouched(with: tappedEdge)
rotationDial?.isHidden = true
cropMaskViewManager.showDimmingBackground(animated: true)
case .touchRotationBoard:
cropAuxiliaryIndicatorView.gridLineNumberType = .rotate
cropAuxiliaryIndicatorView.setGrid(hidden: false, animated: true)
cropAuxiliaryIndicatorView.gridHidden = false
cropMaskViewManager.showDimmingBackground(animated: true)
case .betweenOperation:
cropAuxiliaryIndicatorView.handleEdgeUntouched()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum GridLineNumberType {
case crop
case rotate

func getHelpLineNumber() -> Int {
func getIndicatorLineNumber() -> Int {
switch self {
case .none:
return 0
Expand All @@ -29,8 +29,6 @@ protocol CropAuxiliaryIndicatorViewProtocol: UIView {
var gridHidden: Bool { get set }
var cropBoxHotAreaUnit: CGFloat { get set }

func setGrid(hidden: Bool, animated: Bool)
func hideGrid()
func handleIndicatorHandleTouched(with tappedEdge: CropViewAuxiliaryIndicatorHandleType)
func handleEdgeUntouched()
}
33 changes: 0 additions & 33 deletions Tests/MantisTests/CropAuxiliaryIndicatorViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,40 +59,7 @@ final class CropAuxiliaryIndicatorViewTests: XCTestCase {
XCTAssertEqual(cropAuxiliaryIndicatorView.subviews.count, subviewCount + 1)
XCTAssertEqual(cropAuxiliaryIndicatorView.gridLineNumberType, .crop)
}

func testHideGrid() {
cropAuxiliaryIndicatorView.gridLineNumberType = .crop
XCTAssertEqual(cropAuxiliaryIndicatorView.gridLineNumberType, .crop)
cropAuxiliaryIndicatorView.hideGrid()
XCTAssertEqual(cropAuxiliaryIndicatorView.gridLineNumberType, .none)
}

func testSetGrid() {
cropAuxiliaryIndicatorView.setGrid(hidden: true)
XCTAssertTrue(cropAuxiliaryIndicatorView.gridHidden)

var visibleSubViewsCount = cropAuxiliaryIndicatorView.subviews.filter { $0.alpha == 1 }.count

cropAuxiliaryIndicatorView.gridLineNumberType = .crop
cropAuxiliaryIndicatorView.setGrid(hidden: false)
XCTAssertFalse(cropAuxiliaryIndicatorView.gridHidden)

var visibleSubViewsCount1 = cropAuxiliaryIndicatorView.subviews.filter { $0.alpha == 1 }.count
XCTAssertEqual(visibleSubViewsCount1, visibleSubViewsCount + 2 * 2)

cropAuxiliaryIndicatorView.setGrid(hidden: true)
XCTAssertTrue(cropAuxiliaryIndicatorView.gridHidden)

visibleSubViewsCount = cropAuxiliaryIndicatorView.subviews.filter { $0.alpha == 1 }.count

cropAuxiliaryIndicatorView.gridLineNumberType = .rotate
cropAuxiliaryIndicatorView.setGrid(hidden: false)
XCTAssertFalse(cropAuxiliaryIndicatorView.gridHidden)

visibleSubViewsCount1 = cropAuxiliaryIndicatorView.subviews.filter { $0.alpha == 1 }.count
XCTAssertEqual(visibleSubViewsCount1, visibleSubViewsCount + 2 * 8)
}

func testHandleCornerHandleTouched() {
let subviewCount = cropAuxiliaryIndicatorView.subviews.count
cropAuxiliaryIndicatorView.handleIndicatorHandleTouched(with: .none)
Expand Down

0 comments on commit 88f09a2

Please sign in to comment.