ホーム

scrollViewの上に置いてあるUIViewをロングプレスで操作するときに詰まった

環境

  • xcode
  • xcode9
  • swift
  • swift3
  • scrollView
  • longpress
  • ロングプレス

scrollViewの上に置いてあるUIViewをロングプレスで操作するとき詰まりました。二日間も詰まりました。痛恨の極みです。最近、本当にこういうのはよくないと思いました。遅い。遅すぎる。遅いよりは早い方がいい。15分わからなかったら相談する。これを自分の仕事に対する行動指針にする。

やりたいこと

  • スーパービューのscrollViewを追加する。
  • scrollViewにUIViewを追加する
  • UIViewをロングプレスする
  • 現在ロングプレスしてある位置にUIViewの中心を持ってくる
  • ロングプレスを動かす度にそれに合わせてUIViewの中心も移動する

うまくいった実行

うまくいった実行動画
on.gif

うまくいった実装

//
//  ViewController.swift
//  LongPressTutolial
//
//  Created by ryosuke-hujisawa on 2017/10/31.
//  Copyright © 2017年 ryosuke-hujisawa. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    var tapLocation: CGPoint = CGPoint()
    let SubView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: 250, height: 250))
    let scrollView = UIScrollView()

    override func viewDidLoad() {
        super.viewDidLoad()

        scrollView.backgroundColor = UIColor.gray
        scrollView.frame = CGRect(x: 0, y: self.view.frame.height/2, width: self.view.frame.width, height: self.view.frame.height/2)
        scrollView.contentSize = CGSize(width: 1000, height: 600)
        scrollView.bounces = false
        scrollView.delegate = self
        scrollView.clipsToBounds = false
        self.view.addSubview(scrollView)

        let bgColor = UIColor.blue
        SubView.backgroundColor = bgColor
        self.scrollView.addSubview(SubView)
        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.longPressed(_:)))
        self.SubView.addGestureRecognizer(longPressRecognizer)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @objc func longPressed(_ sender: UILongPressGestureRecognizer)
    {
        print("longpressed")
        tapLocation = sender.location(in: self.scrollView)
        SubView.center = tapLocation
    }
}

うまくいかなかった実行

on.gif

うまくいかなかった実装

//
//  ViewController.swift
//  ImageRotatedSwift3
//
//  Created by ryosuke-hujisawa on 2017/10/30.
//  Copyright © 2017年 ryosuke-hujisawa. All rights reserved.
//

import UIKit

var tapLocation: CGPoint = CGPoint()

class ViewController: UIViewController, UIScrollViewDelegate {

    let SubView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: 250, height: 250))
    let scrollView = UIScrollView()
    var tapLocation: CGPoint = CGPoint()

    override func viewDidLoad() {
        super.viewDidLoad()

        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressView(sender:)))
        longPressGesture.minimumPressDuration = 1
        longPressGesture.allowableMovement = 50
        self.SubView.addGestureRecognizer(longPressGesture)
        scrollView.backgroundColor = UIColor.gray
        scrollView.frame = CGRect(x: 0, y: self.view.frame.height/2, width: self.view.frame.width, height: self.view.frame.height/2)
        scrollView.contentSize = CGSize(width: 1000, height: 600)
        scrollView.bounces = false
        scrollView.delegate = self
        let bgColor = UIColor.blue
        SubView.backgroundColor = bgColor
        SubView.isUserInteractionEnabled = true
        scrollView.addSubview(SubView)
        self.view.addSubview(scrollView)
    }

    @objc func longPressView(sender: UILongPressGestureRecognizer) {
        print("Long Press")
        tapLocation = sender.location(in: self.view)
        SubView.center = tapLocation

        }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

なぜ、こんなことになったのか

tapLocation = sender.location(in: self.view)の部分。現在タップしている位置の基準がスーパービューになっている。SubViewの中心を現在ロングプレスしているロケーションの位置に持ってこようとした場合、ロケーションがスーパービューだとおかしくなる。なぜなら、SubViewはスーパービューではなくscrollViewに追加されているからだ。例えば、scrollViewがViewの上(x100y100)の位置に追加されているとして、scrollの一番左を触ったとしたら、現在ロングプレスしているロケーションの位置は(x0,y0)になる。scrollViewの(x0,y0)の位置に追加されているSubViewの一番はじを触った場合、本当であれば、SubViewは(x-50,y-50)の位置にくるはずだが、実際現在選択されているロケーションの位置は(x100y100)なので、SubViewの中心はscrollViewの中の(x100y100)の位置に移動することになった。正しい実装では、self.SubView.addGestureRecognizer(longPressRecognizer)のようにSubViewにロングプレスを追加して、そして、sender.location(in: self.scrollView)のように、現在ロングプレスしている位置をscrollViewを基準にしている。SubViewはscrollViewに追加されているのだから、うまくいく。

Pocket
LinkedIn にシェア

エンジニアにおすすめできる本

Card image cap
リーダブルコード

より良いコードを書くためのシンプルで実践的なテクニック

Card image cap
Webを支える技術

HTTP,URI,HTML,そしてREST

Card image cap
誰でもPythonで作れる

儲かるAIとソフトウェアの作り方

Card image cap
プログラマが知るべき97のこと

現場で使える実践哲学のマスターピース

Card image cap
情熱プログラマー

時代を超えて。ソフトウェア開発者の幸せな生き方

Card image cap
アジャイルサムライ

プログラミング達人開発者への道

Card image cap
Rubyを作った男 まつもとゆきひろ

コードの世界 スーパー・プログラマになる14の思考法

ご提供 sponsor
 

Meee!(ミー)は、ビジネスからプライベート利用まで、個人のスキルを気軽に売り買いできるスキルマーケットです。カテゴリや居住地から、検索することが可能です。

 

ランゲージエクスチェンジは、ネイティブスピーカーと気軽にマッチングできる言語交換プラットフォームです。あなたの地元に住む外国人を探したり、留学や海外移住の前に、現地のネイティブスピーカーと繋がることもできます!

宣伝
 

りょすけトークchは、仕事や私生活をより豊にするYouTubeチャンネルです。文献(本、映画、論文)から役に立つ情報をまとめ、生涯にわたり役に立つ哲学をお届けしています。是非、チャンネル登録してみてね

-ホーム

Copyright© offブログ! , 2021 All Rights Reserved Powered by AFFINGER5.