ti-enxame.com

Toque UIButton está atrasado quando no UIScrollView

Eu estou correndo em um pequeno problema no meu aplicativo. 

Eu essencialmente tenho uma série de UIButtons adicionado como subviews em um UIScrollView que faz parte de um bico. Toda vez que toco em um botão, há um atraso perceptível antes que o botão seja realçado. Eu essencialmente tenho que segurá-lo por cerca de meio segundo antes do botão escurecer e aparecer selecionado.

Eu estou supondo que isso é porque o UIScrollView precisa determinar se o toque é um pergaminho ou se é um toque que se destina a uma subvisualização.

De qualquer forma, estou um pouco inseguro sobre como proceder. Eu simplesmente quero que o botão apareça selecionado assim que eu tocar nele.

Qualquer ajuda é apreciada!

Editar:

Eu tentei definir delaysContentTouches paraNO, mas a rolagem se torna quase impossível, já que a maioria do meu scrollView é preenchida com UIButtons.

47
Jeff

Ok, resolvi isso subclassificando UIScrollView e substituindo touchesShouldCancelInContentView

Agora, minha UIButton que foi marcada como 99 é realçada corretamente e minha rolagem está rolando!

myCustomScrollView.h :

@interface myCustomScrollView : UIScrollView  {

}

@end

e myCustomScrollView.m :

@implementation myCustomScrollView

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

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

A solução de Jeff não estava funcionando bem para mim, mas esta similar faz: http://charlesharley.com/2013/programming/uibutton-in-uitableviewcell-has-no-highlight-state

Além de sobrescrever touchesShouldCancelInContentView em sua subclasse de rolagem, você ainda precisa definir delaysContentTouches como false. Por fim, você precisa retornar true em vez de false para seus botões. Aqui está um exemplo modificado do link acima. Como os comentadores sugeriram, ele verifica qualquer subclasse de UIControl em vez de UIButton especificamente para que esse comportamento se aplique a qualquer tipo de controle.

Objetivo-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)
}
45
jlong64

Tente definir a propriedade UIScrollView delaysContentTouches como NO.

26
Vladimir

Em 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)
    }
}

Você pode então usar este ScrollViewWithButtons no IB ou no código.

1
Simon Reggiani

Solução de storyboard: selecione a visualização de rolagem, abra o "Inspetor de atributos" e desmarque "Atrasa os toques do conteúdo"

 enter image description here

1
José

Nenhuma das soluções existentes funcionou para mim. Talvez minha situação seja mais singular.

Eu tenho muitos UIButtons dentro de um UIScrollView. Quando um UIButton é pressionado, um novo UIViewController é apresentado ao usuário. Se um botão for pressionado e mantido por tempo suficiente, o botão mostrará seu estado deprimido. Meu cliente estava reclamando que se você tocar muito rapidamente, nenhum estado deprimido será mostrado.

Minha solução: Dentro do método de tap UIButtons ', onde eu carrego o novo UIViewController e o apresento na tela, eu uso

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

Isso agenda o carregamento do próximo UIViewController no próximo loop de eventos. Permitindo tempo para o UIButton redesenhar. O UIButton agora mostra seu estado deprimido antes de carregar o próximo UIViewController.

0
Brad Goss

Swift 3:

scrollView.delaysContentTouches = false
0
Oubaida AlQuraan