2010-10-22 5 views
5

लौटाता है मेरे पास एक दृश्य पदानुक्रम है जिसमें स्क्रॉल व्यू पर छोटे दृश्य होते हैं। प्रत्येक दृश्य में बटन आदि जैसे सबव्यूव हो सकते हैंहिटटेस्ट गलत UIView

किसी कारण से, दृश्य पर बटन क्लिक नहीं किए जाते हैं; आगे की खोज से पता चला कि स्क्रॉल व्यू को टचबिगन घटना प्राप्त होती है, लेकिन बटन नहीं होता है। हिटटेस्ट को कॉल करना: ईवेंट: संदेश दिखाता है कि बटन वापस नहीं किया गया है, भले ही यह सीमाओं के भीतर है।

मैंने स्क्रॉल व्यू पर स्पर्श के स्थान का वर्णन करने वाला लॉग आउटपुट शामिल किया है, हिटटेस्ट से लौटाया गया आइटम, स्पर्श स्थान जहां मैंने स्थान इनव्यू कहा है: अपेक्षित आइटम का उपयोग करके, और अपेक्षित आइटम का पदानुक्रम (मुद्रित फ्रेम के साथ))। इस उत्पादन से मैं मान सकते हैं कि बटन बुलाया गया है चाहिए ...

किसी को भी इस व्याख्या कर सकते हैं? क्या मैं कुछ भूल रहा हूँ?

