2013-09-25 31 views
2

無法點擊按鈕這是非常令人困惑的。在3.5」iPhone模擬器上,我的應用程序中的所有UIButton都可以正常工作。然而,當我在4「iPhone模擬器上啓動時,應用程序左側的所有UIButtons都不會收到任何點擊事件4「iPhone

下面是3.5英寸大小和4英寸大小的屏幕截圖。 4「大小,我添加了一行。該行左側,沒有任何按鈕會收到點擊事件。在該行的右側,所有按鈕的行爲都正常。按鈕2,5和8的左側不響應點擊,但是這些按鈕的右側響應。

enter image description here

enter image description here

UPDATE ---- 感謝@iccir,我發現更多的信息。顯然,我的UIWindow只有320x480而不是568x320。我沒有觸及我的代碼中的UIWindow,除非讓它看起來很重要。在我的MainWindow.xib中,我將它的IBOutlet連接到我的rootViewController。

<UIWindow: 0xc097d50; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0xc098460>; layer = <UIWindowLayer: 0xc097e70>> 

我是flabberghasted。任何想法爲什麼UIWindow的大小不正確?

+0

我認爲這是幀大小的問題。因此,請嘗試檢查視圖大小(在您嘗試添加按鈕時檢查視圖幀) – Tendulkar

+0

嘗試在設備上嘗試其他任何操作。 – preetam

+0

我沒有用於設備測試的iPhone 5。 –

回答

8

這是一個很常見的問題:你的UIButton超出了它的一個superviews的界限。如果clipsToBounds/masksToBounds設置爲NO(默認值),您的UIButton仍然會顯示,但觸摸事件不會被髮送到它。

讓我們來簡化這種情況。假設一個視圖控制器用下面的代碼:

- (void) viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIColor *fadedRedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.25]; 
    UIColor *fadedBlueColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.25]; 

    CGRect containerFrame = CGRectMake(25, 25, 100, 100); 
    CGRect buttonFrame = CGRectMake(100, 100, 64, 44); 

    UIView *container = [[UIView alloc] initWithFrame:containerFrame]; 

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 
    [button setTitle:@"Button" forState:UIControlStateNormal]; 
    [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 
    [button setFrame:buttonFrame]; 
    [button addTarget:self action:@selector(_handleButton:) forControlEvents:UIControlEventTouchUpInside]; 

    [container setBackgroundColor:fadedRedColor]; 
    [button setBackgroundColor:fadedBlueColor]; 

    [container addSubview:button]; 

    [[self view] addSubview:container]; 
} 

- (void) _handleButton:(id)sender 
{ 
    NSLog(@"Moooooo!"); 
} 

看起來像這樣: Screenshot 1

按鈕包含在container,但它駐留在容器的邊界的外側(容器是100個像素寬和100像素高,按鈕的原點在100, 100)。

當您觸摸屏幕時,UIKit將從視圖層次結構(UIWindow)的頂部開始遞歸調用-[UIView hitTest:withEvent:],直至找到應處理該觸摸的視圖。然而,在這個例子中,UIKit永遠不會下降到容器中(因爲你觸摸了它的邊界),因此按鈕子視圖將不會被擊中。

如果我們不是改變buttonFrame50, 50,它看起來像這樣: Screenshot 2

與容器重疊將響應觸摸事件按鈕的一部分。駐留在容器外的部分將不會:

Screenshot 3

要調試一個觀點,即不完全可觸摸,你可以試試下面這樣的調試功能:

