У меня есть вопрос, касающийся UIButton и его хитовой области. Я использую кнопку Info Dark в конструкторе интерфейсов, но обнаружил, что область попадания недостаточно велика для пальцев некоторых людей.
Есть ли способ увеличить область нажатия кнопки программно или в Интерфейсном Разработчике без изменения размера графики InfoButton?
ios
cocoa-touch
uibutton
uikit
Кевин Бомберри
источник
источник
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Ответы:
Поскольку я использую фоновое изображение, ни одно из этих решений не помогло мне. Вот решение, которое делает некоторую забавную магию target-c и предлагает решение с минимальным кодом.
Сначала добавьте категорию,
UIButton
которая переопределяет тест на попадание, а также добавляет свойство для расширения рамки теста на попадание.UIButton + Extensions.h
UIButton + Extensions.m
Как только этот класс будет добавлен, все, что вам нужно сделать, это установить края вставки вашей кнопки. Обратите внимание, что я решил добавить вставки, поэтому, если вы хотите увеличить область попадания, вы должны использовать отрицательные числа.
Примечание: не забудьте импортировать категорию (
#import "UIButton+Extensions.h"
) в ваших классах.источник
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
и просто установить нужную ширину и высоту: `backButton.frame = CGRectMake (5, 28, 45, 30);`Просто установите значения вставки края изображения в конструкторе интерфейса.
источник
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Вот элегантное решение с использованием расширений в Swift. Это дает всем UIB-кнопкам область попадания, по крайней мере, 44x44 точки, в соответствии с Руководством Apple по человеческому интерфейсу ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Свифт 2:
Свифт 3:
источник
Вы также можете
UIButton
создать подкласс или пользовательскийUIView
и переопределитьpoint(inside:with:)
что-то вроде:Swift 3
Objective-C
источник
Вот Чейз UIButton + Расширения в Swift 3.0.
Чтобы использовать его, вы можете:
источник
UIControl
, а неUIButton
.pTouchAreaEdgeInsets
должна бытьInt
, а неUIEdgeInsets
. (На самом деле, это может быть любой тип, но онInt
является наиболее общим и простым типом, поэтому он часто встречается в такой конструкции). (Поэтому я люблю этот подход в целом. Спасибо, dcRay!)Я рекомендую разместить UIButton с типом Custom по центру над вашей информационной кнопкой. Измените размер пользовательской кнопки до размера, который вы хотите, чтобы область попадания была. Оттуда у вас есть два варианта:
Установите флажок «Показать касание при выделении» пользовательской кнопки. Белое свечение появится над информационной кнопкой, но в большинстве случаев это будет скрыто пальцем пользователя, и все, что они увидят, это свечение вокруг снаружи.
Установите IBOutlet для информационной кнопки и два IBActions для пользовательской кнопки, одну для «Touch Down» и одну для «Touch Up Inside». Затем в XCode сделайте событие приземления, установите выделенное свойство кнопки информации в YES, и событие touchupinside установите выделенное свойство в НЕТ.
источник
Не устанавливайте
backgroundImage
свойство с вашим изображением, установитеimageView
свойство. Также убедитесь, что выimageView.contentMode
установили наUIViewContentModeCenter
.источник
imageView.contentMode
Может быть установленUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Мое решение на Swift 3:
источник
В представленных ответах нет ничего плохого; однако я хотел бы расширить ответ jlarjlar, поскольку он обладает удивительным потенциалом, который может добавить ценность к той же проблеме с другими элементами управления (например, SearchBar). Это связано с тем, что поскольку pointInside подключен к UIView, можно создать подкласс любого элемента управления. для улучшения области касания. Этот ответ также показывает полный пример того, как реализовать полное решение.
Создайте новый подкласс для вашей кнопки (или любого элемента управления)
Затем переопределите метод pointInside в вашей реализации подкласса
В файле раскадровки / xib выберите нужный элемент управления, откройте инспектор идентификации и введите имя своего пользовательского класса.
В вашем классе UIViewController для сцены, содержащей кнопку, измените тип класса для кнопки на имя вашего подкласса.
Свяжите свою раскадровку / кнопку xib со свойством IBOutlet, и ваша область касания будет расширена, чтобы соответствовать области, определенной в подклассе.
В дополнение к переопределению метода pointInside вместе с методами CGRectInset и CGRectContainsPoint , необходимо потратить время на изучение CGGeometry для расширения прямоугольной области касания любого подкласса UIView. Вы также можете найти несколько полезных советов по применению CGGeometry на NSHipster. .
Например, можно сделать область касания нерегулярной, используя методы, упомянутые выше, или просто сделать так, чтобы область касания шириной была в два раза больше горизонтальной области касания:
Примечание: замена любого элемента управления класса UI должна давать аналогичные результаты при расширении сенсорной области для различных элементов управления (или любого подкласса UIView, такого как UIImageView и т. Д.).
источник
Это работает для меня:
источник
Не меняйте поведение UIButton.
источник
Я использую более общий подход к Swizzling
-[UIView pointInside:withEvent:]
. Это позволяет мне модифицировать поведение тестирования на попадание на любомUIView
, а не толькоUIButton
.Часто внутри контейнера отображается кнопка, которая также ограничивает проверку попадания. Например, когда кнопка находится в верхней части представления контейнера и вы хотите расширить цель касания вверх, вам также необходимо расширить цель касания представления контейнера.
Хорошая вещь в этом подходе заключается в том, что вы можете использовать его даже в раскадровках, добавив определяемый пользователем атрибут времени выполнения. К сожалению,
UIEdgeInsets
не доступны непосредственно в качестве типа там , но такCGRect
же состоит из структуры с четырьмяCGFloat
работает безупречно, выбрав «Rect» и заполнение значений , как это:{{top, left}, {bottom, right}}
.источник
Я использую следующий класс в Swift, чтобы также включить свойство Interface Builder для настройки поля:
источник
Ну, вы можете поместить вашу UIButton внутри прозрачного и немного большего UIView, а затем перехватить сенсорные события в экземпляре UIView, как в UIButton. Таким образом, у вас все еще будет кнопка, но с большей сенсорной областью. Вам придется вручную работать с выбранными и выделенными состояниями с помощью кнопки, если пользователь нажимает на вид вместо кнопки.
Другая возможность предполагает использование UIImage вместо UIButton.
источник
Я смог увеличить область попадания кнопки информации программно. Рисунок «i» не меняет масштаб и остается в центре новой рамки кнопки.
Кажется, размер кнопки информации в Интерфейсном Разработчике установлен на 18x19 [*]. Подключив его к IBOutlet, я смог без проблем изменить размер кадра в коде.
[*]: Более поздние версии iOS, похоже, увеличили область нажатия кнопки информации.
источник
Это мое решение Swift 3 (на основе этого поста в блоге: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
источник
Пользовательский тест попадания Чейза реализован как подкласс UIButton. Написано в Objective-C.
Кажется, работает как для, так
init
и дляbuttonWithType:
конструкторов. Для моих нужд это идеально, но поскольку подклассыUIButton
могут быть волосатыми, мне было бы интересно узнать, есть ли у кого-то в этом ошибка.CustomeHitAreaButton.h
CustomHitAreaButton.m
источник
Реализация через переопределение наследуется UIButton.
Swift 2.2 :
источник
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
источник
Никогда не переопределять метод в категории. Кнопка подкласса и переопределение
- pointInside:withEvent:
. Например, если сторона вашей кнопки меньше 44 пикселей (что рекомендуется в качестве минимальной площади нажатия), используйте это:источник
Я сделал библиотеку для этой цели.
Вы можете использовать
UIView
категорию без подклассов :Или вы можете создать подкласс UIView или UIButton и установить
minimumHitTestWidth
и / илиminimumHitTestHeight
. Ваша область проверки нажатия кнопки будет представлена этими двумя значениями.Как и другие решения, он использует
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
метод. Метод вызывается, когда iOS выполняет тестирование нажатия. В этом посте есть хорошее описание того, как работает iOS-тестирование.https://github.com/kgaidis/KGHitTestingViews
Вы также можете просто создать подкласс и использовать Interface Builder без написания какого-либо кода:
источник
Основываясь на ответе giaset выше (который я нашел самое элегантное решение), вот версия swift 3:
источник
Это просто так:
Вот и все.
источник
Я использую этот трюк для кнопки внутри tableviewcell.accessoryView, чтобы увеличить ее область касания
источник
Я только что сделал порт решения @Chase в Swift 2.2
вы можете использовать как это
Для любой другой ссылки см. Https://stackoverflow.com/a/13067285/1728552
источник
@ Антуан ответ отформатирован для Swift 4
источник
Я следил за ответом Чейза, и он прекрасно работает, единственная проблема, когда вы создаете слишком большую область, большую, чем зона, в которой кнопка отменяется (если зона не была больше), она не вызывает селектор для события UIControlEventTouchUpInside ,
Я думаю, что размер более 200 в любом направлении или что-то в этом роде.
источник
Я так опаздываю к этой игре, но хотел взвесить простую технику, которая может решить ваши проблемы. Вот типичный программный фрагмент UIButton для меня:
Я загружаю прозрачное изображение PNG для своей кнопки и устанавливаю фоновое изображение. Я устанавливаю кадр на основе UIImage и масштабирую на 50% для сетчатки. Хорошо, может быть, вы согласны с вышеизложенным или нет, НО, если вы хотите сделать область удара БОЛЬШЕ и избавить себя от головной боли:
Что я делаю, открываю изображение в фотошопе и просто увеличиваю размер холста до 120% и сохраняю. Фактически вы только что увеличили изображение с помощью прозрачных пикселей.
Всего один подход.
источник
Ответ @jlajlar выше казался хорошим и прямым, но не соответствует Xamarin.iOS, поэтому я перевел его на Xamarin. Если вы ищете решение для iOS Xamarin, вот оно:
Вы можете добавить этот метод в класс, где вы переопределяете UIView или UIImageView. Это сработало
источник
Ни один из ответов не работает идеально для меня, потому что я использую фоновое изображение и заголовок на этой кнопке. Кроме того, размер кнопки будет изменяться при изменении размера экрана.
Вместо этого я увеличиваю область крана, увеличивая прозрачную область png.
источник