- (void)preventGADBannerViewBounceScrolling:(GADBannerView*)bannerView {
for (UIWebView *webView in bannerView.subviews) {
if ([webView isKindOfClass:[UIWebView class]]) {
webView.scrollView.scrollEnabled = NO;
webView.scrollView.bounces = NO;
}
}
}
I have been using the above code to stop the AdMob banner from scrolling.
I just updated the SDK to the latest (6.12.0) and having this code and calling it with the following...
[self.view addSubview:self.adMobBannerView];
[self preventGADBannerViewBounceScrolling:(GADBannerView *)_adMobBannerView];
Does nothing on the latest SDK, I was wondering if anyone has had this issue and resolved it?
Also when on this subject, I have noticed some developers have made their banners so if the user clicks then it opens up in a web view within the application and has a "Done" button at the right hand corner so the user does not fully leave the application when they press on the in-app adverts, I think that is genius...
If anyone could tell me how that is done I would appreciate that greatly!
It looks like UIWebView is wrapped into one more view in the new SDK, so it's better to go through the whole subview tree:
- (void)walkSubviewsOfView:(UIView *)v block:(void (^)(UIView *))block {
block(v);
for (UIView *subview in v.subviews) {
[self walkSubviewsOfView:subview block:block];
}
}
- (void)disableBannerWebViewBouncing {
[self walkSubviewsOfView:_bannerView block:^(UIView *v) {
for (UIGestureRecognizer *r in v.gestureRecognizers) {
if ([NSStringFromClass(r.class) isEqual:#"UIWebTouchEventsGestureRecognizer"])
r.enabled = NO;
}
if ([v isKindOfClass:[UIScrollView class]])
((UIScrollView *)v).bounces = NO;
}];
}
Of course this is not a future proof solution as well, I'd prefer there would be a corresponding property in the SDK.
I went with a non-block version of aleh's answer, I found it easier to read:
- (void)removeScrollingFromView:(UIView *)view
{
for (UIView *subview in view.subviews) {
[self removeScrollingFromView:subview];
}
if ([view isKindOfClass:[UIWebView class]]) {
((UIWebView *)view).scrollView.scrollEnabled = NO;
((UIWebView *)view).scrollView.bounces = NO;
}
}
I know I won't have any scrolling ads, but if you do, just disable bouncing and not scrolling. If you vote up my answer, please consider giving aleh a vote up too!
Related
I'm implementing a share extension for my app, so far everything is going good except I can't seem to dismiss the keyboard that automatically opens using the default layout/storyboard.
I'm keeping the default design/layout (SLComposeServiceViewController) which includes the preview image and UITextview, the UITextview automatically gets in focus which opens the keyboard.
Normally this is fine, but if you're not logged in my app I display an UIAlertController saying you need to login to share. The problem is the keyboard opens at the same time as the alert.
I've tried [self.view endEditing:YES]; and [self.textView resignFirstResponder]; in both viewDidLoad, viewDidAppear and viewWillAppear with no luck.
Found the answer! I didn't read the docs very carefully...
I had to do [self.textView resignFirstResponder]; in -(void)presentationAnimationDidFinish
my way is to use UITextViewDelegate
- (void)viewDidLoad {
[super viewDidLoad];
self.textView.delegate = self;
self.canShare = NO;
[self.view setAlpha:0.0];
}
change canShare to YES in your check login logic
- (void)checkLoggedIn {
if ([[ShareAccountManager checkLoggedIn]) {
self.canShare = YES;
[self.view setAlpha:1.0];
}
}
and implement method textViewShouldBeginEditing
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
if (self.canShare) {
return YES;
}
return NO;
}
I want to implement a function whereby a lock button is pressed which locks the current state of my app and prevents all scrolling and button pressing until the unlock button is pressed. I have no idea how to go about this please give me ideas and sample code! There is a similar function in the app GoodReader if anyone knows of this.
Thanks!
try something like:
for(UIView* subview in [self.view subviews])
if(subview != yourLockButton)
subview.userInteractionEnabled = NO;
Disable all the scroll in the view
- (void)disableScrollView
{
for (UIScrollView *view in your_viewController.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.scrollEnabled = NO;
}
}
}
Please bear with me, I searched a lot over the internet and I couldn't find a solution since it's a new API.
I am trying to create a custom keyboard for iOS 8. It works perfectly fine except in WebView!
It has previous-next button, which are in inputAccessoryView. I know it's read-only property for webview but since iOS 8 allows the users to have custom keyboard I assume this view should be editable somewhere. Has anybody run into the same issue? Any help would be appreciated.
You may try and improve this. try call this function inside Your UIKeyboardDidShowNotification event handler.
-(void) removeKeyboard {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([[possibleFormView description] hasPrefix : #"<UIInputSetContainerView"]) {
for (UIView* peripheralView in possibleFormView.subviews) {
for (UIView* peripheralView_sub in peripheralView.subviews) {
// hides the backdrop (iOS 8)
if ([[peripheralView_sub description] hasPrefix : #"<UIKBInputBackdropView"] && peripheralView_sub.frame.size.height == 44) {
[[peripheralView_sub layer] setOpacity : 0.0];
}
// hides the accessory bar
if ([[peripheralView_sub description] hasPrefix : #"<UIWebFormAccessory"]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
CGRect frame1 = UIInputViewContent_sub.frame;
frame1.size.height = 0;
peripheralView_sub.frame = frame1;
UIInputViewContent_sub.frame = frame1;
[[peripheralView_sub layer] setOpacity : 0.0];
}
CGRect viewBounds = peripheralView_sub.frame;
viewBounds.size.height = 0;
peripheralView_sub.frame = viewBounds;
}
}
}
}
}
}
Hope this helps...
This is the level of views in accessory:
(UIWebFormAccessory) -> (UIToolbar) -> (UIImageView,UIToolbarButton,UIToolbarButton)
Removing or scaling to zero height the accessory bar will cause black area. You can play around the mainview's frame or bounds. or if You just want to get rid of the buttons, just try to have a 0 opacity on the UIToolbutton , the toolbutton is inside uitoolbar view
Use this , it works like a charm and it is much cleaner than the other solutions. It's hacking with the inputAccessoryView for UIWebBrowserView (inner UIWebView).
Good luck with coding!
In my app I need to call some UIViews more than once. But in one of my method, i've a code like :
[self addSubview:UIImageView];
But i've read that addsubview method must be call once. So, to let the code how is it, how could I check if it's already on subview ? Like :
if ([UIImageView isOnSubview] == NO)
{
[self addSubview:UIImageView];
}
Because I don't find any method to check this :/
Thank you !
You are probably looking for UIView's -(BOOL)isDescendantOfView:(UIView *)view; taken in UIView class reference.
use this one
for (UIView *subview in [self subviews])
{
NSLog(#"%#", subview);
// ---------- remember one thing there should be one imageview ------
if(![subview isKindOfClass:[UIImageView class]])
{
[self addSubview:UIImageView];
}
}
(my boss says) that I have to implement a "Done" button on a navBar so that the various items in the view (that contain an edit box) will dismiss their keyboard (if they were in focus).
It seems that I must iterate through all items and then call resignFirstResponder on each on the off-chance that one of them is in focus? This seems a bit messy (and hard to maintain if e.g. someone else adds more items in future) - is there a better way to do it?
I have found it!
Thanks to this
I discovered that all I need do is this:-
-(void) done {
[[self.tableView superview] endEditing:YES];
}
// also [self.view endEditing:YES]; works fine
[remark]
Also I learn how to do the equivalent of an "eventFilter" to stop UITableViewController from swallowing background touch events by intercepting them before they get there - from the same, wonderful post on that thread - see "DismissableUITableView".
[end of remark]
You don't have to iterate through the controls since only one can be first responder at the moment.
This will reset the responder to the Window itself:
[[self window] makeFirstResponder:nil]
One solution is to use a currentTextField Object,
In .h file have an instance variable as
UITextField *currentTextField;
Now in .m file.
Note : Dont forget to set the delegates of all the textField to this class
- (void)textViewDidBeginEditing:(UITextView *)textView
{
currentTextField = textField;
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
currentTextField = nil;
}
Now in your button action method
-(IBAction)buttonTap
{
if([currentTextField isFirstResponder])
[currentTextField resignFirstResponder];
}
This avoids iterating through all the text field.
I think best way to handle it by searching all subviews of main view with recursive function, check example below
- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder]) {
return YES;
}
}
return NO;
}
and also you can put this method to your utility class and can use from tap gesture. All you have to do is simply adding to gesture to view.
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(hideEverything)];
[self.tableView addGestureRecognizer:gestureRecognizer];
and than you can call hideEverything method;
- (void) hideKeyboard {
[self.view findAndResignFirstResponder];
...
...
}