static void sDebugViewThatIsntTouchable(UIView *view) 
{ 
    UIView *superview = [view superview]; 

    while (superview) { 
     CGRect rectInSuperview = [view convertRect:[view bounds] toView:superview]; 

     CGPoint topLeft  = CGPointMake(CGRectGetMinX(rectInSuperview), CGRectGetMinY(rectInSuperview)); 
     CGPoint topRight = CGPointMake(CGRectGetMaxX(rectInSuperview), CGRectGetMinY(rectInSuperview)); 
     CGPoint bottomLeft = CGPointMake(CGRectGetMinX(rectInSuperview), CGRectGetMaxY(rectInSuperview)); 
     CGPoint bottomRight = CGPointMake(CGRectGetMaxX(rectInSuperview), CGRectGetMaxY(rectInSuperview)); 

     if (![superview pointInside:topLeft withEvent:nil]) { 
      NSLog(@"Top left point of view %@ not inside superview %@", view, superview); 
     } 

     if (![superview pointInside:topRight withEvent:nil]) { 
      NSLog(@"Top right point of view %@ not inside superview %@", view, superview); 
     } 

     if (![superview pointInside:bottomLeft withEvent:nil]) { 
      NSLog(@"Bottom left point of view %@ not inside superview %@", view, superview); 
     } 

     if (![superview pointInside:bottomRight withEvent:nil]) { 
      NSLog(@"Bottom right point of view %@ not inside superview %@", view, superview); 
     } 

     superview = [superview superview]; 
    } 
}; 

編輯: 正如你在評論中提到的,罪魁禍首是UIWindow的主要尺寸爲320x480而不是320x568。 打開xib中的「啓動時全屏」固定此

當然,問題是:「爲什麼?」 :)

如果您在文本編輯器中拉出xib文件,您會注意到寬度320和高度480被硬編碼到窗口。當xib在啓動時解碼時,窗口最初是用這個320x480幀構造的。

UIKit然後查詢-[UIWindow resizesToFullScreen](私有方法)。如果這返回YES,則UIWindow執行[self setFrame:[[self window] bounds]]的等效操作。

在Interface Builder中切換「啓動時全屏」標誌直接切換私有UIWindow.resizesToFullScreen標誌。

+0

這個功能非常完美,謝謝!事實證明,我的'self.view'是正確的大小,但UIWindow是320x480!那麼......到底是怎麼回事?我會繼續尋找。 –

+0

您是在代碼中還是在xib/storyboard中手動創建UIWindow?如果手動操作,是否希望將[[UIScreen mainScreen]範圍]或'-applicationFrame'用於窗口框架而不是硬編碼值。 – iccir

+0

我使用的是由Xcode生成的舊MainWindow.xib。 –

0

讓我猜,這隻發生在風景模式,對吧? 當我專門爲iPhone-4S開發時,我在我的應用程序中遇到了同樣的問題。但是當我開始測試iPhone-5時,觸摸底部並沒有奏效。這是frame。確保frames設置爲bounds,無論是在代碼中,還是XIB文件(如果有的話)。 manxib文件中的不同frames/bounds也可能導致此類行爲。

我最終刪除了xib文件,並以編程方式執行了所有操作。我學到的一件事是,將你的框架設置爲viewWillAppearviewDidAppear而不是viewDidLoad。還請檢查您的RootViewController中的frame/bounds。最後一件事,儘量不要使用常數值爲frames,對超視圖使用參考幀。

PS,知道是否真的是造成這種行爲的框架/邊界的一種方法是,對views設置masksToBoundsYES。那樣,你的觀點就不會在他們的觀點之外看到。

+0

讓我知道,即使這不起作用。 – n00bProgrammer

+0

我沒有以編程方式設置我的框架,它們在xib加載時自動設置。我已驗證該視圖是568x320。卡片(UIButtons)直接添加到主視圖中,不在超級視圖之外。例如,我無法點擊的其中一張卡在(18,60)50x64。 –

+0

@iccir答案是正確的。 這是我的第二個建議。在AppDelegate文件的'applicationDidFinishLaunching'方法中,應該相應地設置'applicationFrame'。一個不錯的選擇是使用'[UIScreen mainScreen] .bounds',但你可能想要檢查它在iOS7上的行爲。我還沒有遷移到XCode5/iOS7,所以不能肯定地說。 – n00bProgrammer