web-dev-qa-db-ja.com

UIScrollViewでUIButtonのタッチが遅れる

アプリで小さな問題が発生しています。

基本的には、nibの一部であるUIButtonsのサブビューとして追加された一連のUIScrollViewがあります。ボタンをタップするたびに、ボタンが強調表示されるまでにかなりの遅延があります。ボタンが暗くなり、選択されたように見える前に、私は基本的にそれを約0.5秒間保持する必要があります。

これは、UIScrollViewがタッチがスクロールであるのか、それともサブビュー用のタッチであるのかを判別する必要があるためだと思います。

とにかく、どうすればいいか分からない。ボタンをタップするとすぐに、ボタンが選択された状態で表示されるようにするだけです。

どんな助けでもありがたいです!

編集:

私はdelaysContentTouches[〜#〜] no [〜#〜]に設定しようとしましたが、スクロールのほとんどが不可能になります私のscrollViewはUIButtonsで埋められています。

50
Jeff

UIScrollViewをサブクラス化してtouchesShouldCancelInContentViewをオーバーライドすることで解決しました

これで、99とタグ付けされたUIButtonが正しくハイライト表示され、スクロールビューがスクロールします。

myCustomScrollView.h

@interface myCustomScrollView : UIScrollView  {

}

@end

およびmyCustomScrollView.m

@implementation myCustomScrollView

    - (BOOL)touchesShouldCancelInContentView:(UIView *)view
    {
        NSLog(@"touchesShouldCancelInContentView");

        if (view.tag == 99)
            return NO;
        else 
            return YES;
    }
41
Jeff

ジェフの解決策は私にはうまく機能しませんでしたが、これと同じような解決策は機能します: http://charlesharley.com/2013/programming/uibutton-in-uitableviewcell-has-no-highlight-state

スクロールビューサブクラスでtouchesShouldCancelInContentViewをオーバーライドすることに加えて、delaysContentTouchesfalseに設定する必要があります。最後に、ボタンに対してtrueではなくfalseを返す必要があります。上記のリンクからの変更例を次に示します。コメンターが示唆したように、この動作はすべてのタイプのコントロールに適用されるように、特にUIControlではなくUIButtonのサブクラスをチェックします。

Objective-C:

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.delaysContentTouches = false;
    }

    return self;
}

- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
    if ([view isKindOfClass:UIControl.class]) {
        return true;
    }

    return [super touchesShouldCancelInContentView:view];
}

Swift 4:

override func touchesShouldCancel(in view: UIView) -> Bool {
    if view is UIControl {
        return true
    }
    return super.touchesShouldCancel(in: view)
}
50
jlong64

UIScrollView delaysContentTouchesプロパティをNOに設定してみてください。

26
Vladimir

Swift 3:

import UIKit

class ScrollViewWithButtons: UIScrollView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        myInit()
    }

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

    private func myInit() {
        self.delaysContentTouches = false
    }

    override func touchesShouldCancel(in view: UIView) -> Bool {
        if view is UIButton {
            return true
        }
        return super.touchesShouldCancel(in: view)
    }
}

その後、このScrollViewWithButtonsをIBまたはコードで使用できます。

1
Simon Reggiani

ストーリーボードソリューション:スクロールビューを選択し、[属性インスペクター]を開いて[コンテンツタッチの遅延]チェックボックスをオフにします

enter image description here

1
José

既存の解決策はどれも私にとってうまくいきませんでした。多分私の状況はもっと独特です。

UIButtons内に多くのUIScrollViewがあります。 UIButtonを押すと、新しいUIViewControllerがユーザーに表示されます。ボタンが長押しされると、ボタンは押された状態を示します。急にタップしても落ち込んでいる状態が表示されないとクライアントから不満が出ていました。

私の解決策:UIButtons 'タップメソッド内で、新しいUIViewControllerを読み込んで画面に表示するために、

[self performSelector:@selector(loadNextScreenWithOptions:) 
           withObject:options 
           afterDelay:0.]

これにより、次のイベントループで次のUIViewControllerの読み込みがスケジュールされます。 UIButtonが再描画するための時間を確保してください。 UIButtonは、次のUIViewControllerをロードする前に、押し下げられた状態を示します。

0
Brad Goss

スウィフト3:

scrollView.delaysContentTouches = false
0