ipad - how to dismiss a modal view controller presented as "Form Sheet" when a touch occur outside the form sheet? -
i have view controller (with uiwebview) present in form sheet style. have put "done" button in uitoolbar of view in view controller have dismissed. but, since presenting in "form sheet" style leaves plenty of unused space outside view controller's view... wandering.. there way detect touch outside view? in "grayed out" area? in advance
on ios 4.2, view hierarchy of navigation controller based app modal form sheet follows during viewwillappear:
. once modal view appears, uitransitionview has been replaced uidropshadowview contains modal view hierarchy.
uiwindow uilayoutcontainerview (regular hierarchy) uidimmingview uitransitionview
apple warn against relying on subviews of built in views, these considered private , may change in future releases. potentially break app.
approach 1
can insert transparent view between last 2 subviews of window, , have respond touch events dismissing modal form.
this implementation checks window's view hierarchy expected, , silently nothing if not.
create , use dismissingview
viewwillappear:
in modal view controller.
dismissingview *dismiss = [[dismissingview alloc] initwithframe:window.frame selector:@selector(dismissview:) target:self]; [dismiss addtowindow:window]; [dismiss release];
and implementation.
@interface dismissingview : uiview { } @property (nonatomic, retain) id target; @property (nonatomic) sel selector; - (id) initwithframe:(cgrect)frame target:(id)target selector:(sel)selector; @end @implementation dismissingview @synthesize target; @synthesize selector; - (id) initwithframe:(cgrect)frame target:(id)target selector:(sel)selector { self = [super initwithframe:frame]; self.opaque = no; self.backgroundcolor = [uicolor clearcolor]; self.selector = selector; self.target = target; return self; } - (void) addtowindow:(uiwindow*)window { nsuinteger count = window.subviews.count; id v = [window.subviews objectatindex:count - 1]; if (![@"uitransitionview" isequal:nsstringfromclass([v class])]) return; v = [window.subviews objectatindex:count - 2]; if (![@"uidimmingview" isequal:nsstringfromclass([v class])]) return; uiview *front = [window.subviews lastobject]; [window addsubview:self]; [window bringsubviewtofront:front]; } - (void)touchesbegan:(nsset*)touches withevent:(uievent*)event { [self removefromsuperview]; [target performselector:selector withobject:self]; } @end
approach 2
first approach preferred, 1 has additional logic every touch event on modal form.
add transparent view front view of window. touch events within modal view's frame passed it, , outside frame dismiss modal form.
before appears, modal view hierarchy looks this. when appears, uidropshadowview replaces uitransitionview in window's subviews. uilayoutcontainerview
uidropshadowview uiimageview uilayoutcontainerview uinavigationtransitionview uiviewcontrollerwrapperview uiview (the modal view) uinavigationbar
the implementation same before, new property , addtowindow:
replaced addtowindow:modalview:
.
dismissingview can still added window in viewwillappear:
, since uidropshadowview replaces uitransitionview.
again silently nothing if view hierarchy not expected.
@property (nonatomic, retain) uiview *view; - (void) addtowindow:(uiwindow*)window modalview:(uiview*)v { while (![@"uilayoutcontainerview" isequal:nsstringfromclass([v class])]) { v = v.superview; if (!v) { return; } } self.view = v; [window addsubview:self]; } - (uiview*)hittest:(cgpoint)point withevent:(uievent*)event { cgpoint p = [self convertpoint:point toview:view]; uiview *v = [view hittest:p withevent:event]; return v ? v : [super hittest:point withevent:event]; }
Comments
Post a Comment