Задачи UIButton не работают, если UIView добавлен как подвью
У меня есть UIButton
. Он имеет два подхода. Затем я вызываю:
[createButton addTarget:self action:@selector(openComposer) forControlEvents:UIControlEventTouchUpInside];
Если я коснусь частей UIButton
, которые не охвачены, кроме одного из его подзонов, он работает нормально. Однако, если я коснусь одного из подзонов, это не вызывает действие.
В обоих подзонах я имеет .userInteractionEnabled
значение YES
.
Оба подзона равны UIViews
с frame
и backgroundColor
.
Как я могу получить крану "пройти" через UIView
и на UIButton
?
Спасибо
EDIT: Мне нужно использовать UIControlEvents, потому что мне нужен UIControlEventTouchDown.
ИЗМЕНИТЬ 2:
Вот код кнопки.
@interface CreateButton ()
@property (nonatomic) Theme *theme;
@property (nonatomic) UIView *verticle;
@property (nonatomic) UIView *horizontal;
@property (nonatomic) BOOL mini;
@end
@implementation CreateButton
#pragma mark - Accessors
- (UIView *)verticle {
if (! _verticle) {
_verticle = [[UIView alloc] init];
_verticle.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
_verticle.userInteractionEnabled = NO;
}
return _verticle;
}
- (UIView *)horizontal {
if (! _horizontal) {
_horizontal = [[UIView alloc] init];
_horizontal.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
_verticle.userInteractionEnabled = NO;
}
return _horizontal;
}
#pragma mark - Init
- (instancetype)initWithTheme:(Theme *)theme frame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_theme = theme;
self.layer.cornerRadius = roundf(frame.size.width / 2);
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = .1f;
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowRadius = 15.f;
self.backgroundColor = [self.theme colorForKey:@"createButtonBackgroundColor"];
[self addSubview:self.verticle];
[self addSubview:self.horizontal];
[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpOutside];
}
return self;
}
#pragma mark - Actions
- (void)animate {
[UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:8 options:kNilOptions animations:^{
if (self.mini) {
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.mini = NO;
} else {
self.transform = CGAffineTransformMakeScale(0.90, 0.90);
self.mini = YES;
}
} completion:nil];
}
#pragma mark - UIView
- (void)layoutSubviews {
CGSize size = self.bounds.size;
NSInteger width = 3;
NSInteger verticleInset = 12;
self.verticle.frame = CGRectMake((size.width - width) / 2, verticleInset, width, size.height - (verticleInset * 2));
self.horizontal.frame = CGRectMake(verticleInset, (size.height - width) / 2, size.width - (verticleInset * 2), width);
}
@end
Ответы
Ответ 1
Установите userInteractionEnabled
в NO
, чтобы ваши подпункты позволяли касаниям проходить через них и на вашу кнопку.
Также не забудьте изменить _verticle.userInteractionEnabled = NO;
в своем ленивом загрузчике для вашего свойства horizontal
на _horizontal.userInteractionEnabled = NO;
, поскольку я считаю, что опечатка.
Ответ 2
используйте код, как показано ниже (замените "ViewControllerFilterCategory" своим собственным + nibName), чтобы добавить контроллер из nib (дочерний один) в качестве дочернего контроллера текущего контроллера, прежде чем добавлять представление в виде суб-представления. Затем iOS будет вызывать действия, прикрепленные к дочернему контроллеру, как вы ожидаете:
let vcCats = ViewControllerFilterCategory(nibName: "ViewControllerFilterCategory", bundle: Bundle.main);
self.addChildViewController(vcCats);
self.view.addSubview(vcCats.view);
P.S. не забудьте вызвать 'removeFromParentViewController' перед удалением вашего подвидного представления (например, ниже):
@IBAction func onCanceled(_ sender: Any) {
self.removeFromParentViewController()
self.view.removeFromSuperview()
}
Ответ 3
Я столкнулся с этой проблемой.
В моем случае у меня был nib, загруженный как subview.
UIViewController *vc = [[[NSClassFromString(@"nib_controller") alloc] initWithNibName:@"nib_name" bundle:nil] autorelease];
[self.view addSubview:vc.view];
В представлении nib (vc.view) все кнопки не вызывали действие.
[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)btnActions:(id)sender{
// list star buttons for bookmark
NSLog(@"btnActions tag %d", [sender tag]);
// bla bla bla
}
Мне удалось коснуться кнопок, но метод btnActions
не был запущен.
Тогда я просто попробовал что-то очень простое и логичное.
На родительском контроллере представления у меня есть метод с тем же именем:
-(IBAction)btnActions:(id)sender{
// list star buttons for bookmark
NSLog(@"parent btnActions tag %d", [sender tag]);
// bla bla bla
}
Я просто добавил NSLog внутри, чтобы узнать, что произойдет. Результат появился на консоли журнала:
parent btnActions tag xxx
Это было невозможно в версиях iOS, предшествующих 9.
Но теперь его можно получить доступ к методам из родительского представления, если представление загружено из представления контроллера nib.
Для тех, кто все еще запутывается, см. ниже рисунок
родительский → A
ребенок > B
----------
| |
| A |
| |
----------
|
|--- -(IBAction)btnActions:(id)sender
----------
| |
| B |
| |
----------
|
|--- -(IBAction)btnActions:(id)sender (the controller have an method with same name as parent)
B.View добавляется из контроллера A
----------
| |
| A |
| |
----------
|
|--- (touching some button -> execute this:
UIViewController *B = [[[NSClassFromString(@"B_controller") alloc] initWithNibName:@"B_name" bundle:nil] autorelease];
[self.view addSubview:B.view]; // The B.view is added as subview.
Кнопки внутри B.view отправляют действия на -(IBAction)btnActions
Пример
[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];
Все кнопки работают хорошо, потому что все их можно было коснуться или щелкнуть (симулятор xcode). Но метод -(IBAction)btnActions
, объявленный в B.controller
, не вызывался. Я пытался решить это в течение многих часов, пока не понял, что действия отправляются в A.Controller
, как описано выше.
Головная боль здесь в ранних версиях iOS была невозможна.
Я не уверен, но я думаю, что из iOS9 у нас есть это другое поведение.
Приложение работает хорошо до iOS8.