質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

Swiftのカスタムボタンついてお願いします。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,246

A-B-fly_man

score 25

わかりやすいのでこれ使うことにします。

前提・実現したいこと

Swiftの座標取得ができないです...から作ってみたものが
① UIViewController上に移動できるボタンを作る。
② ①を3回繰り返し3個の移動できるボタンを作る。(作ったボタンを仮に A B C とします。)
③ A はドラッグできますが、 B C をドラッグしようしても何故か A が反応し、そのまま移動する。( B 、 C は無反応です。)

なので、 A B C がそれぞれ動くようにしたいです。

該当のソースコード

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

        for touch: AnyObject in touches {
            // 座標取得
            var point = touch.locationInView(self.view)
        print(point)

        }

        // タッチイベントを取得
        let touchEvent1 = touches.first!
        let touchEvent2 = touches.first!
        let touchEvent3 = touches.first!

        let tag1 = touchEvent1.view?.tag
        let tag2 = touchEvent2.view?.tag
        let tag3 = touchEvent3.view?.tag

        if tag1 == 999 {moveView1(touchEvent1, vi1: TAO01)

        }else if tag2 == 999{moveView2(touchEvent2, vi2: TAO02)
        }else if tag3 == 999{moveView3(touchEvent3, vi3: TAO03)}
    }

   func  moveView1<T1: UIView>(touchEvent1: UITouch, vi1: T1) {
        // ドラッグ前の座標
        let preDx1 = touchEvent1.previousLocationInView(self.view).x
        let preDy1 = touchEvent1.previousLocationInView(self.view).y

        // ドラッグ後の座標
        let newDx1 = touchEvent1.locationInView(self.view).x
        let newDy1 = touchEvent1.locationInView(self.view).y

        // ドラッグしたx座標の移動距離
        let dx1 = newDx1 - preDx1

        // ドラッグしたy座標の移動距離
        let dy1 = newDy1 - preDy1

        // 画像のフレーム
        var viewFrame1: CGRect = vi1.frame

        // 移動分を反映させる
        viewFrame1.origin.x += dx1
        viewFrame1.origin.y += dy1
        vi1.frame = viewFrame1
    }

    func  moveView2<T2: UIView>(touchEvent2: UITouch, vi2: T2) {
        // ドラッグ前の座標
        let preDx2 = touchEvent2.previousLocationInView(self.view).x
        let preDy2 = touchEvent2.previousLocationInView(self.view).y

        // ドラッグ後の座標
        let newDx2 = touchEvent2.locationInView(self.view).x
        let newDy2 = touchEvent2.locationInView(self.view).y

        // ドラッグしたx座標の移動距離
        let dx2 = newDx2 - preDx2

        // ドラッグしたy座標の移動距離
        let dy2 = newDy2 - preDy2

        // 画像のフレーム
        var viewFrame2: CGRect = vi2.frame

        // 移動分を反映させる
        viewFrame2.origin.x += dx2
        viewFrame2.origin.y += dy2
        vi2.frame = viewFrame2
    }

    func  moveView3<T3: UIView>(touchEvent3: UITouch, vi3: T3) {
        // ドラッグ前の座標
        let preDx3 = touchEvent3.previousLocationInView(self.view).x
        let preDy3 = touchEvent3.previousLocationInView(self.view).y

        // ドラッグ後の座標
        let newDx3 = touchEvent3.locationInView(self.view).x
        let newDy3 = touchEvent3.locationInView(self.view).y

        // ドラッグしたx座標の移動距離
        let dx3 = newDx3 - preDx3

        // ドラッグしたy座標の移動距離
        let dy3 = newDy3 - preDy3

        // 画像のフレーム
        var viewFrame3: CGRect = vi3.frame

        // 移動分を反映させる
        viewFrame3.origin.x += dx3
        viewFrame3.origin.y += dy3
        vi3.frame = viewFrame3
    }

    class CustomButton1: UIButton {
        var vc1: UIViewController!
        var isMoveing1: Bool = false

        override func touchesMoved(touches1: Set<UITouch>, withEvent event1: UIEvent?) {
            super.touchesMoved(touches1, withEvent: event1)
            isMoveing1 = true
            vc1.touchesMoved(touches1, withEvent: event1)}

        override func touchesEnded(touches1: Set<UITouch>, withEvent event1: UIEvent?) {
            super.touchesEnded(touches1, withEvent: event1)
            self.superview!.touchesEnded(touches1, withEvent: event1)

            super.touchesEnded(touches1, withEvent: event1)
            isMoveing1 = false
            vc1.touchesEnded(touches1, withEvent: event1)
        }}

    class CustomButton2: UIButton {
        var vc2: UIViewController!
        var isMoveing2: Bool = false

        override func touchesMoved(touches1: Set<UITouch>, withEvent event1: UIEvent?) {
            super.touchesMoved(touches1, withEvent: event1)
            isMoveing2 = true
            vc2.touchesMoved(touches1, withEvent: event1)}

        override func touchesEnded(touches2: Set<UITouch>, withEvent event2: UIEvent?) {
            super.touchesEnded(touches2, withEvent: event2)
            self.superview!.touchesEnded(touches2, withEvent: event2)

            super.touchesEnded(touches2, withEvent: event2)
            isMoveing2 = false
            vc2.touchesEnded(touches2, withEvent: event2)
        }}

    class CustomButton3: UIButton {
        var vc3: UIViewController!
        var isMoveing3: Bool = false

        override func touchesMoved(touches3: Set<UITouch>, withEvent event3: UIEvent?) {
            super.touchesMoved(touches3, withEvent: event3)
            isMoveing3 = true
            vc3.touchesMoved(touches3, withEvent: event3)}

        override func touchesEnded(touches3: Set<UITouch>, withEvent event3: UIEvent?) {
            super.touchesEnded(touches3, withEvent: event3)
            self.superview!.touchesEnded(touches3, withEvent: event3)

            super.touchesEnded(touches3, withEvent: event3)
            isMoveing3 = false
            vc3.touchesEnded(touches3, withEvent: event3)
        }}