touched ({451, 309}) on <VCViewContainersView: 0x4b31ee0; frame = (0 0; 748 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x4b32130>> (location in expected item: {17, 7.5}) 
expected touched item is: 
view: <UIButtonLabel: 0x482b920; frame = (32 5; 36 19); text = 'Click'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4831370>>, layer transform: [1, 0, 0, 1, 0, 0] 
view: <UIRoundedRectButton: 0x482c100; frame = (50 50; 100 30); opaque = NO; layer = <CALayer: 0x482c450>>, layer transform: [1, 0, 0, 1, 0, 0] 
    view: <UIImageView: 0x480f290; frame = (0 0; 320 255); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x480e840>>, layer transform: [1, 0, 0, 1, 0, 0] 
    view: <VCViewContainer: 0x4b333c0; frame = (352 246.5; 320 471.75); layer = <CALayer: 0x4b33d50>>, layer transform: [1, 0, 0, 1, 0, 0] 
    view: <UIScrollView: 0x4b32600; frame = (0 0; 1024 748); clipsToBounds = YES; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x4b32780>>, layer transform: [1, 0, 0, 1, 0, 0] 
    view: <VCViewsContainerView: 0x4b31ee0; frame = (0 0; 748 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x4b32130>>, layer transform: [0, 1, -1, 0, 0, 0] 
     view: <UIWindow: 0x4b1d590; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4b1d6d0>>, layer transform: [1, 0, 0, 1, 0, 0] 

अद्यतन: UIWindow और VCViewsContainerView अलावा, सभी दृश्यों को प्रोग्राम के बनाई गई हैं initWithFrame का उपयोग कर: या बटन, buttonWithType के मामले में:। VCViewContainer को CGRectZero का उपयोग करके प्रारंभ किया गया है और जब UIImageView बनाया गया है, तो इसका फ्रेम छवि के आकार + उसके नीचे के लेबल के लिए अतिरिक्त स्थान पर सेट किया गया है।

अद्यतन 2: जब [hitTest self.layer: स्थान] बुला एक ही स्थान के साथ, मैं सही देखने की परत प्राप्त करें! यहाँ क्या चल रहा है...?

+0

UIRoundedRectButton * * बटन है। – kennytm

+0

हम देखना चाहते हैं कि आप अपने दृश्य पदानुक्रम ... InterfaceBuilder, कोड, बनाने की जरूरत है आदि ... – jv42

+0

@KennyTM: अगर यह स्पष्ट नहीं था, यह कहते हैं, "छुआ (स्थान) पर (वास्तव में छुआ आइटम)"। ध्यान दें कि छुआ आइटम VCViewContainerView और _not_ UIRoundedRectButton है। –

उत्तर

0

यदि मैं सही स्टैक को सही ढंग से समझता हूं तो आपका बटन कुछ UIImageView का सबव्यूव है - इसमें userInteractionEnabled संपत्ति सेट (डिफ़ॉल्ट रूप से) पर सेट है - इसलिए छवि दृश्य और उसके सभी सबव्यूव को कोई स्पर्श ईवेंट नहीं मिलेगा।

YES करने के लिए सेटिंग छवि को देखने के userInteractionEnabled संपत्ति समस्या का समाधान करना चाहिए

+0

बस अगर मैंने कोशिश की - लेकिन दुर्भाग्यवश यह मामला नहीं है। मुझे नहीं लगता कि आपने जो कहा वह सच है; दस्तावेज़ निर्दिष्ट करते हैं कि किसी ईवेंट हैंडलर की खोज शीर्ष से नीचे है, इसलिए बटन को पहले परीक्षण किया जाना चाहिए। और किसी भी मामले में, हिटटेस्ट: उपयोगकर्ता इंटरैक्शन द्वारा बिल्कुल प्रभावित नहीं होता है .. –

5

hitTest: withEvent: खिड़की पर शुरू होता है। प्रत्येक दृश्य अपने परीक्षणों से पहले अपने सबव्यूव का परीक्षण करता है, और इसी तरह, पुनरावर्ती रूप से। यदि कोई दृश्य का उपयोगकर्ता इंटरैक्शनएनेबल नहीं है, हालांकि, यह हिटटेस्ट से शून्य लौटाता है: साथ:, इसके सबव्यूज़ का परीक्षण किए बिना। इस तरह का एक दृश्य निश्चित रूप से हिट-परीक्षण किया जाता है, लेकिन यह तुरंत जवाब देता है कि न तो यह और न ही इसके किसी भी सबव्यू हिट व्यू है।

आप UIScrollView नहीं करने के लिए अपने userInteractinonEnabled सेट है। इस प्रकार, जब VCViewContainersView अपने subview UIScrollView परीक्षण, और UIScrollView रिटर्न शून्य है क्योंकि इसके userInteractionEnabled नहीं है, सीधे VCViewContainersView pointInside का उपयोग करता है: withEvent: खुद पर, पता चलता है कि स्पर्श के भीतर ही है, और हिट दृश्य के रूप में देता है (और खोज समाप्त होता है)। यह आपको बताए गए परिणाम बताता है।

यह तब नहीं होता जब आप परतों के माध्यम से हिट-टेस्ट करते हैं, यह है कि परतें स्पर्श करने योग्य नहीं हैं और स्पर्श के नियमों के बारे में कुछ भी नहीं जानते हैं, इसलिए वे उपयोगकर्ता इंटरेक्शनएनेबल को अनदेखा करते हैं, जो दृश्य सुविधा है, नहीं एक परत सुविधा। परत मारा-परीक्षण एक kludge, केवल जब एक दृश्य के एक पूरे परत पदानुक्रम (एक दृश्य पदानुक्रम के बिना) शामिल हैं के लिए लक्षित की तरह है और आप अनुकरण करने के लिए है कि एक विशेष परत स्पर्श है चाहता हूँ।की तुलना में यह करने के लिए एक दृश्य के hitTest है:: withEvent :, हालांकि वे कैसे वास्तव में समझाने के लिए असफल डॉक्स आपको बता दूँ कि तर्क को परत के hitTest के लिए अलग अलग है।

मुझे नहीं पता कि आपने अपने स्क्रॉल व्यू को टच करने योग्य क्यों सेट किया है, लेकिन यदि यह आपके लिए महत्वपूर्ण है, तो आप हिटटेस्ट ओवरराइड कर सकते हैं: साथ: UIScrollView सबक्लास में ताकि यह इसके सबव्यूज़ का परीक्षण कर सके लेकिन शून्य हो वे सभी शून्य वापस आते हैं।

+0

+1 स्पष्टीकरण के लिए धन्यवाद कि 'हिटटेस्ट: साथ:' आवेदक ''रिटर्न' शून्य 'जब' userInteractionEnabled' 'NO' –

+2

@AlexanderFarber मेरे पूर्ण रिवर्स के लिए टच डिलीवरी और हिट-टेस्टिंग की इंजीनियरिंग, यहां देखें: http://www.apeth.com/iOSBook/ch18.html#_hit_testing – matt

+0

धन्यवाद मैट, मैंने सफारी में अपनी पुस्तक पढ़ी - यह बहुत उपयोगी है। क्या आपको http://stackoverflow.com/questions/22582649/dragging-views-on-a-scroll-view-touchesbegan-is-received-but-no- पर मेरी वर्तमान समस्या (बाउंटी 500) के लिए कोई सलाह है? touchesended-o? मैं उचित 'हिटटेस्ट: के साथ:' वहां नहीं समझ सकता। –

1

आप अपने UIScrollView उपवर्गीकरण यह भीतर वस्तुओं पर छूता है प्राप्त करने के लिए कोशिश कर सकते हैं।

डिफ़ॉल्ट अपने छूता है, अपने UIScrollView द्वारा प्राप्त हो जाएगा, इसलिए यदि आप इसके अंदर की वस्तुओं पर अंतिम रूप प्राप्त करना चाहते हैं, तो आप उसे सेट कर स्पष्ट रूप से करने की जरूरत है के द्वारा।

यहाँ एक काम कर उपवर्ग सिर्फ इतना है कि ऐसा करने के लिए है। इसके लिए एसओ समुदाय के लिए धन्यवाद, क्योंकि मेरा मानना ​​है कि मुझे मूल रूप से ऐसा कुछ मिला है, बस मूल पोस्ट को खोद नहीं सकता है।

#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 

@interface TouchScroller : UIScrollView 
{ 
} 

@end 

और मीटर:

#import "TouchScroller.h" 


@implementation TouchScroller 

- (id)initWithFrame:(CGRect)frame 
{ 
return [super initWithFrame:frame]; 
} 

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event 
{ 
// If not dragging, send event to next responder 
if (!self.dragging) 
    [self.nextResponder touchesEnded: touches withEvent:event]; 
else 
    [super touchesEnded: touches withEvent: event]; 
} 

@end 

कि यह करना चाहिए

यहाँ ज है।