iOS UI 技巧: 视图无法被点击

来源:互联网 发布:机械能守恒实验带数据 编辑:程序博客网 时间:2024/05/18 01:08

初学 iOS 开发, 有时候会被一些很简单的问题给弄得头昏脑涨.

iOS UI 技巧系列博客, 将和大家一起总结和积累在 iOS 开发中遇到的各种奇葩问题.

今天和大家聊聊, 当前设置的视图无法被点击的原因和解决思路.

当我们添加一个视图A到另外一个视图B上面, 希望视图B可以被点击或者被 touch.

当然, 这个是一个再正常不过的要求.

当你一切准备就绪, 发现, 卧槽, B 为什么点击不了.什么鬼.

B 不能被点击, 有下面几个原因.

  1. 被其他透明的视图挡住了
  2. 没有设置userInteractionEnabled为 yes
  3. frame 设置错误
  4. 等等…

那么对应的解决方案, 也有几种

  1. 颜色法(设置不同的 BackGroundColor 调试)
  2. 看视图的等级结构
  3. 设置userInteractionEnabled为 yes
  4. 设置 masksToBounds为 yes

在开发的过程中, 比较常见的就是userInteractionEnabled设置错误.

这个问题很好解决.

iOS 开发文档说了, userInteractionEnabled属性默认是 yes, 但是有些 UIView 的子类改变了这个继承的属性.
你看 UILabel 的头文件:

// default is NO@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;  

凡是 UIControl 的子类该属性都是 yes.
UIControl 子类看下图.

图1

这些东西不需要大家死记硬背.多查文档就知道了.

至于视图层级查看, xcode 现在也自带了一个类似 Reveal 的功能, 但是个人还是比较习惯 Reveal, 使用 Reveal 来排查和优化 UI 问题, 简直爽.

关于 frame 导致无法点击, 这个问题在初学者面前确实有点难搞.

下面举个例子.

图2

绿色视图是视图 A, 红色视图是 B 视图(Button).

A 视图添加了 B 视图.

#import "ViewController.h"#define kViewWidth  (200)#define kViewHeight (160)@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad{    [super viewDidLoad];    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(50, 100, kViewWidth, kViewHeight)];    view.backgroundColor = [UIColor greenColor];    [self.view addSubview:view];    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    // 将 button 添加到 vview 中    [view addSubview:button];    [button setBackgroundColor:[UIColor redColor]];    [button setTitle:@"可能你点击不了我!" forState:UIControlStateNormal];    button.frame = CGRectMake(0, kViewHeight, kViewWidth, 100);    [button addTarget:self action:@selector(onClickButton:) forControlEvents:UIControlEventTouchUpInside];}- (void)onClickButton:(UIButton *)sender{    NSLog(@"button is clicked.");}@end

无论你怎么点击视图 B, 都不可能调用 onClickButton 方法.

仔细观察代码, 可以发现 Button 的位置已经超出了父视图 A 的范围.

那么我们可以设置 masksToBounds, 将超出父视图的子视图裁剪掉.

view.layer.masksToBounds = YES;

再次运行, 你就无法看到红色的 Button 视图了.

重新调整 Button 的 y 位置, 就可以解决问题.

这里的视图层级关系比较简单.
当视图比较复杂的时候, 猜测是否是 frame 问题, 可以这样调用:

subView.superview.layer.masksToBounds = YES;
1 0