Skip to content

Commit

Permalink
Use custom zoom control as an example
Browse files Browse the repository at this point in the history
  • Loading branch information
Anatoly Petrov authored and ok-gurov committed May 6, 2021
1 parent 1752b15 commit 96bbe62
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 4 deletions.
4 changes: 4 additions & 0 deletions app.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
4B96E77B2608C14C0057C366 /* Arcdegree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B96E7792608C14C0057C366 /* Arcdegree.swift */; };
4B96EBDC2608C5780057C366 /* View+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B96EBDA2608C5780057C366 /* View+Helpers.swift */; };
4B96EBDD2608C5780057C366 /* Channel+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B96EBDB2608C5780057C366 /* Channel+Helpers.swift */; };
4B96D147260224AB0057C366 /* CustomZoomControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B96D146260224AB0057C366 /* CustomZoomControl.swift */; };
4BADDFCC2528016600FBF589 /* SuggestResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BADDFCB2528016600FBF589 /* SuggestResultView.swift */; };
4BADDFCF252801BD00FBF589 /* SuggestResultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BADDFCE252801BC00FBF589 /* SuggestResultViewModel.swift */; };
4BADDFD2252802A500FBF589 /* SearchResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BADDFD1252802A500FBF589 /* SearchResultView.swift */; };
Expand Down Expand Up @@ -98,6 +99,7 @@
4B96E7792608C14C0057C366 /* Arcdegree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Arcdegree.swift; sourceTree = "<group>"; };
4B96EBDA2608C5780057C366 /* View+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+Helpers.swift"; sourceTree = "<group>"; };
4B96EBDB2608C5780057C366 /* Channel+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Channel+Helpers.swift"; sourceTree = "<group>"; };
4B96D146260224AB0057C366 /* CustomZoomControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomZoomControl.swift; sourceTree = "<group>"; };
4BADDFCB2528016600FBF589 /* SuggestResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestResultView.swift; sourceTree = "<group>"; };
4BADDFCE252801BC00FBF589 /* SuggestResultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestResultViewModel.swift; sourceTree = "<group>"; };
4BADDFD1252802A500FBF589 /* SearchResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -273,6 +275,7 @@
children = (
4BBE7E1F25264F2B00D7EBDB /* MapView.swift */,
0991909525B96E1C00F4235B /* MapControl.swift */,
4B96D146260224AB0057C366 /* CustomZoomControl.swift */,
);
path = Map;
sourceTree = "<group>";
Expand Down Expand Up @@ -423,6 +426,7 @@
4BADDFD2252802A500FBF589 /* SearchResultView.swift in Sources */,
4B96D1902603682B0057C366 /* StylePickerViewModel.swift in Sources */,
0991909625B96E1C00F4235B /* MapControl.swift in Sources */,
4B96D147260224AB0057C366 /* CustomZoomControl.swift in Sources */,
4B4291652527A49C006E74BE /* SuggestView.swift in Sources */,
B709914F25FA6B6F00B2F1A5 /* RenderedObjectInfo+Helpers.swift in Sources */,
4B96D18E260348C10057C366 /* StylePickerView.swift in Sources */,
Expand Down
4 changes: 4 additions & 0 deletions app/Container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ final class Container {
[mapFactory = self.mapFactory] in
mapFactory.mapView
},
customZoomControlFactory: {
[sdk = self.sdk] in
CustomZoomControl(map: sdk.map)
},
mapControlFactory: self.mapFactory.mapControlFactory
)
return viewFactory
Expand Down
104 changes: 104 additions & 0 deletions app/Map/CustomZoomControl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import UIKit
import PlatformSDK

/// Блок управления масштабом карты.
public final class CustomZoomControl: UIControl {
public static override var requiresConstraintBasedLayout: Bool { true }
private let stack: UIStackView

init(map: Map) {
let model = createZoomControlModel(map: map)

let zoomIn = ZoomButton(model: model, direction: .zoomIn)
let zoomInImage = UIImage(systemName: "plus.magnifyingglass")
zoomIn.setImage(zoomInImage, for: .normal)

let zoomOut = ZoomButton(model: model, direction: .zoomOut)
let zoomOutImage = UIImage(systemName: "minus.magnifyingglass")
zoomOut.setImage(zoomOutImage, for: .normal)

self.stack = UIStackView(arrangedSubviews: [zoomIn, zoomOut])
self.stack.distribution = .fillEqually
self.stack.alignment = .fill
self.stack.axis = .vertical

super.init(frame: .zero)

self.addSubview(self.stack)
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("Use init(map:)")
}

public override func layoutSubviews() {
super.layoutSubviews()
self.stack.frame = self.bounds
}
}

private final class ZoomButton: UIButton {
private let model: ZoomControlModel
private let direction: ZoomControlButton
private var connection: ICancellable = NoopCancellable()

init(model: ZoomControlModel, direction: ZoomControlButton) {
self.model = model
self.direction = direction

super.init(frame: .zero)

self.contentVerticalAlignment = .fill
self.contentHorizontalAlignment = .fill

self.addTarget(
self,
action: #selector(self.startZoom),
for: .touchDown
)
self.addTarget(
self,
action: #selector(self.stopZoom),
for: [.touchCancel, .touchUpInside, .touchUpOutside]
)

// Реагируем на отключение действия — выключаем кнопку.
// Такое возможно при достижении предела изменения масштаба.
self.connection = self.model.isEnabled(button: self.direction).sink {
[weak self] isEnabled in
DispatchQueue.main.async {
self?.isEnabled = isEnabled
}
}
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

@objc private func startZoom() {
UIView.animate(
withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 5,
animations: {
self.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
})
self.model.setPressed(button: self.direction, value: true)
}

@objc private func stopZoom() {
UIView.animate(
withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 5,
animations: {
self.transform = CGAffineTransform.identity
})
self.model.setPressed(button: self.direction, value: false)
}
}
4 changes: 1 addition & 3 deletions app/Root/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ struct RootView: View {
HStack {
Spacer()
self.viewFactory.makeZoomControl()
.frame(width: 60, height: 128)
.fixedSize()
.transformEffect(.init(scaleX: 0.8, y: 0.8))
.frame(width: 60, height: 120)
.padding(10)
}
}
Expand Down
5 changes: 4 additions & 1 deletion app/Root/RootViewFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ struct RootViewFactory {
private let markerViewModel: MarkerViewModel
private let routeViewModel: RouteViewModel
private let mapUIViewFactory: () -> UIView & IMapView
private let customZoomControlFactory: () -> UIView
private let mapControlFactory: IMapControlFactory

init(
viewModel: RootViewModel,
markerViewModel: MarkerViewModel,
routeViewModel: RouteViewModel,
mapUIViewFactory: @escaping () -> UIView & IMapView,
customZoomControlFactory: @escaping () -> UIView,
mapControlFactory: IMapControlFactory
) {
self.viewModel = viewModel
self.markerViewModel = markerViewModel
self.routeViewModel = routeViewModel
self.mapUIViewFactory = mapUIViewFactory
self.customZoomControlFactory = customZoomControlFactory
self.mapControlFactory = mapControlFactory
}

Expand All @@ -27,7 +30,7 @@ struct RootViewFactory {
}

func makeZoomControl() -> some View {
MapControl(controlFactory: self.mapControlFactory.makeZoomControl)
MapControl(controlFactory: self.customZoomControlFactory)
}

func makeSearchView() -> some View {
Expand Down

0 comments on commit 96bbe62

Please sign in to comment.