Here is my code, I didnβt have time to filter the code, but it includes the whole function, such as rotation, translation and scaling of the image in the scroll.
import UIKit
import AudioToolbox import PureLayout
let MIN_ZOOM_SCALE: CGFloat = 1 let MAX_ZOOM_SCALE: CGFloat = 5 let DEFAULT_ZOOM_SCALE: CGFloat = 2
let markerSize: CGFloat = GET_PROPORTIONAL_HEIGHT (height: 50)
class ViewController: UIViewController, UIScrollViewDelegate, AGConfiguratorDelegate, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var btnTest: UIButton! @IBOutlet weak var btnTest1: UIButton! @IBOutlet weak var btnTest2: UIButton! var markerCount:Int = 0 var arrPlacedMarkers = [UIButton]() var isPullViewOpened:Bool = false var table:UITableView! var viewHeader:UIView! var viewBtnContainer:UIView! var timerRotateButtons:Timer! var btnRotateLeft:UIButton! var btnRotateRight:UIButton! var selectedBtnMarker:UIButton? var maxYTouchPointToScrollUp:CGFloat = -1 let configurator = AGPullViewConfigurator()
// var xx = SCREEN_WIDTH * 257.076682316119 / self.imageView.image! .size.width // var yy = SCREEN_HEIGHT * 599.097704011388 / self.imageView.image! .size.height
// var xx = SCREEN_WIDTH * 395.150738305702 / self.imageView.image! .size.width // var yy = SCREEN_HEIGHT * 295.700957624736 / self.imageView.image! .size.height
var xx = SCREEN_WIDTH * 253.0 / self.imageView.image!.size.width var yy = SCREEN_HEIGHT * 591.549295774648 / self.imageView.image!.size.height print("xx : \(xx) yy : \(yy) ") xx = xx + (markerSize/2) yy = yy + (markerSize/2) print("xx : \(xx) yy : \(yy) ") self.addButtonWithAtPoint(touchedPoint: CGPoint(x: xx, y: yy)) print("\nMAP : \(self.imageView.image!.size)") print("SCR : \(self.scrollView.frame)") print("VIE : \(self.view.frame)") } } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() } //For correct working of layout in early versions of iOS 10 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() self.configurator.layoutPullView() let pullViewHeight = self.configurator.contentView.superview?.frame.size.height self.maxYTouchPointToScrollUp = (SCREEN_HEIGHT - (pullViewHeight)! - scrollView.frame.origin.y) } //MARK:- SAVE MARKER IN DEFAULTS func saveMarkerInDefault(){ var counter:Int = 0 for eachButton in arrPlacedMarkers{ print(" \(counter) x : \(eachButton.frame.origin.x) y : \(eachButton.frame.origin.y)") if(counter == 0){ let xPos = eachButton.frame.origin.x let yPos = eachButton.frame.origin.y let newXPos = (imageView.image!.size.width * xPos) / SCREEN_WIDTH let newYPos = (imageView.image!.size.height * yPos) / SCREEN_HEIGHT print("default stored x : \(newXPos) y : \(newYPos)") UserDefaults.standard.set(newXPos, forKey: "xPos") UserDefaults.standard.set(newYPos, forKey: "yPos") } counter += 1 } } func getMarkerFromDefaults() -> [AIMarker]{ var arrSavedMarker = [AIMarker]() if let xPos = UserDefaults.standard.object(forKey: "xPos") as? CGFloat{ if let yPos = UserDefaults.standard.object(forKey: "yPos") as? CGFloat{ let marker = AIMarker(x: xPos, y: yPos) arrSavedMarker.append(marker) } } return arrSavedMarker } //MARK:- UI SETUP func doSetupUI() { btnTest.isHidden = true btnTest1.isHidden = true btnTest2.isHidden = true // IMAGEVIEW imageView.clipsToBounds = true imageView.contentMode = UIViewContentMode.scaleToFill imageView.isUserInteractionEnabled = true imageView.image = UIImage(named: "RoomPlan2") self.scrollView.applyBorderDefault() // SCROLLVIEW scrollView.minimumZoomScale = MIN_ZOOM_SCALE scrollView.maximumZoomScale = MAX_ZOOM_SCALE scrollView.zoomScale = DEFAULT_ZOOM_SCALE scrollView.delegate = self scrollView.bounces = false scrollView.bouncesZoom = false // SINGLE TAP let singleTap = UITapGestureRecognizer(target: self, action:
//viewBtnContainer.applyBorder(color: UIColor.red, width: 2) //btnRotateRight.applyBorderDefault () //btnRotateLeft.applyBorderDefault ()
} //MARK:- ********* func doSetupPullView(){ self.configurator.setupPullView(forSuperview: self.view, colorScheme: ColorSchemeTypeWhite)
// let pullViewHeight = self.configurator.contentView.superview? .frame.size.height // print ("PULL VIEW HEIGHT: ((self.configurator.contentView.superview? .frame)!)") // print (" IMG: (imageView.frame) SC: (scrollView.frame) ") // print (" SCREEN HEIGHT: (SCREEN_HEIGHT) XX: (SCREEN_HEIGHT - pullViewHeight! - scrollView.frame.origin.y) ") // let maxBottomTapValue = (SCREEN_HEIGHT - pullViewHeight! - scrollView.frame.origin.y)
viewBtnContainer.autoPinEdge(toSuperviewEdge: ALEdge.bottom, withInset: (height: self.configurator.contentView.superview!.frame.size.height)) self.configurator.percentOfFilling = 90//85 self.configurator.delegate = self self.configurator.needBounceEffect = true self.configurator.animationDuration = 0.45 self.configurator.enableShowingWithTouch = true; self.configurator.enableHidingWithTouch = true; self.configurator.enableBlurEffect(withBlurStyle: .dark) self.hidePullViewFromBottom(animated: false) //Test UITableView table = UITableView(frame: CGRect(), style: .plain) table.dataSource = self table.delegate = self table.separatorStyle = .none; table.backgroundColor = UIColor.clear table.isUserInteractionEnabled = false let viewFooter = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: GET_PROPORTIONAL_HEIGHT(height: 40))) viewFooter.backgroundColor = UIColor.lightGray let btnRemoveMarker = UIButton(forAutoLayout: ()) btnRemoveMarker.setTitle("Remove Marker", for: .normal) btnRemoveMarker.addTarget(self, action:
// print ("already open") return} tempSuperView? .isHidden = false self.configurator.doShowTopBottomButtons () tempSuperView? .transform = CGAffineTransform.init (translationX: 0, y: tempSuperView! .height) UIView.animate (withDuration: 0.2, animations: {tempSuperView? .Transform = CGAffineTransform.init (translateX: 0, y: 0)}) {(bbb) in}
showRotateButtons(withAnimation: isAnimated) } func hidePullViewFromBottom(animated isAnimated:Bool){ let tempSuperView = self.configurator.contentView.superview if(tempSuperView!.transform.isIdentity && tempSuperView?.isHidden == true){
// print ("already closed") return}
let duration:TimeInterval = isAnimated ? 0.2 : 0.0 UIView.animate(withDuration: duration, animations: { tempSuperView?.transform = CGAffineTransform.init(translationX: 0, y: tempSuperView!.height) }) { (bbb) in tempSuperView?.transform = CGAffineTransform.init(translationX: 0, y: 0) tempSuperView?.isHidden = true self.configurator.doHideTopBottomButtons() } hideRotateButtons(withAnimation: isAnimated) } //MARK:- SHOW / HIDE ROTATE BUTTONS func showRotateButtons(withAnimation animated:Bool){ if self.viewBtnContainer != nil{ UIView.animate(withDuration: animated ? 0.2 : 0.0, animations: { self.viewBtnContainer.alpha = 1 }) { (bb) in } } } func hideRotateButtons(withAnimation animated:Bool){ if self.viewBtnContainer != nil{ UIView.animate(withDuration: animated ? 0.1 : 0.0, animations: { self.viewBtnContainer.alpha = 0 }) { (bb) in } } } //MARK:- ADD BUTTON func addButtonWithAtPoint(touchedPoint:CGPoint) { print("\n\n\nTOUCH POINT : \(touchedPoint)") // CREATING BUTTON FOR MARKER let xPos = touchedPoint.x - (markerSize/2) let yPos = touchedPoint.y - (markerSize/2) let btnMarker = UIButton(type: .custom) btnMarker.frame = CGRect(x: xPos, y: yPos, width: markerSize, height: markerSize) print("xpos : \(xPos) ypos : \(yPos)----\(btnMarker.frame)") print("ce----\(btnMarker.center)") btnMarker.setTitleColor(UIColor.white, for: .normal) btnMarker.setTitle("M\(markerCount + 1)", for: .normal) btnMarker.tag = markerCount btnMarker.titleLabel?.numberOfLines = 1 btnMarker.titleLabel?.adjustsFontSizeToFitWidth = true btnMarker.titleLabel?.lineBreakMode = .byClipping btnMarker.addTarget(self, action:
// let rotateGesture = UIRotationGestureRecognizer (target: self, action: #selector (self.rotationGestureHandler (_ :))) //btnMarker.addGestureRecognizer(rotateGesture)
// ADDING MARKER IN MAIN ARRAY self.arrPlacedMarkers.append(btnMarker) markerCount += 1 // SCALING MARKER AS PER MAP CURRENT ZOOM SCALE let invertedTransform = CGAffineTransform.inverted(imageView.transform) for eachSubview in imageView.subviews{ let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a)); eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle)) } playVibrate() presentPullViewForMarker(btnMarker: btnMarker)
//btnMarker.applyBorderDefault ()}
func playVibrate(){
// AudioServicesPlaySystemSound (kSystemSoundID_Vibrate); }
func presentPullViewForMarker(btnMarker:UIButton){ self.selectedBtnMarker = btnMarker self.showPullViewAtBottom(animated: true) (viewHeader.subviews.first as! UIButton).setTitle("Add Photos for : \((btnMarker.titleLabel?.text)!)", for: .normal) }
// let secondVC = self.storyboard? .instantiateViewController (withIdentifier: "SecondViewController") like! SecondViewController //self.navigationController?.pushViewController(secondVC, animated: true) //self.present(secondVC, animated: true) {//
//}}
func btnRemoveMarkerTapHandler(_ sender:UIButton){ if let selectedBtnMarker = self.selectedBtnMarker { showAlertWithTitle(title: "Remove Marker \((selectedBtnMarker.titleLabel?.text)!)", message: "Are you sure you want to remove this marker ?", buttons: ["Cancel","Yes"], showsCancelOption: false, completion: { (selectedIndex) in if(selectedIndex == 1){ if let validIndex = self.arrPlacedMarkers.index(of: selectedBtnMarker){ self.arrPlacedMarkers.remove(at: validIndex) self.selectedBtnMarker?.removeFromSuperview() DispatchQueue.main.async { self.configurator.hide(animated: true) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.4) { self.hidePullViewFromBottom(animated: true) } } } } }) } } //MARK:- func btnRotateLeftHandler(sender:UIButton){ if let selectedBtnMarker = self.selectedBtnMarker { selectedBtnMarker.rotate(angle: -5) } } func btnRotateRightHandler(sender:UIButton){ if let selectedBtnMarker = self.selectedBtnMarker { selectedBtnMarker.rotate(angle: 5) } } //MARK:- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() cell.backgroundColor = UIColor.clear cell.textLabel?.textColor = UIColor.gray cell.textLabel?.text = "Photo \(indexPath.row + 1)" return cell; } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { viewHeader = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 100)) viewHeader.backgroundColor = UIColor.lightGray let btnAddPhotos = UIButton(forAutoLayout: ()) btnAddPhotos.setTitle("Add Photos", for: .normal) btnAddPhotos.addTarget(self, action: #selector(self.btnAddPhotosTapHandler(_:)), for: .touchUpInside) viewHeader.addSubview(btnAddPhotos) btnAddPhotos.autoCenterInSuperview() return viewHeader } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return GET_PROPORTIONAL_HEIGHT(height: 40) } //MARK:- override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { self.configurator.handleTouchesBegan(touches) } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { self.configurator.handleTouchesMoved(touches) } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { self.configurator.handleTouchesEnded(touches) } //MARK:- AGPullView DELEGATES func didDrag(_ pullView: AGPullView!, withOpeningPercent openingPercent: Float) {
// print ("did drag: (openingPercent)") openingPercent> 0.0? hideRotateButtons (withAnimation: true): showRotateButtons (withAnimation: true)}
func didShow(_ pullView: AGPullView!) { print("shown"); isPullViewOpened = true table.isUserInteractionEnabled = true hideRotateButtons(withAnimation: true) } func didHide(_ pullView: AGPullView!) { print("hidden") isPullViewOpened = false table.isUserInteractionEnabled = false showRotateButtons(withAnimation: true) } func didTouch(toShow pullView: AGPullView!) { print("touched to show") } func didTouch(toHide pullView: AGPullView!) { print("touched to hide") } //MARK:- PAN GESTURE HANDLER func panGestureHandler(_ recognizer:UIPanGestureRecognizer){ if(recognizer.state == .changed || recognizer.state == .ended) { let draggedButton = recognizer.view var newFrame = draggedButton?.frame if(newFrame!.origin.x < 0.0){ newFrame!.origin.x = 0.0 } if(newFrame!.origin.y < 0.0){ newFrame!.origin.y = 0.0 } let oldXPlusWidth = newFrame!.origin.x + newFrame!.size.width let trailingMarginToKeep = self.imageView.bounds.size.width - newFrame!.size.width if(oldXPlusWidth > self.imageView.bounds.size.width){ newFrame!.origin.x = trailingMarginToKeep } let oldYPlusHeight = newFrame!.origin.y + newFrame!.size.height let bottomMarginToKeep = self.imageView.bounds.size.height - newFrame!.size.height if(oldYPlusHeight > self.imageView.bounds.size.height){ newFrame!.origin.y = bottomMarginToKeep } let translationPoint = recognizer.translation(in: self.imageView) newFrame?.origin.x += translationPoint.x newFrame?.origin.y += translationPoint.y let centerX:CGFloat = newFrame!.origin.x + (newFrame!.size.width/2) let centerY:CGFloat = newFrame!.origin.y + (newFrame!.size.height/2) draggedButton?.center = CGPoint(x: centerX, y: centerY) recognizer.setTranslation(CGPoint.zero, in: self.imageView) } } //MARK:- ROTATION GESTURE HANDLER func rotationGestureHandler(_ recognizer:UIRotationGestureRecognizer){ recognizer.view!.transform = recognizer.view!.transform.rotated(by: recognizer.rotation) recognizer.rotation = 0 } //MARK:- LONG PRESS HANDLER func longPressHandlerForMapImageView(_ sender:UILongPressGestureRecognizer){ if sender.state == .began{
//self.addButtonWithAtPoint(touchhed: sender.location (in: sender.view)) self.addButtonWithAtPoint (touchhed: sender.location (in: imageView))}}
func longPressHandlerForRotateLeftButton(_ sender:UILongPressGestureRecognizer){ switch sender.state { case .began: self.timerRotateButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.timerHandlerForRotateButton(sender:)), userInfo: sender.view, repeats: true) case .ended: self.timerRotateButtons.invalidate() self.timerRotateButtons = nil default: break } } func longPressHandlerForRotateRightButton(_ sender:UILongPressGestureRecognizer){ switch sender.state { case .began: self.timerRotateButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.timerHandlerForRotateButton(sender:)), userInfo: sender.view, repeats: true) case .ended: self.timerRotateButtons.invalidate() self.timerRotateButtons = nil default: break } }
// print ("SINGLE TAP")
if(self.isPullViewOpened){
// print ("SINGLE TAP: don't close .. open")} More {self.hidePullViewFromBottom (animated: true)}
} func doubleTapHandler(_ sender:UITapGestureRecognizer){
// print ("DOUBLE TAP (scrollView.minimumZoomScale) (scrollView.maximumZoomScale) (scrollView.zoomScale)")
// ZOOM RESET if(scrollView.zoomScale > scrollView.minimumZoomScale){ scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true) }else{ // ZOOM IN let zoomRect = self.zoomRectForScale(scale: DEFAULT_ZOOM_SCALE, withCenter: sender.location(in: sender.view)) scrollView.zoom(to: zoomRect, animated: true) } } func zoomRectForScale(scale:CGFloat, withCenter center:CGPoint) -> CGRect { var zooomRect:CGRect = CGRect() zooomRect.size.height = imageView.frame.size.height / scale zooomRect.size.width = imageView.frame.size.width / scale let tempCenter = imageView.convert(center, from: self.imageView) zooomRect.origin.x = tempCenter.x - (zooomRect.size.width / 2.0) zooomRect.origin.y = tempCenter.y - (zooomRect.size.height / 2.0) return zooomRect } //MARK:- BUTTION EVENTS @IBAction func btnTestPressed(_ sender: Any) { // print("BTN 10 % TAP") showAlertWithTitle(title: "title", message: "message", buttons: ["b1","b2"], showsCancelOption: false) { (selecgtedIndex) in print("selected \(selecgtedIndex)") } } @IBAction func btnTest1Pressed(_ sender: Any) { // print("\n\nBTN 90 % TAP") } @IBAction func btnTest2Pressed(_ sender: Any) { // print("BTN RESET TAP") scrollView.setZoomScale(1, animated: true) } //MARK:- SCROLLVIEW DELEGATE func viewForZooming(in scrollView: UIScrollView) -> UIView? { return imageView } func scrollViewDidScroll(_ scrollView: UIScrollView) {
// print ("\ n \ n (#function) (scrollView.zoomScale) __ (scrollView.contentSize) __ (scrollView.contentOffset) \ n")
let invertedTransform = CGAffineTransform.inverted(imageView.transform) for eachSubview in imageView.subviews{ let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a)); eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle)) } if(self.isPullViewOpened){
// print ("scroll: do not close .. open")} More {self.hidePullViewFromBottom (animated: true)}}
//MARK:- func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { print("\n\(#function)\n") return false }
// func scrollViewDidScrollToTop (_ scrollView: UIScrollView) {// print ("\ n (#function) \ n") //} // //
//// NOTE: - // func scrollViewDidEndScrollingAnimation (_ scrollView: UIScrollView) {// print ("\ n (#function) \ n") //} // NOTE: - // func scrollViewWillBeginZooming (_ scrollView: UIScrollView , with a view: UIView?) {// print ("\ n (#function) \ n") //} // func scrollViewDidZoom (_ scrollView: UIScrollView) {// print ("\ n (#function) (scrollView .zoomScale) __ (scrollView.contentSize) __ (scrollView.contentOffset) ") //} func scrollViewDidEndZooming (_ scrollView: UIScrollView, with view: UIView ?, atScale scale: CGFloat) {// print (" \ n (#function ) \ n ")
let invertedTransform = CGAffineTransform.inverted(imageView.transform) for eachSubview in imageView.subviews{ let angle = atan2f(Float(eachSubview.transform.b), Float(eachSubview.transform.a)); eachSubview.transform = invertedTransform().rotated(by: CGFloat(angle)) }
// for I'm at 0 ..
// for I'm at 0 ..
}
// func scrollViewWillBeginDragging (_ scrollView: UIScrollView) {// print ("\ n (#function) \ n") //} // func scrollViewWillEndDragging (_ scrollView: UIScrollView, withVelocity speed: CGPoint, targetContentOffset: UnsafeMutablePointer) {/ / print ("\ n (#function) \ n") //} // func scrollViewDidEndDragging (_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {// print ("\ n (#function) \ n") // } // func scrollViewWillBeginDecelerating (_ scrollView: UIScrollView) {// print ("\ n (#function) \ n") //} // func scrollViewDidEndDecelerating (_ scrollView: UIScrollView) {// print ("\ n (# function) \ n ") //}
}