Common Zoom
Although the zooming code is quite distinct for both platforms let´s move it to the common library as good as we can. This will help us later when we implement additional clients such as JavaFx or JavaScript.
var cellSize = 15.0f
var minCellSize = 7.0f
var maxCellSize = 60.0f
var cellPadding = 3.0f
fun scale(scaleFactor: Float) {
val newCellSize = cellSize * scaleFactor
cellSize = when {
newCellSize < minCellSize -> minCellSize
newCellSize > maxCellSize -> maxCellSize
else -> newCellSize
}
}
Once again we integrate the common function first into our Android project and then into our iOS project.
private val zoomListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
val oldCellSize = board.cellSize
board.scale(detector.scaleFactor)
val realScaleFactor = board.cellSize / oldCellSize
val distX = detector.focusX - offsetX
val distY = detector.focusY - offsetY
val corrX = distX - distX * realScaleFactor
val corrY = distY - distY * realScaleFactor
offsetX += corrX
offsetY += corrY
invalidate()
return true
}
}
@ViewBuilder
var body: some View {
if self.board != nil {
VStack(spacing: CGFloat(self.board!.cellPadding)) {
ForEach(0..<Int(self.board!.rows)) { rowIdx in
HStack(spacing: CGFloat(self.board!.cellPadding)) {
ForEach(0..<Int(self.board!.columns)) { columnIdx in
self.createCell(board: self.board!, rowIdx: rowIdx, columnIdx: columnIdx)
}
}
}
}
.gesture(MagnificationGesture()
.onChanged{value in
let delta = value / self.lastScaleValue
self.lastScaleValue = value
self.board!.scale(scaleFactor: Float(delta))
}.onEnded{value in
self.lastScaleValue = 1.0
})
}
else {
EmptyView()
}
}