Follow

Advertising by injecting custom views into Pugpig

This guide describes how to integrate a 3rd party advert (like a Google DFP banner view) into Pugpig. The idea is to inject a view on top of the Pugpig web view on chosen pages. The web view can act as a fallback advert placeholder.

We will use a single banner, and ensure that it's in the appropriate place by moving its position as the user pages through an edition. You could implement this approach using multiple banners; the approach remains exactly the same.

You are responsible for managing the banner views, ensuring they are the right size and ready for display.

For the purposes of this example, let's assume the the page control is being driven by a datasource with 10 pages. You want an advert on page 5 and page 7.

Inject the banner view into the page control's scrollable area

We'll assume you have created a banner view property on your DocumentViewController. The banner view is fixed size here, but you'd probably want something that tracks the size of the device. Notice that the ad is placed off-screen until we're ready to place it.

iOS:

@property (nonatomic, retain) UIView *bannerView;
...
- (void)viewDidLoad {
... CGRect f = CGRectMake(-768, 0, 768, 1024); bannerView.frame = f; [self.pageControl.subviews[0] addSubview:self.bannerView];

Android:

private View bannerView;
...
public void viewDidLoad {
  ...
  ViewGroup scrollContentView = (ViewGroup)pageControl.getChildAt(0);
  scrollContentView.addView(bannerView, 0);
  AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams(768, 1024, -768, 0);
  bannerView.setLayoutParams(lp);
bannerView.layout(lp.x, lp.y, lp.x+lp.width, lp.y+lp.height);

Track when web page is displayed in order to ensure the banner view is visible

Pugpig presents the web view once the page has loaded and is ready for interaction. This includes moving it to the top of the z-order. We want to override this behaviour when appropriate, ensuring that our banner view is at the top. This is possibly by observing the SnapshotFinished event; if you're already doing so you can just extend your observer.

iOS:

[pageControl addTarget:self action:@selector(webViewReady:) forControlEvents:(UIControlEvents)KGControlEventContentSnapshotFinished];
...
- (void)webViewReady:(UIWebView *)webView {
  if (self.pageControl.pageNumber == 5 || self.pageControl.pageNumber == 7) {
    [self.bannerView.superview bringSubviewToFront:self.bannerView];
  }
}

Android:

pageControl.addActionForControlEvents(this, "webViewReady", ControlEvents.ContentSnapshotFinished);
  ..
public void webViewReady(WebView *webView) {
  if (pageControl.pageNumber() == 5 || pageControl.pageNumber() == 7) {
    webView.setVisibility(View.INVISIBLE);
    bannerView.bringToFront();
    bannerView.invalidate();
  }
}

Track page control movement, and use the information to place the banner view

We must insure that the banner is showing in the right place. This is accomplished by observing the page control's fractionalPageNumber, and changing the x-offset of the banner view if it's about to become visible but it's not in the right place.

iOS (Android would be a direct port)

  [pageControl addObserver:self forKeyPath:@"fractionalPageNumber" options:NSKeyValueObservingOptionNew context:nil];
...
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  ...
  if ([keyPath isEqualToString:@"fractionalPageNumber"]) {
    NSArray *adPages = @[ @5, @7 ];
    for (NSNumber *n in adPages) {
      CGFloat lowerPos = [n intValue] - 1;
      CGFloat upperPos = [n intValue] + 1;
      if (pageControl.fractionalPageNumber >= lowerPos && pageControl.fractionalPageNumber < upperPos) {
        // if fractionalPage is "near" an ad page, make sure the banner is in the correct place
        CGRect fr = bannerView.frame;
        if ((int)fr.origin.x != [n intValue]*pageControl.bounds.size.width) {
          fr.origin.x = [n intValue]*pageControl.bounds.size.width;
          bannerView.frame = fr;
        }
      }
    }
  }
}

Don't forget to remove any observers your create when your DocumentViewController goes out of scope.

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

Powered by Zendesk