TAO1、TAO2、TAO3を作るコードは⬆︎が記述されているコードより下の方にあります。コピペなので省きます。

試したこと

作る分だけ関数を増やしてみたり、単数個しかないものはとりあえず複数個作ってみました。それでも結局 A しか動きませんでした。

補足情報(言語/FW/ツール等のバージョンなど)

できれば配列に格納できればいいのですが、var TAO01 = CustomButton1(type: .Custom)を普通に格納してみようとしましたができませんでした。できるならばお願い致します。

ということなのですがわかる方はご教授お願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

Stripeさんのアドバイスの通り、UIButtonのサブクラスの中で移動処理を行う様に書きなおしてみました。
お試しください。

こちらをベースにしたほうが使い回しがきくと思います。

import UIKit

class ViewController: UIViewController {

    let button1 = CustomButton(type: .Custom)
    let button2 = CustomButton(type: .Custom)

    override func viewDidLoad() {
        super.viewDidLoad()

        // ボタン1を生成
        button1.frame = CGRectMake(100, 100, 200, 50)
        button1.setTitle("Button1", forState: .Normal)
        button1.setTitleColor(UIColor.blueColor(), forState: .Normal)
        button1.backgroundColor = UIColor.yellowColor()
        button1.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), forControlEvents: .TouchUpInside)
        button1.userInteractionEnabled = true
        button1.tag = 1
        view.addSubview(button1)

        // ボタン2を生成
        button2.frame = CGRectMake(100, 200, 200, 50)
        button2.setTitle("Button2", forState: .Normal)
        button2.setTitleColor(UIColor.blueColor(), forState: .Normal)
        button2.backgroundColor = UIColor.greenColor()
        button2.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), forControlEvents: .TouchUpInside)
        button2.userInteractionEnabled = true
        button2.tag = 2
        view.addSubview(button2)
    }

    func buttonPressed(sender: UIButton) {
        if !button1.isMoveing && sender.tag == 1 {
            // ボタン1押下時のイベント
            print("Push! Button1")
        }

        if !button2.isMoveing && sender.tag == 2 {
            // ボタン2押下時のイベント
            print("Push! Button2")
        }
    }
}


// CustomButton Class
class CustomButton: UIButton {

    var isMoveing: Bool = false
    var position: CGPoint!

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesBegan(touches, withEvent: event)
        position = self.frame.origin
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesMoved(touches, withEvent: event)

        isMoveing = true

        let touchEvent = touches.first!

        // ドラッグ前の座標
        let preDx = touchEvent.previousLocationInView(superview).x
        let preDy = touchEvent.previousLocationInView(superview).y

        // ドラッグ後の座標
        let newDx = touchEvent.locationInView(superview).x
        let newDy = touchEvent.locationInView(superview).y

        // ドラッグしたx座標の移動距離
        let dx = newDx - preDx

        // ドラッグしたy座標の移動距離
        let dy = newDy - preDy

        // 画像のフレーム
        var viewFrame: CGRect = self.frame

        // 移動分を反映させる
        viewFrame.origin.x += dx
        viewFrame.origin.y += dy
        self.frame = viewFrame
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesEnded(touches, withEvent: event)
        isMoveing = false
        if position == self.frame.origin {
            self.sendActionsForControlEvents(.TouchUpInside)
        }
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/22 16:27

    毎回ありがとうございます。助かります!
    試してみたところUIButton自体を増やす方法も簡単だったためわかりやすかったです。
    何日も困っていたのですごく助かりました。本当にありがとうございました!

    キャンセル

0

ViewController内のtouchesMoved()で、touchEvent1 touchEvent2 touchEvent3は全く同じ値です。
だから、tag1 tag2 tag3も全く同じ値になります。
そのため、if文の中のmoveView2(touchEvent2, vi2: TAO02)moveView3(touchEvent3, vi3: TAO03)は絶対に実行されません。

そもそも、UIButtonをサブクラス化しているなら、ボタンの移動処理をその中で完結できます。ViewControllerに処理を委ねる必要はありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/22 16:25

    コメントありがとうございます。
    助かりました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る