Eu tenho uma pergunta sobre o UIButton e sua área de ocorrência. Estou usando o botão Info Dark no criador de interface, mas estou descobrindo que a área de ocorrência não é grande o suficiente para os dedos de algumas pessoas.
Existe uma maneira de aumentar a área de acerto de um botão programaticamente ou no Interface Builder sem alterar o tamanho do gráfico do InfoButton?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
fonte
fonte
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Respostas:
Como estou usando uma imagem de plano de fundo, nenhuma dessas soluções funcionou bem para mim. Aqui está uma solução que faz alguma mágica divertida do objetivo-c e oferece uma queda na solução com o mínimo de código.
Primeiro, adicione uma categoria
UIButton
que substitua o teste de acerto e também adicione uma propriedade para expandir o quadro de teste de acerto.UIButton + Extensions.h
UIButton + Extensões.m
Depois que essa classe é adicionada, tudo o que você precisa fazer é definir as bordas do seu botão. Observe que eu escolhi adicionar as inserções; portanto, se você quiser aumentar a área de acerto, use números negativos.
Nota: Lembre-se de importar a categoria (
#import "UIButton+Extensions.h"
) nas suas aulas.fonte
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
E apenas defina a largura e a altura necessárias: `backButton.frame = CGRectMake (5, 28, 45, 30);`Basta definir os valores inseridos na borda da imagem no criador de interface.
fonte
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Aqui está uma solução elegante usando Extensões no Swift. Dá a todos os UIButtons uma área atingida de pelo menos 44x44 pontos, conforme as Diretrizes de interface humana da Apple ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Swift 2:
Swift 3:
fonte
Você também pode
UIButton
criar uma subclasse ou um personalizadoUIView
e substituirpoint(inside:with:)
por algo como:Swift 3
Objetivo-C
fonte
Aqui estão as extensões UIButton + do Chase no Swift 3.0.
Para usá-lo, você pode:
fonte
UIControl
, nãoUIButton
.pTouchAreaEdgeInsets
deve serInt
, nãoUIEdgeInsets
. (Na verdade, pode ser de qualquer tipo, masInt
é o tipo mais genérico e simples, por isso é comum nessa construção). (Por isso eu amo essa abordagem em geral Obrigado, dcRay.!)Eu recomendo colocar um UIButton com o tipo Custom centrado sobre o botão de informações. Redimensione o botão personalizado para o tamanho desejado para a área de ocorrência. A partir daí, você tem duas opções:
Marque a opção "Mostrar toque no destaque" do botão personalizado. O brilho branco aparecerá sobre o botão de informações, mas na maioria dos casos o dedo do usuário cobrirá isso e tudo o que eles verão é o brilho do lado de fora.
Configure um IBOutlet para o botão de informações e duas IBActions para o botão personalizado, um para 'Touch Down' e outro para o 'Touch Up Inside'. Em seguida, no Xcode, faça com que o evento de touchdown defina a propriedade destacada do botão de informações como YES e o evento touchupinside defina a propriedade destacada como NO.
fonte
Não defina a
backgroundImage
propriedade com sua imagem, defina aimageView
propriedade. Além disso, verifique se vocêimageView.contentMode
definiu emUIViewContentModeCenter
.fonte
imageView.contentMode
pode ser definido comoUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Minha solução no Swift 3:
fonte
Não há nada errado com as respostas apresentadas; no entanto, eu queria estender a resposta de jlarjlar, pois possui um potencial incrível que pode agregar valor ao mesmo problema com outros controles (por exemplo, SearchBar). Isso ocorre porque, como pointInside está anexado a um UIView, é possível subclassificar qualquer controle para melhorar a área de toque. Esta resposta também mostra uma amostra completa de como implementar a solução completa.
Crie uma nova subclasse para o seu botão (ou qualquer controle)
Em seguida, substitua o método pointInside em sua implementação de subclasse
No seu arquivo storyboard / xib, selecione o controle em questão e abra o inspetor de identidade e digite o nome da sua classe personalizada.
Na sua classe UIViewController para a cena que contém o botão, altere o tipo de classe do botão para o nome da sua subclasse.
Vincule seu botão storyboard / xib à propriedade IBOutlet e sua área de toque será expandida para caber na área definida na subclasse.
Além de substituir o método pointInside em conjunto com os CGRectInset e CGRectContainsPoint métodos, um deve ter tempo para examinar o CGGeometry para alargar a área de toque rectangular de qualquer subclasse UIView. Você também pode encontrar algumas dicas interessantes sobre casos de uso da CGGeometry no NSHipster .
Por exemplo, pode-se tornar a área de toque irregular usando os métodos mencionados acima ou simplesmente optar por aumentar a área de toque duas vezes maior que a área de toque horizontal:
NB: Substituir qualquer controle de classe de interface do usuário deve produzir resultados semelhantes ao estender a área de toque para diferentes controles (ou qualquer subclasse UIView, como UIImageView, etc.).
fonte
Isso funciona para mim:
fonte
Não mude o comportamento do UIButton.
fonte
Estou usando uma abordagem mais genérica por swizzling
-[UIView pointInside:withEvent:]
. Isso me permite modificar o comportamento do teste de ocorrência em qualquer umUIView
, não apenasUIButton
.Muitas vezes, um botão é colocado dentro de uma exibição de contêiner que também limita o teste de acerto. Por exemplo, quando um botão está na parte superior de uma exibição de contêiner e você deseja estender o alvo de toque para cima, também é necessário estender o alvo de toque da exibição de contêiner.
O bom dessa abordagem é que você pode usá-la mesmo no Storyboards adicionando um Atributo de Tempo de Execução Definido pelo Usuário. Infelizmente,
UIEdgeInsets
não está diretamente disponível como um tipo lá, mas uma vez queCGRect
também é composto por uma estrutura com quatroCGFloat
ele funciona perfeitamente, escolhendo "Rect" e preenchendo os valores como este:{{top, left}, {bottom, right}}
.fonte
Estou usando a seguinte classe no Swift, para também habilitar uma propriedade do Interface Builder para ajustar a margem:
fonte
Bem, você pode colocar seu UIButton dentro de um UIView transparente e um pouco maior e, em seguida, capturar os eventos de toque na instância UIView como no UIButton. Dessa forma, você ainda terá seu botão, mas com uma área de toque maior. Você terá que lidar manualmente com os estados selecionados e destacados com o botão se o usuário tocar na visualização em vez do botão.
Outra possibilidade envolve o uso de um UIImage em vez de um UIButton.
fonte
Consegui aumentar a área de ocorrência do botão de informações programaticamente. O gráfico "i" não altera a escala e permanece centralizado no novo quadro de botão.
O tamanho do botão de informações parece estar fixado em 18x19 [*] no Interface Builder. Ao conectá-lo a um IBOutlet, consegui alterar o tamanho do quadro no código sem problemas.
[*]: As versões posteriores do iOS parecem ter aumentado a área de ocorrência do botão de informações.
fonte
Esta é a minha solução Swift 3 (com base neste post do blog: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
fonte
O teste de acerto personalizado do Chase implementado como uma subclasse de UIButton. Escrito em Objective-C.
Parece funcionar tanto para
init
ebuttonWithType:
construtores. Para minhas necessidades, é perfeito, mas desde a subclassificaçãoUIButton
pode ser complicada, eu estaria interessado em saber se alguém tem alguma falha nisso.CustomeHitAreaButton.h
CustomHitAreaButton.m
fonte
Implementação através da substituição de UIButton herdado.
Swift 2.2 :
fonte
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
fonte
Nunca substitua o método na categoria. Subclasse e substitua
- pointInside:withEvent:
. Por exemplo, se o lado do seu botão for menor que 44 px (recomendado como área de toque mínimo), use o seguinte:fonte
Eu fiz uma biblioteca para esse propósito.
Você pode optar por usar uma
UIView
categoria, sem necessidade de subclassificação :Ou você pode subclassificar seu UIView ou UIButton e definir o
minimumHitTestWidth
e / ouminimumHitTestHeight
. A área de teste de batida do botão será representada por esses 2 valores.Assim como outras soluções, ele usa o
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
método O método é chamado quando o iOS executa o teste de acerto. este postagem do blog tem uma boa descrição de como o teste de impacto do iOS funciona.https://github.com/kgaidis/KGHitTestingViews
Você também pode apenas subclasse e usar o Interface Builder sem escrever nenhum código:
fonte
Baseado na resposta do giaset acima (que achei a solução mais elegante), aqui está a versão rápida 3:
fonte
É simples assim:
Essa é a coisa toda.
fonte
Estou usando este truque para o botão dentro do tableviewcell.accessoryView para aumentar sua área de toque
fonte
Acabei de fazer a porta da solução @Chase no Swift 2.2
e você pode usar assim
Para qualquer outra referência, consulte https://stackoverflow.com/a/13067285/1728552
fonte
Resposta de @ antoine formatada para Swift 4
fonte
Eu segui a resposta do Chase e funciona muito bem, um único problema quando você cria a área muito grande, maior que a zona em que o botão é desmarcado (se a zona não for maior), ele não chama o seletor para o evento UIControlEventTouchUpInside .
Eu acho que o tamanho é superior a 200 em qualquer direção ou algo assim.
fonte
Estou muito atrasado para este jogo, mas queria analisar uma técnica simples que pode resolver seus problemas. Aqui está um trecho UIButton programático típico para mim:
Estou carregando uma imagem png transparente para o meu botão e definindo a imagem de fundo. Estou definindo o quadro com base na UIImage e redimensionando em 50% a retina. OK, talvez você concorde com o exposto acima ou não, mas se você quiser aumentar a área atingida e economizar uma dor de cabeça:
O que faço, abra a imagem no photoshop e simplesmente aumente o tamanho da tela para 120% e economize. Efetivamente, você acabou de aumentar a imagem com pixels transparentes.
Apenas uma abordagem.
fonte
A resposta de @jlajlar acima parecia boa e direta, mas não corresponde ao Xamarin.iOS, então eu o convertei no Xamarin. Se você está procurando uma solução em um Xamarin iOS, aqui está:
Você pode adicionar esse método à classe em que você está substituindo o UIView ou o UIImageView. Isso funcionou muito bem :)
fonte
Nenhuma das respostas funciona perfeita para mim, porque eu uso a imagem de plano de fundo e um título nesse botão. Além disso, o botão será redimensionado conforme o tamanho da tela for alterado.
Em vez disso, amplio a área da torneira aumentando a área transparente do png.
fonte