做這個(gè)東西的話松捉,其實(shí)主要是因?yàn)橐患律視?huì)比較經(jīng)常食用手機(jī)迅雷下載電影戈次,每次開啟迅雷,都會(huì)默認(rèn)來(lái)一段廣告筒扒,這種強(qiáng)制的讓使用者看廣告的行為雖然讓人很討厭怯邪,但是本著好奇就認(rèn)真挖掘的原則,看了一下網(wǎng)上的介紹花墩,再自己實(shí)踐了一下悬秉。
1, AppDelegate,入口冰蘑,處理不同的回調(diào)和泌,比如現(xiàn)在定義的三種不同結(jié)果,一是廣告時(shí)間耗盡祠肥,未點(diǎn)擊廣告武氓,也未點(diǎn)擊跳過(guò)廣告按鈕了;二是點(diǎn)擊廣告仇箱;三是點(diǎn)擊跳過(guò)按鈕聋丝,程序中只是簡(jiǎn)單的根據(jù)不同的事件定義了不同的回調(diào),并未繼續(xù)做進(jìn)一步的處理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
/*
簡(jiǎn)書主頁(yè):http://www.reibang.com/users/1bacae3170dd/latest_articles
*/
/*添加廣告
1.初始化工碾,選擇屏占比
2.設(shè)置廣告總時(shí)長(zhǎng)弱睦,可跳過(guò),默認(rèn)是6秒
3.啟動(dòng)計(jì)時(shí)器
*/
// MCLaunchAdView* view = [[MCLaunchAdView alloc] initWithWindow:self.window with:MCAdViewTypeFullScreen];
// MCLaunchAdView* view = [[MCLaunchAdView alloc] initWithWindow:self.window with:MCAdViewTypeHalfScreen];
// MCLaunchAdView* view = [[MCLaunchAdView alloc] initWithWindow:self.window with:MCAdViewTypeThreeQuarters];
MCLaunchAdView* view = [[MCLaunchAdView alloc] initWithWindow:self.window with:MCAdViewTypeFiveSixths];
//顯示本地圖片
// view.localImageName = @"adImage_lion.png";
//顯示網(wǎng)絡(luò)圖片
view.imageURL = @"http://imgsrc.baidu.com/forum/pic/item/65c1a9cc7b899e51371108904aa7d933c9950d56.jpg";
// http://imgsrc.baidu.com/forum/pic/item/65c1a9cc7b899e51371108904aa7d933c9950d56.jpg
[view setTimer:6];
[view startTimer];
view.clickBlock = ^(MCQuitLaunchAdStyle tag){
MCQuitLaunchAdStyle style = MCQuitLaunchAdStyleDefault;
switch (tag) {
case MCQuitLaunchAdStyleTimeOut:{
NSLog(@"%@",NSLocalizedString(@"時(shí)間耗盡", nil));
style = MCQuitLaunchAdStyleTimeOut;
}
break;
case MCQuitLaunchAdStyleSkip:{
NSLog(@"%@",NSLocalizedString(@"跳過(guò)廣告", nil));
style = MCQuitLaunchAdStyleSkip;
}
break;
case MCQuitLaunchAdStyleJumpToURL:{
NSLog(@"%@",NSLocalizedString(@"進(jìn)入廣告", nil));
style = MCQuitLaunchAdStyleJumpToURL;
}
break;
default:{
NSLog(@"%@",NSLocalizedString(@"未知原因", nil));
style = MCQuitLaunchAdStyleDefault;
}
break;
}
ViewController* vc = [[ViewController alloc] initWithLaunchStyle:style];
vc.view.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:vc];
};
//打印mainbundle
NSDictionary* dict = [[NSBundle mainBundle] infoDictionary];
NSLog(@"%@",dict);
//
return YES;
}
2, MCLaunchAdView渊额,主要UI况木,顯示在App上的啟動(dòng)頁(yè),可以看到的東西旬迹,都是在這里面
MCLaunchAdView.h
#import <UIKit/UIKit.h>
/*廣告顯示屏幕占比類型火惊,對(duì)應(yīng)的NSUInteger竟然選擇有意義一點(diǎn)的*/
typedef NS_ENUM(NSUInteger, MCAdViewType) {
MCAdViewTypeFullScreen = 1,//全屏
MCAdViewTypeHalfScreen = 2,//半屏
MCAdViewTypeThreeQuarters = 4,//四分之三屏
MCAdViewTypeFiveSixths = 6,//六分之五屏
};
/*廣告結(jié)束的方式*/
typedef NS_ENUM(NSUInteger, MCQuitLaunchAdStyle) {
MCQuitLaunchAdStyleDefault = 0,
MCQuitLaunchAdStyleTimeOut,//時(shí)間耗盡
MCQuitLaunchAdStyleSkip,//跳過(guò)廣告
MCQuitLaunchAdStyleJumpToURL,//進(jìn)入廣告
};
/*塊回調(diào),廣告結(jié)束后根據(jù)不同的結(jié)束方式處理下一步*/
typedef void (^MCClick) (MCQuitLaunchAdStyle tag);
/*廣告*/
#pragma mark - MCLaunchAdView
@interface MCLaunchAdView : UIView
@property (nonatomic, strong) UIWindow* window;
@property (nonatomic, strong) NSString* localImageName;//本地圖片名
@property (nonatomic, strong) NSString* imageURL;//網(wǎng)絡(luò)圖片名
@property (nonatomic, copy) MCClick clickBlock;//塊回調(diào)奔垦,處理不同的操作
-(instancetype)initWithWindow:(UIWindow*)window with:(MCAdViewType)type;
-(void)setTimer:(NSInteger)time;
-(void)startTimer;
@end
MCLaunchAdView.m
//
// MCLaunchAdView.m
// MCLaunchAd
//
// Created by 朱進(jìn)林 on 9/16/16.
// Copyright ? 2016 Martin Choo. All rights reserved.
//
#import "MCLaunchAdView.h"
#import "MCCountingButton.h"
#import "UIImageView+WebCache.h"
#define screenWidth [UIScreen mainScreen].bounds.size.width
#define screenHeight [UIScreen mainScreen].bounds.size.height
#define TIMER_INTERVAL 0.04 //25幀每秒
#define SKIPBUTTONSIZE 30
#pragma mark - MCLaunchAdView
@interface MCLaunchAdView()
{
MCCountingButton* _countingBtn;//跳過(guò)廣告按鈕
}
@property (nonatomic) MCAdViewType adViewtype;
@property (nonatomic, strong) UIImageView* adView;/*廣告界面*/
@property (nonatomic) NSInteger adTime;//廣告時(shí)長(zhǎng)屹耐,默認(rèn)6秒
@property (nonatomic) CGFloat adTimeLeft;/*剩余時(shí)間,用于計(jì)算時(shí)間是否耗盡*/
@property (nonatomic, strong) NSTimer* countTimer;/*計(jì)時(shí)器*/
@end
@implementation MCLaunchAdView
/*初始化*/
-(instancetype)initWithWindow:(UIWindow*)window with:(MCAdViewType)type
{
self = [super init];
if (self) {
//
self.window = window;
[window makeKeyAndVisible];
self.adViewtype = type;
self.adTime = 6;//默認(rèn)6秒
self.adTimeLeft = self.adTime;
[self initailView];
[self.window addSubview:self];
}
return self;
}
-(void)initailView
{
//廣告界面
{
UIImageView* imgView = [[UIImageView alloc] init];
imgView.contentMode = UIViewContentModeScaleToFill;//因?yàn)閳D片不一定鋪滿整個(gè)屏幕椿猎,所以這里暫時(shí)做了拉伸
[self addSubview:imgView];
self.adView = imgView;
}
//跳過(guò)按鈕
{
MCCountingButton* countingBtn = [[MCCountingButton alloc] initWithFrame:CGRectMake(0, 0, SKIPBUTTONSIZE, SKIPBUTTONSIZE)];
[countingBtn addTarget:self action:@selector(skipButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.adView addSubview:countingBtn];
_countingBtn = countingBtn;
}
}
-(void)layoutSubviews
{
self.frame = CGRectMake(0, 0, screenWidth, screenHeight);
//設(shè)置啟動(dòng)界面的背景惶岭,顯示logo
NSString* imgName = [self getBestLaunchImage];
UIImage* img = [UIImage imageNamed:imgName];
self.layer.contents = (id)img.CGImage;
//根據(jù)不同的廣告占屏比設(shè)置不同的布局
if (self.adViewtype == MCAdViewTypeFullScreen) {
self.adView.bounds = CGRectMake(0, 0, screenWidth, screenHeight);
}else if (self.adViewtype == MCAdViewTypeHalfScreen) {
self.adView.bounds = CGRectMake(0, 0, screenWidth, 2*screenHeight/3);
}else if (self.adViewtype == MCAdViewTypeThreeQuarters) {
self.adView.bounds = CGRectMake(0, 0, screenWidth, 3*screenHeight/4);
}else if (self.adViewtype == MCAdViewTypeFiveSixths) {
self.adView.bounds = CGRectMake(0, 0, screenWidth, 5*screenHeight/6);
}else {
self.adView.bounds = CGRectMake(0, 0, screenWidth, screenHeight);
}
self.adView.center = CGPointMake(screenWidth/2, self.adView.bounds.size.height/2);
//跳過(guò)按鈕的布局
_countingBtn.center = CGPointMake(screenWidth-SKIPBUTTONSIZE/2-5, SKIPBUTTONSIZE/2+20);
_countingBtn.tickTockInterval = TIMER_INTERVAL*1000;//設(shè)置計(jì)時(shí)間隔
_countingBtn.totalTime = self.adTime;//設(shè)置總時(shí)長(zhǎng)
}
/*設(shè)置計(jì)時(shí)器時(shí)長(zhǎng)寿弱,不調(diào)用這個(gè)方法,就使用計(jì)時(shí)器默認(rèn)的6秒*/
-(void)setTimer:(NSInteger)time
{
self.adTime = time;
self.adTimeLeft = time;
}
/*啟動(dòng)計(jì)時(shí)器*/
-(void)startTimer
{
//添加計(jì)時(shí)器
self.countTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(TickTock) userInfo:nil repeats:YES];
}
/*關(guān)閉計(jì)時(shí)器*/
-(void)closeTimer
{
//關(guān)閉
if (self.countTimer) {
[self.countTimer invalidate];
self.countTimer = nil;
}
}
#pragma mark - Action
/*過(guò)了一個(gè)計(jì)時(shí)單位TIMER_INTERVAL按灶,檢查剩余時(shí)間*/
-(void)TickTock
{
if (self.adTimeLeft > 0) {
//默認(rèn)6秒症革,時(shí)間未耗盡,繼續(xù)展示
self.adTimeLeft = self.adTimeLeft - TIMER_INTERVAL;
[_countingBtn counting];
}else {
//默認(rèn)6秒鸯旁,時(shí)間耗盡
[self closeTimer];
if (self.clickBlock) {
self.clickBlock(MCQuitLaunchAdStyleTimeOut);
}
}
}
/*響應(yīng)點(diǎn)擊跳過(guò)按鈕事件*/
-(void)skipButtonClicked:(UIButton*)btn
{
[self closeTimer];
if (self.clickBlock) {
self.clickBlock(MCQuitLaunchAdStyleSkip);
}
}
/*響應(yīng)點(diǎn)擊廣告事件*/
-(void)jumpToURL:(UITapGestureRecognizer*)recognizer
{
[self closeTimer];
if (self.clickBlock) {
self.clickBlock(MCQuitLaunchAdStyleJumpToURL);
}
}
#pragma mark - 獲取最佳啟動(dòng)圖
/*獲取最佳啟動(dòng)圖噪矛,根據(jù)硬件設(shè)備分辨率,從info.plist中獲取圖片名铺罢,需要在plist中添加相關(guān)的圖片信息艇挨,從而適配不同尺寸的設(shè)備*/
-(NSString*)getBestLaunchImage
{
NSString* launchImage = nil;
CGSize viewSize = [UIScreen mainScreen].bounds.size;
NSString* viewOrientation = @"Portrait";//如需設(shè)置橫屏,請(qǐng)修改為L(zhǎng)andscape,對(duì)應(yīng)的viewSize也要切換一下
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
viewSize = CGSizeMake(viewSize.height, viewSize.width);
viewOrientation = @"Landscape";
}
//比較設(shè)備分辨率和圖片尺寸韭赘,取得匹配的圖片名
NSArray* imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for (NSDictionary* dict in imagesDict) {
CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]);
if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]])
//這邊會(huì)有問(wèn)題缩滨,因?yàn)槠聊徽急炔灰欢ㄈ粒赃@邊其實(shí)還要進(jìn)一步截取屏幕的大小辞居,但是這邊我省略了楷怒,外部在調(diào)用的時(shí)候我做了拉伸的處理
launchImage = dict[@"UILaunchImageName"];
}
//沒(méi)有匹配的圖片,取默認(rèn)的圖片名
if (!launchImage) {
launchImage = @"LaunchImageIconLogo_930.png";
}
return launchImage;
}
#pragma mark -
/*重寫setter方法瓦灶,支持GIF圖的顯示*/
-(void)setLocalImageName:(NSString *)localImageName
{
_localImageName = localImageName;
if (_localImageName) {
if ([[_localImageName uppercaseString] rangeOfString:@".GIF"].location != NSNotFound) {
_localImageName = [_localImageName stringByReplacingCharactersInRange:[[_localImageName uppercaseString] rangeOfString:@".GIF"] withString:@""];
NSData* gifData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:_localImageName ofType:@"gif"]];
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.adView.frame];
webView.backgroundColor = [UIColor clearColor];
webView.scalesPageToFit = YES;
[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:@"" baseURL:[NSURL URLWithString:@""]];
[self.adView addSubview:webView];
[self.adView bringSubviewToFront:_countingBtn];
}else {
self.adView.image = [UIImage imageNamed:_localImageName];
}
//添加點(diǎn)擊廣告監(jiān)聽,在此處添加鸠删,避免沒(méi)有圖片時(shí)點(diǎn)擊區(qū)域依然跳轉(zhuǎn)的發(fā)生
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jumpToURL:)];
self.adView.userInteractionEnabled = YES;
[self.adView addGestureRecognizer:tap];
}
}
-(void)setImageURL:(NSString *)imageURL
{
_imageURL = imageURL;
if (_imageURL) {
SDWebImageManager* manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:[NSURL URLWithString:_imageURL] options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"receivedSize:%ld, expectedSize:%ld",receivedSize,expectedSize);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) {
self.adView.image = image;
//添加點(diǎn)擊廣告監(jiān)聽,在此處添加,避免沒(méi)有圖片時(shí)點(diǎn)擊區(qū)域依然跳轉(zhuǎn)的發(fā)生
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jumpToURL:)];
self.adView.userInteractionEnabled = YES;
[self.adView addGestureRecognizer:tap];
}
}];
}
}
@end
3, MCCountingButton贼陶,倒計(jì)時(shí)按鈕刃泡,也就是跳過(guò)廣告按鈕,這邊是依照設(shè)置的倒計(jì)時(shí)總時(shí)長(zhǎng)畫個(gè)圓環(huán)碉怔,可以擴(kuò)展一下烘贴,加上一些其它的動(dòng)畫,比如廣告圖下面加進(jìn)度條撮胧,顯示讀秒的跳過(guò)按鈕桨踪,模仿水位上升的倒計(jì)時(shí)等,這些實(shí)現(xiàn)起來(lái)原來(lái)都是相似的芹啥,可以簡(jiǎn)單的設(shè)置一個(gè)定時(shí)器锻离,固定時(shí)間間隔后更新界面,再靈活的使用一下UIBezierPath和CAShapeLayer墓怀,即可得到自己想要的
MCCountingButton.h
#import <UIKit/UIKit.h>
/** 帶倒計(jì)時(shí)的跳過(guò)按鈕
* 初始化后需設(shè)置總時(shí)長(zhǎng)和間隔時(shí)間
*/
@interface MCCountingButton : UIButton
@property (nonatomic) NSInteger totalTime;//總時(shí)長(zhǎng)汽纠,單位秒
@property (nonatomic) NSInteger tickTockInterval;//計(jì)時(shí)間隔單位,表示兩次計(jì)數(shù)間的時(shí)間間隔傀履,單位毫秒
-(instancetype)initWithFrame:(CGRect)frame;
/**
* 改變進(jìn)度條末端位置虱朵,循環(huán)調(diào)用實(shí)現(xiàn)進(jìn)度條刷新
*/
-(void)counting;
@end
MCCountingButton.m
//
// MCCountingView.m
// MCLaunchAd
//
// Created by 朱進(jìn)林 on 9/19/16.
// Copyright ? 2016 Martin Choo. All rights reserved.
//
#import "MCCountingButton.h"
#pragma mark - MCCountingButton
@interface MCCountingButton()
@property (nonatomic, strong) UIBezierPath* path;
@property (nonatomic, strong) CAShapeLayer* backgroundShapeLayer;
@property (nonatomic, strong) CAShapeLayer* shapeLayer;
@end
@implementation MCCountingButton
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//
self.totalTime = 6;//默認(rèn)總時(shí)長(zhǎng)6秒
self.tickTockInterval = 40;//默認(rèn)25下每秒
[self initialView];
}
return self;
}
-(void)initialView
{
//設(shè)置路徑
self.path = [UIBezierPath bezierPathWithOvalInRect:self.bounds];
//灰色底層
self.backgroundShapeLayer = [CAShapeLayer layer];
self.backgroundShapeLayer.frame = self.bounds;
self.backgroundShapeLayer.fillColor = [UIColor clearColor].CGColor;
self.backgroundShapeLayer.lineWidth = 2.0f;
self.backgroundShapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;
self.backgroundShapeLayer.strokeStart = 0.f;
self.backgroundShapeLayer.strokeEnd = 1.f;
self.backgroundShapeLayer.path = self.path.CGPath;
[self.layer addSublayer:self.backgroundShapeLayer];
//環(huán)形進(jìn)度條,起始點(diǎn)=終結(jié)點(diǎn)=0,所以初始化時(shí)不可見(jiàn)
self.shapeLayer = [CAShapeLayer layer];
self.shapeLayer.frame = self.bounds;
self.shapeLayer.fillColor = [UIColor clearColor].CGColor;
self.shapeLayer.lineWidth = 2.0f;
self.shapeLayer.lineCap = kCALineCapRound;
self.shapeLayer.strokeColor = [UIColor colorWithRed:30.0/255.0 green:144.0/255.0 blue:255.0/255.0 alpha:1.0].CGColor;
self.shapeLayer.strokeStart = 0.0f;
//通過(guò)不斷修改stroEnd的值碴犬,使形成像動(dòng)畫刷新的效果絮宁,也可以使用CAAnimation的方式,動(dòng)畫的顯示出來(lái)翅敌,duration設(shè)置為你廣告總時(shí)長(zhǎng)就可以
self.shapeLayer.strokeEnd = 0.0f;
self.shapeLayer.path = self.path.CGPath;
[self.layer addSublayer:self.shapeLayer];
//修正坐標(biāo)軸羞福,逆時(shí)針旋轉(zhuǎn)90度惕蹄,從12點(diǎn)鐘開始倒計(jì)時(shí)
self.shapeLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI / 2, 0, 0, -1);
//
[self setTitle:NSLocalizedString(@"跳過(guò)", nil) forState:UIControlStateNormal];
[self setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:10.0];
}
/*改變進(jìn)度條末端位置蚯涮,循環(huán)調(diào)用實(shí)現(xiàn)進(jìn)度條刷新*/
-(void)counting
{
//strokeEnd的取值范圍是0.0到1.0,所以超出1.0時(shí)截取
CGFloat unit = self.tickTockInterval/(self.totalTime*1000.0);
CGFloat f = self.shapeLayer.strokeEnd+unit;
if (f > 1.0) {
self.shapeLayer.strokeEnd = 1.0f;
}else {
self.shapeLayer.strokeEnd = f;
}
}
@end