LoginSignup
7
0

More than 5 years have passed since last update.

UIPageViewControllerにUIButtonを置くと横スクロールできない問題

Last updated at Posted at 2018-10-23

環境

Swift 4
Xcode 10

問題

UIPageViewControllerにUIButtonを置くと横スクロールできない

UIPageViewControllerの横スクロールのイベントがUIButtonに取られちゃって、ボタンの上からスクロールを始めると横スクロールできない。結果、画面に大きめのボタンがあるとすごくスクロールしにくい。

func touchesShouldCancel(in view: UIView) -> Boolでtrueを返せばいいのでは?

func touchesShouldCancel(in view: UIView) -> Bool でtrueを返すと、UIScrollView上にUIButtonをおいてもいい感じになる。(Tapできるし、スクロールしたらTapがキャンセルされてそのままスクロールできる)

touchesShouldCancel(in:) - UIScrollView | Apple Developer Documentation
https://developer.apple.com/documentation/uikit/uiscrollview/1619387-touchesshouldcancel

UIPageViewControllerではできない😂

func touchesShouldCancel(in view: UIView) -> Boolでtrueを返すためにはoverrideしないといけないのだが、UIPageViewControllerの中にあるUIScrollViewってどうやったらoverrideできるの😂

※UIScrollView, UITableView, UICollectionViewはoverrideしたサブクラスを作成することでいい感じにできます👍

解決法

UIButtonをUIPageViewController上で使わない!

func touchesShouldCancel(in view: UIView) -> BoolのDocumentに書いてあるんですが、UIControlを継承しているクラスだとfalseを返して、それ以外だったらtrueを返すらしいんですよ。
なので、UIButtonじゃなくてUIViewにTapイベントとか設定すればいい感じに動く👍

まとめ

Document読もう!

touchesShouldCancel(in:) - UIScrollView | Apple Developer Documentation
https://developer.apple.com/documentation/uikit/uiscrollview/1619387-touchesshouldcancel

おまけ

以前の記事でUIButtonのサブクラスで、Highlight時に白っぽくなるボタンを作ったのですが、それのUIView版のコードを張っておきます。以下のUIViewを使用すれば横スクロールもいい感じ🌟

// タップイベントを処理したい場合は以下のdelegateを使用してください
protocol HighlightViewDelegate: class {
    func didTapHighlightView()
}

/// 以下参照
/// https://developer.apple.com/documentation/uikit/uiscrollview/1619387-touchesshouldcancel
class HighlightView: UIView {

    // MARK: Parameter

    weak var delegate: HighlightViewDelegate?

    private let highlightedAlpha: CGFloat = 0.4
    private lazy var normalBgColor: UIColor = .clear
    private lazy var highlightedBgColor: UIColor = {
        return UIColor.white.withAlphaComponent(CGFloat(1) - self.highlightedAlpha)
    }()

    private var isShowAnimation: Bool = false
    private var isHideAnimation: Bool = false

    private var isHighlighted: Bool = false {
        willSet {
            self.doAnimation(isShow: newValue) {
                self.backgroundColor = newValue ? self.highlightedBgColor : self.normalBgColor
            }
        }
    }

    // MARK: Init

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }

    func commonInit() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(self.didTapSelf))
        self.addGestureRecognizer(tap)
    }

    // MARK: Func

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.isHighlighted = true
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.isHighlighted = false
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.isHighlighted = false
    }

    @objc
    private func didTapSelf() {
        self.delegate?.didTapHighlightView()
    }
}

extension HighlightView {

    private func doAnimation(isShow: Bool, animation: @escaping () -> Void) {
        if isShow {
            if !self.isShowAnimation {
                self.isShowAnimation = true
                UIView.animate(withDuration: 0.1, animations: {
                    animation()
                }, completion: { _ in
                    self.isShowAnimation = false
                })
            }
        } else {
            if !self.isHideAnimation {
                self.isHideAnimation = true
                UIView.animate(withDuration: 0.3, animations: {
                    animation()
                }, completion: { _ in
                    self.isHideAnimation = false
                })
            }
        }
    }
}
7
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0