简体   繁体   English

UIButton 在 iOS 7 中无法正常工作

[英]UIButton not working correctly in iOS 7

I have a problem with a UIButton that works perfectly well in iOS6, but fails to respond to touch events in iOS7 up to a certain point.我有一个 UIButton 问题,它在 iOS6 中运行良好,但在某个点上无法响应 iOS7 中的触摸事件。 To clarify please see below image:为了澄清,请参见下图:

ios7_button_issue

The button that fails is the "Discard All" button that is in the UIView.失败的按钮是 UIView 中的“全部放弃”按钮。 (Please note, this button is only disabled temporarily and that is NOT the issue. I just don't have a screenshot of the newest test where the button is enabled") (请注意,此按钮只是暂时禁用,这不是问题。我只是没有启用该按钮的最新测试的屏幕截图”)

This button ignores all touches, unless one first presses the "Discard" or "Retry" buttons in the UITableViewCell.此按钮忽略所有触摸,除非首先按下 UITableViewCell 中的“放弃”或“重试”按钮。 (This does cause a reload of the view controller, which triggers the lifecycle methods like ViewDidLoad to be called again.) After either the "Discard" or "Retry" buttons in the table view cell have been pressed, the "Discard All" button starts functioning correctly. (这确实会导致视图控制器的重新加载,这会触发生命周期方法(如 ViewDidLoad)再次被调用。)按下表视图单元格中的“放弃”或“重试”按钮后,“全部放弃”按钮开始正常运行。

The view and the "Discard All" button are build on the Controller's XIB file and not in code.视图和“全部放弃”按钮建立在控制器的 XIB 文件上,而不是在代码中。 This only fails on iOS7, and starts working as soon as the taleview cell buttons are touched.这仅在 iOS7 上失败,并且在触摸 taleview 单元格按钮后立即开始工作。

Anyone have any ideas?任何人有任何想法?

Thanks!谢谢!

I found the solution last night.我昨晚找到了解决方案。 Okay, so what happens is that I put the above table view and UIView elements onto a target frame.好的,接下来发生的事情是我将上面的 table view 和 UIView 元素放在目标框架上。

I'm not 100% sure, but it seems that in iOS6 the buttons respond to events irrespective of where they are placed.我不是 100% 肯定,但似乎在 iOS6 中,按钮会响应事件,而不管它们放置在哪里。 For some reason in iOS7 when the button sits outside of the frame it is supposed to be in, it ignores touch events, even though it does get displayed.出于某种原因,在 iOS7 中,当按钮位于它应该位于的框架之外时,它会忽略触摸事件,即使它确实被显示了。

I solved the problem by positioning the view's frame in the correct place so it overlays the button.我通过将视图的框架定位在正确的位置来解决这个问题,因此它覆盖了按钮。

If I can find any documentation around this, I will post here.如果我能找到有关此的任何文档,我会在这里发布。

Thanks!谢谢!

I have just faced to this problem.我刚刚面临这个问题。 According to @Guntis Treulands advice, I decided to check what happens if I override hitTest:withEvent: method in my custom header view.根据@Guntis Treulands 的建议,我决定检查如果在自定义标题视图中覆盖hitTest:withEvent:方法会发生什么。 This method ignores view objects that are hidden, that have disabled user interactions, or have an alpha level less than 0.01.此方法会忽略隐藏的、已禁用用户交互或 alpha 级别小于 0.01 的视图对象。 This method does not take the view's content into account when determining a hit.此方法在确定命中时不考虑视图的内容。 Thus, a view can still be returned even if the specified point is in a transparent portion of that view's content and now, after it has been overridden, receives touches outside the bounds.因此,即使指定的点位于该视图内容的透明部分中,并且现在在它被覆盖后接收到边界外的触摸,该视图仍然可以返回。 It did the trick for me.它对我有用。 Hope it helps you, guys.希望对你有帮助,伙计们。

swift迅速

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard !isHidden, alpha > 0 else {
      return super.hitTest(point, with: event)
    }
    
    for subview in subviews {
      let subpoint = subview.convert(point, from: self)
      let result = subview.hitTest(subpoint, with: event)
      if result != nil {
        return result
      }
    }
    return super.hitTest(point, with: event)
}

Objective-C目标-C

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (!self.clipsToBounds && !self.hidden && self.alpha > 0) {
        for (UIView *subview in self.subviews.reverseObjectEnumerator) {
            CGPoint subPoint = [subview convertPoint:point fromView:self];
            UIView *result = [subview hitTest:subPoint withEvent:event];
            if (result != nil) {
                return result;
            }
        }
    }
    // use this to pass the 'touch' onward in case no subviews trigger the touch
    return [super hitTest:point withEvent:event];
}

