在視圖控制器類中,self.view中會包括多個多層的自定義視圖。我自定義了一個uicollectionview類,名稱爲gridview,又自定義了一個uicollectionviewcell類,名爲gridcell。在gridcell的contentview中增加uitextfield對象。
+----------------------------+
|A -gridview |
|+--------+ +------------+ |
||B- | |C | |
||gridcell| |gridcell | |
|+--------+ +------------+ |
| |
| |
+----------------------------+
這樣,該視圖控制器類就會展現出一系列的表格組合,類似於excel。要實現的功能有這些:
1、在touch一個格子時就能出現虛擬鍵盤,從而可以立即編輯它。
2、在虛擬鍵盤出現以後,再touch表格視圖的任意點都能關閉虛擬鍵盤,但不再次打開可能被touch到的另外一個格子。
3、在longpress一個格子時,還是鎖定並移動它到任意位置上。
通過對touch事件的控制,可以實現虛擬鍵盤的打開和關閉,所見即所得的功能。
uiview的hitTest:withEvent:方法
在自定義的gridview類中,需要對該方法進行重定義,用於控制touch事件的傳播和對gridview的處理。
如果hitTest:withEvent:返回的結果不是nil,則touch事件會傳播到gridcell中,並調用gridview的-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event方法。
如果返回的結果是nil,則返回調用視圖控制器類中-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event方法,這個方法重載以後,可以實現對控制虛擬鍵盤的關閉。
因此,重載這個方法,可以實現對touch事件的傳播的控制。
gridview中重載的方法
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
// 根據條件截斷 事件的傳輸鏈條
if ([selfisFirstResponder]) {
// [selfresignFirstResponder]; 因爲該方法 一次點擊會被調用兩次,導致其會進一步調用cell中的該方法。所以不在此處 resign first responder
// 在此出將 事件鏈條 截斷,從而使得 集合視圖可以工作。否則,將觸發集合視圖覆蓋的虛擬鍵盤。
// return NO;
}
return [superpointInside:point withEvent:event];
}
在這個方法中也可以實現對touch事件的傳播進行控制。
//---
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
GTMLoggerDebug(@"\nmasterCV hitTest:%@", [NSDate date]);
// 根據條件截斷 事件的傳輸鏈條
if ([selfisFirstResponder]) {
// [selfresignFirstResponder]; 因爲該方法 一次點擊會被調用兩次,導致其會進一步調用cell中的該方法。所以不在此處 resign first responder
// 在此出將 事件鏈條 截斷,從而使得 集合視圖可以工作。否則,將觸發集合視圖覆蓋的虛擬鍵盤。
return nil;
}
if (self.editingCell)
{
return nil;
}
UIView *result = [superhitTest:point withEvent:event];
return result;
}
注意,這兩個方法在一次touch時,會被多次調用。在ios7.1中,我測試結果是2次調用,在網上看到有說是3次調用的。
因此,該方法中只用來實現touch事件的傳播控制,不做其他任務如關閉虛擬鍵盤等處理。
這些任務處理在視圖控制類中實現。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[supertouchesBegan:touches withEvent:event];
if ([_gridViewisFirstResponder]) {
[_gridViewresignFirstResponder];
}
[self.navigationItem.titleViewendEditing:YES];
[self.viewendEditing:YES];
}
處理的任務分別有:
如果gridview是第一響應者,則重置它;
導航欄上標題視圖的編輯結束;
self.view中所有視圖的編輯結束。