I made a game(which already fills up the screen) but now I want to add a banner to it using admob.
If I add a banner now, part of the screen I am using will be blocked because of the banner. How do I insert the banner without overlaying my game scene?
PS: All sizes are based on my frame.size, So I tried
frame.size.height = 0.9 * frame.size.height
But this doesn't work(gives error)
What is the right way to do this?
You can't modify directly a view.frame or .bounds (and it's deprecated to do that).
To do that you'll have to create a pretty new frame :
gameView.frame = CGRectMake(CGRectGetMinX(gameView.bounds),
CGRectGetMinY(gameView.bounds),
CGRectGetWidth(gameView.bounds),
CGRectGetHeight(gameView.bounds) * 0.9f);
CGRect contentFrame = self.view.bounds;
if (contentFrame.size.width < contentFrame.size.height) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
CGRect bannerFrame = _bannerView.frame;
if (_bannerView.bannerLoaded) {
contentFrame.size.height -= _bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
[UIView animateWithDuration:animated ? 0.25 : 0.0 animations:^{
_contentView.frame = contentFrame;
[_contentView layoutIfNeeded];
_bannerView.frame = bannerFrame;
}];
Here content view is instance of UIViewController and _bannerView is GADBannerView instance.
Related
I have iAds working almost perfectly using a modified version of UITabBarController-iAds. The only issue I have is on the very first load of an advert my view gets covered. Once the ad refreshes after 30 seconds the view resizes just fine.
I'm using the following code:
- (void)layoutBanner
{
float height = 0.0;
ADBannerView *_banner = (ADBannerView *)[self.view viewWithTag:12];
CGRect bounds = [UIScreen mainScreen].bounds;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
_banner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_banner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
//When compiling against iOS 8 SDK this needs to be height, regardless of the actual device orientation
height = bounds.size.height;
CGSize bannerSize = [ADBannerView sizeFromBannerContentSizeIdentifier:_banner.currentContentSizeIdentifier];
//Get content view
UIView *_contentView = self.selectedViewController.view;
CGRect contentFrame = _contentView.frame;
CGRect bannerFrame = _banner.frame;
if (_banner.isBannerLoaded) {
if (iOS7) {
contentFrame.size.height = height - bannerSize.height;
bannerFrame.origin.y = contentFrame.size.height - self.tabBar.frame.size.height;
} else {
contentFrame.size.height = height - self.tabBar.frame.size.height - bannerSize.height;
bannerFrame.origin.y = contentFrame.size.height;
}
} else {
if (iOS7) {
contentFrame.size.height = height;
bannerFrame.origin.y = bounds.size.height;
} else {
contentFrame.size.height = height - self.tabBar.frame.size.height;
bannerFrame.origin.y = bounds.size.height;
}
}
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
_contentView.frame = contentFrame;
} completion:^(BOOL finished) {
[self.view bringSubviewToFront:_banner];
}];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"Did load");
[self layoutBanner];
}
Any ideas?
I managed to fix this issue by playing around with the animation block. I moved the content view line and it resolved the issue
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
} completion:^(BOOL finished) {
_contentView.frame = contentFrame;
[self.view bringSubviewToFront:_banner];
}];
I'm not 100% sure, but I suppose the problem is related to:
[self.view bringSubviewToFront:_banner];
The whole animation:
[UIView animateWithDuration:0.25 animations:^{
_banner.frame = bannerFrame;
_contentView.frame = contentFrame;
} completion:^(BOOL finished) {
[self.view bringSubviewToFront:_banner];
}];
is a little strange, because at the completion block you are bringing the banner view to front, so I can suppose that before animation did start - the banner was covered by some other view or views - what is the reason of frame animation if banner view is covered - thus cannot be seen while animation is in progress?
Of course the issue applies only for the first run.
as of iOs8 [[UIScreen mainScreen]bounds] has changed.. previously it would always return portrait (where H > W ) values, regardless of interfaceOrientation, but it now appears to respect interface orientation... (which is not a bad thing, unless you're taking previous behaviour for granted)
Why don't you try CGRectGetMinY(CGRect aRect) ..
eg. (Im assuming from your code the banner goes along the screen bottom, and your TAbBar across the top. (which I think is weird..) )
//once you have calculated bannerFrame
contentFrame.size.height = ( CGRectGetMinY(bannerFrame) - CGRectGetMinY (contentView.frame) );
contentFrame.origin.y = CGRectGetMaxY(self.tabbar.frame);
Do you have any constraints / resizingMasks set? when you load a second ad the view controller's view has already been resized to fit an ad, presumably the first ad is the one trying to change things..
I've managed to implement iAd into my app and the banner loads from the bottom, I'm unsure how to get it to load from the top instead. I've tried a number of things but I can't seem to crack it. Can anyone help please?
The code I have:
- (void)layoutAnimated:(BOOL)animated
{
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame = self.bannerView.frame;
if (self.bannerView.bannerLoaded) {
contentFrame.size.height -= self.bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
[UIView animateWithDuration:animated ? 0.25 : 0.0 animations:^{
self.contentView.frame = contentFrame;
[self.contentView layoutIfNeeded];
self.bannerView.frame = bannerFrame;
}];
}
I have a positioning issue of admob for the ipad. The position of the banner is in the middle of the screen when running on ipad. Android and iphone display the banner on the bottom. After debuging CGSize s = [[CCDirector sharedDirector] viewSize]; seems to think its an iphone. Any idea why?I am using this sample
Its a cocos2d project.
AppDelegate.h
#define ADMOB_BANNER_UNIT_ID ((IS_IPAD) ? #"a1526954f69b314" : #"a1526955dc20272" );
#import "GADBannerView.h"
typedef enum _bannerType
{
kBanner_Portrait_Top,
kBanner_Portrait_Bottom,
kBanner_Landscape_Top,
kBanner_Landscape_Bottom,
}CocosBannerType;
#define BANNER_TYPE kBanner_Portrait_Bottom
#interface AppController : CCAppDelegate<GADBannerViewDelegate> {
CocosBannerType mBannerType;
GADBannerView *mBannerView;
float on_x, on_y, off_x, off_y;}
-(void)hideBannerView;
-(void)showBannerView;
#end
AppDelegate.m
#implementation AppController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Configure Cocos2d with the options set in SpriteBuilder
NSString* configPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Published-iOS"]; // TODO: add support for Published-Android support
configPath = [configPath stringByAppendingPathComponent:#"configCocos2d.plist"];
NSMutableDictionary* cocos2dSetup = [NSMutableDictionary dictionaryWithContentsOfFile:configPath];
// Note: this needs to happen before configureCCFileUtils is called, because we need apportable to correctly setup the screen scale factor.
#ifdef APPORTABLE
if([cocos2dSetup[CCSetupScreenMode] isEqual:CCScreenModeFixed])
[UIScreen mainScreen].currentMode = [UIScreenMode emulatedMode:UIScreenAspectFitEmulationMode];
else
[UIScreen mainScreen].currentMode = [UIScreenMode emulatedMode:UIScreenScaledAspectFitEmulationMode];
#endif
// Configure CCFileUtils to work with SpriteBuilder
[CCBReader configureCCFileUtils];
// Do any extra configuration of Cocos2d here (the example line changes the pixel format for faster rendering, but with less colors)
//[cocos2dSetup setObject:kEAGLColorFormatRGB565 forKey:CCConfigPixelFormat];
[self setupCocos2dWithOptions:cocos2dSetup];
#ifndef APPORTABLE
[[AAGameCenter sharedGameCenter] authenticateLocalUser];
#endif
[self createAdmobAds];
return YES;
}
- (CCScene*) startScene
{
return [CCBReader loadAsScene:#"MainMenuScene"];
}
+ (void)initialize
{
#ifndef APPORTABLE
//configure iRate
[iRate sharedInstance].appStoreID = 87522385224; // Replace this
#endif
}
-(void)createAdmobAds
{
mBannerType = BANNER_TYPE;
if(mBannerType <= kBanner_Portrait_Bottom)
mBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
else
mBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerLandscape];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
mBannerView.adUnitID = #"ca-app-pub-885995432323732999994/1885724261";
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
mBannerView.rootViewController = self.navController;
[self.navController.view addSubview:mBannerView];
//#ifdef DEBUG
// GADRequest *request = [GADRequest request];
// request.testDevices = [NSArray arrayWithObjects:GAD_SIMULATOR_ID, nil];
//#endif
// Initiate a generic request to load it with an ad.
[mBannerView loadRequest:[GADRequest request]];
CGSize s = [[CCDirector sharedDirector] viewSize];
CGRect frame = mBannerView.frame;
off_x = 0.0f;
on_x = 0.0f;
switch (mBannerType)
{
case kBanner_Portrait_Top:
{
off_y = -frame.size.height;
on_y = 0.0f;
}
break;
case kBanner_Portrait_Bottom:
{
off_y = s.height;
on_y = s.height-frame.size.height;
}
break;
case kBanner_Landscape_Top:
{
off_y = -frame.size.height;
on_y = 0.0f;
}
break;
case kBanner_Landscape_Bottom:
{
off_y = s.height;
on_y = s.height-frame.size.height;
}
break;
default:
break;
}
frame.origin.y = off_y;
frame.origin.x = off_x;
mBannerView.frame = frame;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationOptionCurveEaseOut];
frame = mBannerView.frame;
frame.origin.x = on_x;
frame.origin.y = on_y;
mBannerView.frame = frame;
[UIView commitAnimations];
}
-(void)showBannerView
{
if (mBannerView)
{
//banner on bottom
{
CGRect frame = mBannerView.frame;
frame.origin.y = off_y;
frame.origin.x = on_x;
mBannerView.frame = frame;
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
CGRect frame = mBannerView.frame;
frame.origin.y = on_y;
frame.origin.x = on_x;
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
}];
}
//Banner on top
// {
// CGRect frame = mBannerView.frame;
// frame.origin.y = -frame.size.height;
// frame.origin.x = off_x;
// mBannerView.frame = frame;
//
// [UIView animateWithDuration:0.5
// delay:0.1
// options: UIViewAnimationCurveEaseOut
// animations:^
// {
// CGRect frame = mBannerView.frame;
// frame.origin.y = 0.0f;
// frame.origin.x = off_x;
// mBannerView.frame = frame;
// }
// completion:^(BOOL finished)
// {
//
//
// }];
// }
}
}
-(void)hideBannerView
{
if (mBannerView)
{
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGRect frame = mBannerView.frame;
frame.origin.y = off_y;
frame.origin.x = off_x;
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
}];
}
}
-(void)dismissAdView
{
if (mBannerView)
{
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGSize s = [[CCDirector sharedDirector] viewSize];
CGRect frame = mBannerView.frame;
frame.origin.y = frame.origin.y + frame.size.height ;
frame.origin.x = (s.width/2.0f - frame.size.width/2.0f);
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
[mBannerView setDelegate:nil];
[mBannerView removeFromSuperview];
mBannerView = nil;
}];
}
}
#end
I had the same situation until I found this. #macgeo your solution does work, I am not sure why but it does revert back the size to the values that work for an ipad device
Additional info: Using SpriteBuilder with produces a content size of (384,512) on a portrait layout with a content scale factor of 4. The content scale factor has no influence in the result of the view positioning as when changing size to
CGRect contentFrame = [CCDirector sharedDirector].view.bounds;
which produces a size of (768,1024) like if it were using a content scale factor of 2, but still the value is 4.
Think problem might be fixed by changing viewSize to view.bounds
//CGSize s = [[CCDirector sharedDirector] viewSize];
CGRect contentFrame = [CCDirector sharedDirector].view.bounds;
And then using contentFrame.size.height for your y positioning. Was having trouble with iAd stuff and that seemed to fix it.
I am new to Adwhirl and am having some problems. I am setting my mainScreen controller as the delegate for AdView. While I am in this view, the ads refresh just fine. When I switch to another view though, the delegate no longer received any new ads(the delegates selectors are not fired). Is there a reason for this? I want one adView for my whole app, so I am passing a pointer around to it everywhere and adding it as a subview to the proper view.
Here is some code:
#pragma mark AdWhirl required delegate methods
- (NSString *)adWhirlApplicationKey {
return MY_AD_WHIRL_APPLICATION_KEY;
}
- (UIViewController *)viewControllerForPresentingModalView {
return self;
}
- (void)adWhirlDidReceiveAd:(AdWhirlView *)adWhirlView {
adView.hidden = NO;
if (self.view.window) {
[UIView beginAnimations:#"AdWhirlDelegate.adWhirlDidReceiveAd:"
context:nil];
[UIView setAnimationDuration:0.7];
CGSize adSize = [adView actualAdSize];
CGRect newFrame = adView.frame;
newFrame.size = adSize;
newFrame.origin.x = (self.view.bounds.size.width - adSize.width)/ 2;
newFrame.origin.y = self.view.bounds.size.height - 50;
adView.frame = newFrame;
[UIView commitAnimations];
}else {
[UIView beginAnimations:#"AdWhirlDelegate.adWhirlDidReceiveAd:"
context:nil];
[UIView setAnimationDuration:0.7];
CGSize adSize = [adView actualAdSize];
CGRect newFrame = adView.frame;
newFrame.size = adSize;
newFrame.origin.x = (self.view.bounds.size.width - adSize.width)/ 2;
//newFrame.origin.y = self.view.bounds.size.height - 50;
adView.frame = newFrame;
[UIView commitAnimations];
}
}
-(void)adWhirlDidFailToReceiveAd:(AdWhirlView *)adWhirlView usingBackup:(BOOL)yesOrNo
{
adView.hidden = YES;
}
Note: The mainScreen controller is the one my app starts with..so it is always resident in memory. This is responsible for pushing the other views on screen. Am I missing something to get this working?
I have an issue with editing table view:
I changed the minus sign location in edit mode to the right side of the cell.
The problem is that the button is sliding from the left and it makes it looks weird.
Is there a way to change this animation?
Also, there is an animation when undoing the delete option (clicking the minus sign when the red delete button is displayed), any idea why?
Here is a video showing the issue:
---edit---
This is how I changed the position:
- (void)layoutSubviews {
[super layoutSubviews];
//Indent to the left instead of right
self.contentView.frame = CGRectMake(0,
self.contentView.frame.origin.y,
self.contentView.frame.size.width,
self.contentView.frame.size.height);
if ((self.editing
&& ((state & UITableViewCellStateShowingEditControlMask)
&& !(state & UITableViewCellStateShowingDeleteConfirmationMask))) ||
((state & UITableViewCellStateShowingEditControlMask)
&& (state & UITableViewCellStateShowingDeleteConfirmationMask)))
{
float indentPoints = self.indentationLevel * self.indentationWidth;
self.contentView.frame = CGRectMake(indentPoints - 35,
self.contentView.frame.origin.y,
self.contentView.frame.size.width - indentPoints,
self.contentView.frame.size.height);
}
//Change editAccessoryView location
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.0f];
//If can't use private classes (UITableViewCellDeleteConfirmationControl..), use [self.subviews objectAtIndex:0];
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 10;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellEditControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 280;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellReorderControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 200;
subview.frame = newFrame;
}
}
[UIView commitAnimations];
}
- (void)willTransitionToState:(UITableViewCellStateMask)aState {
[super willTransitionToState:aState];
self.state = aState;
}
---edit2---
I identified that the part that causes the minus sign jumping issue is the
//Change editAccessoryView location.
Without it there is no jumping but the minus button is back on the left side of the cell.
Any way around that?
Just a guess, but have you tried turning the view upside-down? You might be able to use a UIView transform.
(Code from the Internet, not sure how reliable it is)
CGAffineTransform rotateTransform;
rotateTransform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI);
myView.transform = rotateTransform;