BLOGブログ. 業務日誌

画像ビューワのようにUIScrollViewを使って、ピンチインでUIViewの拡大後に、ドラッグしてスクロールできるようにする。
すごく苦戦したので復習 …… 勉強、勉強の毎日である。
Xcode 6.3
Deployment Target 8.0
まず簡単にviewForZoomingInScrollView使ったパターン。
実際に作ったアプリは拡大時の処理が複雑だったので採用しなかった。
import UIKit class ViewController: UIViewController, UIScrollViewDelegate { // view var baseScrollView:UIScrollView?=nil let baseScrollViewTag:Int=1 var myView:UIView?=nil // viewのサイズ let viewWidth:CGFloat=300 let viewHeight:CGFloat=300 // 拡大率 let zoomMin:CGFloat=1.0 let zoomMax:CGFloat=5.0 override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor=UIColor.whiteColor() // スクロールビュー baseScrollView=UIScrollView(frame: CGRectMake((self.view.frame.size.width-viewWidth)/2,(self.view.frame.size.height-viewHeight)/2,viewWidth,viewHeight)) baseScrollView!.backgroundColor=UIColor.blackColor() baseScrollView!.decelerationRate=UIScrollViewDecelerationRateNormal baseScrollView!.minimumZoomScale=zoomMin baseScrollView!.maximumZoomScale=zoomMax baseScrollView!.tag=baseScrollViewTag baseScrollView!.delegate=self self.view.addSubview(baseScrollView!) // 適当にコンテンツビュー作る myView=UIView(frame: CGRectMake(0,0,viewWidth,viewHeight)) baseScrollView!.addSubview(myView!) var imageview:UIImageView=UIImageView(frame: CGRectMake(0,0,viewWidth,viewHeight)) imageview.image=UIImage(named: "test.png") myView!.addSubview(imageview) let subviewColor:Array<UIColor>=[UIColor.redColor(),UIColor.yellowColor(),UIColor.greenColor(),UIColor.blueColor()] let subviewMax:Int=subviewColor.count let subviewWidth:CGFloat=viewWidth/CGFloat(subviewMax) let subviewHeight:CGFloat=viewHeight/CGFloat(subviewMax) for var i=0 ; i < subviewMax ; i++ { var subview:UIView=UIView(frame: CGRectMake(subviewWidth*CGFloat(i),subviewHeight*CGFloat(i),subviewWidth,subviewHeight)) subview.backgroundColor=subviewColor[i] myView!.addSubview(subview) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { if scrollView.tag == baseScrollViewTag { return myView! }else{ return nil } } }
そして以下が実際に採用した、UIScrollViewDelegateを使わないtransformで拡大縮小するパターン。
UIPinchGestureRecognizerでピンチジェスチャーを登録している。
コードは長くなるがUIViewの拡大時に複雑な処理が必要なら向いてる気がする。
import UIKit class ViewController: UIViewController, UIGestureRecognizerDelegate { // view var baseScrollView:UIScrollView?=nil var myView:UIView?=nil // viewのサイズ let viewWidth:CGFloat=300 let viewHeight:CGFloat=300 // 拡大率 var zoomNow:CGFloat=1.0 let zoomMin:CGFloat=1.0 let zoomMax:CGFloat=5.0 override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor=UIColor.whiteColor() // スクロールビュー baseScrollView=UIScrollView(frame: CGRectMake((self.view.frame.size.width-viewWidth)/2,(self.view.frame.size.height-viewHeight)/2,viewWidth,viewHeight)) baseScrollView!.backgroundColor=UIColor.blackColor() baseScrollView!.decelerationRate=UIScrollViewDecelerationRateNormal self.view.addSubview(baseScrollView!) // 適当にコンテンツビュー作る myView=UIView(frame: CGRectMake(0,0,viewWidth,viewHeight)) baseScrollView!.addSubview(myView!) var imageview:UIImageView=UIImageView(frame: CGRectMake(0,0,viewWidth,viewHeight)) imageview.image=UIImage(named: "test.png") myView!.addSubview(imageview) let subviewColor:Array<UIColor>=[UIColor.redColor(),UIColor.yellowColor(),UIColor.greenColor(),UIColor.blueColor()] let subviewMax:Int=subviewColor.count let subviewWidth:CGFloat=viewWidth/CGFloat(subviewMax) let subviewHeight:CGFloat=viewHeight/CGFloat(subviewMax) for var i=0 ; i < subviewMax ; i++ { var subview:UIView=UIView(frame: CGRectMake(subviewWidth*CGFloat(i),subviewHeight*CGFloat(i),subviewWidth,subviewHeight)) subview.backgroundColor=subviewColor[i] myView!.addSubview(subview) } // コンテンツビューにピンチジェスチャー登録 let pinchGesture:UIPinchGestureRecognizer=UIPinchGestureRecognizer(target:self, action: "viewPinch:") pinchGesture.delegate=self myView!.addGestureRecognizer(pinchGesture) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // ピンチジェスチャー func viewPinch(sender:UIPinchGestureRecognizer){ // 拡大率を適当に決める zoomNow += (sender.scale-1)*0.5 if zoomNow > zoomMax { zoomNow=zoomMax }else if zoomNow < zoomMin { zoomNow=zoomMin } // ピンチ中心座標 var location:CGPoint=sender.locationInView(baseScrollView!) // 拡大処理 self.viewZoom(zoomNow, ox:location.x, oy:location.y) } // 拡大処理 func viewZoom(var z:CGFloat, ox:CGFloat, oy:CGFloat){ if z <= 1 { baseScrollView!.contentSize=CGSizeMake(viewWidth,viewHeight) myView!.transform=CGAffineTransformIdentity myView!.frame.origin.x=0 myView!.frame.origin.y=0 baseScrollView!.contentOffset.x=0 baseScrollView!.contentOffset.y=0 }else{ // 拡大前サイズ保存 let prev_w:CGFloat=myView!.frame.size.width let prev_h:CGFloat=myView!.frame.size.height // 拡大(座標と一緒にやるのどっかで見た気がするのに忘れた) myView!.transform=CGAffineTransformMakeScale(CGFloat(z), CGFloat(z)) myView!.frame.origin.x=0 myView!.frame.origin.y=0 // 拡大後のサイズ let zoom_w:CGFloat=myView!.frame.size.width let zoom_h:CGFloat=myView!.frame.size.height baseScrollView!.contentSize=CGSizeMake(zoom_w,zoom_h) // スクロールx座標計算 let base_ox:CGFloat=ox-baseScrollView!.contentOffset.x var zoom_x:CGFloat=(ox*zoom_w/prev_w)-base_ox if zoom_x < 0 { zoom_x=0 }else if (zoom_w-zoom_x) < viewWidth { zoom_x=zoom_w-viewWidth } // スクロールy座標計算 let base_oy:CGFloat=oy-baseScrollView!.contentOffset.y var zoom_y:CGFloat=(oy*zoom_h/prev_h)-base_oy if zoom_y < 0 { zoom_y=0 }else if (zoom_h-zoom_y) < viewHeight { zoom_y=zoom_h-viewHeight } //スクロール位置 baseScrollView!.contentOffset.x=CGFloat(zoom_x) baseScrollView!.contentOffset.y=CGFloat(zoom_y) } } }
どこかでtransformのナイスなexample読んだのに見つけられない…。
dispatch_async(dispatch_get_main_queue(),{ ... })とか絡んでくると取得できる座標とサイズが違うと思うので要注意。
↑のせいで実際に作ったアプリとは計算式が全然違って、復習にならない。
この感覚は、javascriptの「display:none」が原因のバグとすごく似ている。
RELATION ARTICLE関連記事. 業務日誌
気づけば…
気づけば2年間もブログを更新していない…。
というか、自社サイトの存在自体を忘れていました。
Webの…
0
観光業におけるVR活用・動向調査
・・・という名目で、
お取引企業様へのごあいさつも兼ね、遊びに行ってきました。
相変わらずのデカさ。
…
0
フレーバー枝豆「EDAMAMY(エダマミ…
北海道清水町で「むらせ農場」を営む村瀬さんが、味付きフレーバー枝豆「EDAMAMY(エダマミー)」を商品化しました。
…
0
静的HTML(+JS)だけで共通ソースを…
perlやphp、SSIも使えないサーバで編み出したローテクノロジーの結晶。
※<iframe>も使用
…
0
RELATION ARTICLE関連記事. 高瀬真悟
静的HTML(+JS)だけで共通ソースを…
perlやphp、SSIも使えないサーバで編み出したローテクノロジーの結晶。
※<iframe>も使用
…
0
マイナンバーと「法人番号システムWeb-…
法人番号システムWeb-APIについて考える。
公表される法人番号は誰でも利用できるのが特徴で、Web-APIも用…
0
Swiftで子クラスからコールバックの勉…
Swiftでコールバックたくさん使うので勉強。
こんな書き方で正しいのだろうか。
//ViewControlle…
2
androidアプリで回転後のViewサ…
Google先生に尋ねてもピッタリの方法が見つからなかったのだが、皆さんどうしてるんだろう?AsyncTask使ってなん…
3