Just as an alternative answer - Actually for me, this has never worked (if uibutton is outside it's parent view, then it will not receive touch.) - But in some cases, it is required to have the button outside it's boundaries.就像一个替代答案 - 实际上对我来说,这从来没有奏效(如果 uibutton 在它的父视图之外,那么它不会收到触摸。) - 但在某些情况下,需要将按钮放在它的边界之外。

For that reason, there is a hittest function, which can be overridden - to simply check parent view all subviews to find uibutton that is placed outside parent views boundaries.出于这个原因,有一个可以覆盖的 hittest 函数 - 只需检查父视图的所有子视图即可找到放置在父视图边界之外的 uibutton。 (You would then check each subview, if it is uibutton type, and if touched coordinates are inside uibuttons frame. (然后您将检查每个子视图,如果它是 uibutton 类型,以及触摸的坐标是否在 uibuttons 框架内。

By default hittest function skips checking views, that are outside boundaries.默认情况下,hittest 函数会跳过检查超出边界的视图。

Hittest example: https://stackoverflow.com/questions/17246488/best-way-to-perform-the-hit-test-objective-c . Hittest 示例: https ://stackoverflow.com/questions/17246488/best-way-to-perform-the-hit-test-objective-c。

Not sure if this is the same case, but it might be related:不确定这是否是同一种情况,但可能是相关的:

When the UIButton is in a view with a UIGestureRecognizer which did NOT set delaysTouchesEnded to NO (default is YES), the button won't get TouchUpInside events anymore in iOS 7. It DID get the TouchUpInside events in iOS 6.当 UIButton 处于带有未将 delaysTouchesEnded 设置为 NO(默认为 YES)的 UIGestureRecognizer 的视图中时,该按钮在 iOS 7 中将不再获得 TouchUpInside 事件。它在 iOS 6 中确实获得了 TouchUpInside 事件。

If possible, set the delaysTouchesEnded property of the UIGestureRecognizer to NO to solve the problem.如果可能,将 UIGestureRecognizer 的 delaysTouchesEnded 属性设置为 NO 即可解决问题。

This is weird but I was developing a new app for iOS 7 and setting [cell.contentView setUserInteractionEnabled: YES];这很奇怪,但我正在为 iOS 7 开发一个新应用程序并设置[cell.contentView setUserInteractionEnabled: YES]; actually worked for me.实际上为我工作。

I had this same issue - buttons did work on iOS6 and didn't on iOS7, problem was with Container UIView to which one I was adding UIButtons , I add constrains to container UIView and it started working.我遇到了同样的问题 - 按钮在 iOS6 上工作,而在 iOS7 上没有,问题是容器UIView ,我添加了UIButtons ,我向容器UIView添加约束,它开始工作。 Code that I had to add in my case:我必须在我的案例中添加的代码:

[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:    [_controllersView]-|" options:0 metrics:nil views:views]];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_controllersView(70)]" options:0 metrics:nil views:views]];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_controllersView]|" options:0 metrics:nil views:views]];

我也遇到了同样的问题,但在添加以下代码按钮操作后正常工作cell.contentView.userInteractionEnabled = NO;

If it's using auto layout, then try adding a log statement in -viewDidAppear:如果它使用自动布局,则尝试在 -viewDidAppear 中添加日志语句:

NSLog(@"Height of UIView: %f",  self.<name of UIView>.frame.size.height);

if the result is 0 (or not large enough), then set the height of UIView large than the height of 'Discard All' button.如果结果为 0(或不够大),则将 UIView 的高度设置为大于“全部放弃”按钮的高度。

检查父框架内的按钮

Okay, so seems like buttons programatically created in iOS7 won't call their target.好的,似乎在 iOS7 中以编程方式创建的按钮不会调用它们的目标。 I don't know why, but I've found the following solution:我不知道为什么,但我找到了以下解决方案:

  1. In the InterFace Builder (or nib) add a button and customize and HIDE it.在界面生成器(或笔尖)中添加一个按钮并自定义和隐藏它。 ( theButtonInTheNib ); ( theButtonInTheNib );

  2. Make it IBOutlet property: @property (strong) IBOutlet UIButton *theButtonInTheNib使其成为 IBOutlet 属性: @property (strong) IBOutlet UIButton *theButtonInTheNib

  3. Make the target IBAction connection: (IBAction)theTargetAction:(id)sender;建立目标IBAction连接: (IBAction)theTargetAction:(id)sender;

Here comes the trick.诀窍来了。 We will make a copy/or copies of this button:我们将复制/或复制此按钮:

NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:theButtonInTheNib];
UIButton *theCopyButton = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
[theCopyButton setHidden:NO];
[theCopyButton setFrame:CGRectMake(x, y, width, height)];
[theCopyButton addTarget:self action:@selector(theTargetAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:theCopyButton];

I have added again the target action, but any other action will work.我再次添加了目标操作,但任何其他操作都可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM