分分钟解决iOS开发中App启动广告的功能
前不久有朋友需要一个启动广告的功能,我说网上有挺多的,他说,看的不是很理想。想让我写一个,于是乎,抽空写了一个,代码通俗易懂,简单的封装了一下,各种事件用block回调的,有俩种样式的广告,一种是全屏广告,另一种是下面露logo的,类似网页新闻的启动广告。依赖SDWebImage主要用来下载网络的广告图片,一般项目里面网络图片都用的这个框架,所以在此不做过多的阐述。下面让我们来看看我封装的过程,对于新手来说,可以学习一下这种封装的思想。
1.首先建一个继承View的LBLaunchImageAdView
.H文件 代码如下:
//
// LBLaunchImageAdView.h
// LBLaunchImageAd
// 技术交流群:534926022(免费) 511040024(0.8/人付费)
// Created by gold on 16/6/8.
// Copyright © 2016年 Bison. All rights reserved.
// iOS开发学习app下载https://itunes.apple.com/cn/app/it-blog-for-ios-developers/id1067787090?mt=8
typedef enum {
FullScreenAdType = 1,//全屏的广告
LogoAdType = 0,//带logo的广告
}AdType;
#import <UIKit/UIKit.h>
#import "UIImageView+WebCache.h"
#define mainHeight [[UIScreen mainScreen] bounds].size.height
#define mainWidth [[UIScreen mainScreen] bounds].size.width
typedef void (^LBClick) (NSInteger tag);
@interface LBLaunchImageAdView : UIView
@property (strong, nonatomic) UIImageView *aDImgView;
@property (strong, nonatomic) UIWindow *window;
@property (assign, nonatomic) NSInteger adTime; //倒计时总时长,默认6秒
@property (strong, nonatomic) UIButton *skipBtn;
@property (nonatomic, copy)LBClick clickBlock;
- (instancetype)initWithWindow:(UIWindow *)window andType:(NSInteger)type andImgUrl:(NSString *)url;
@end
里面主要重写了init方法,init方法方便我们在调用封装的类初始化时传递一些参数,在此,我只传递了三个必要的参数,其他参数都用@property属性来调配,达到自己想要的效果,再有就是一个block的回调函数,主要处理各种事件。下面我们看看.m文件里面实现的部分
//
// LBLaunchImageAdView.m
// LBLaunchImageAd
// 技术交流群:534926022(免费) 511040024(0.8/人付费)
// Created by gold on 16/6/8.
// Copyright © 2016年 Bison. All rights reserved.
// iOS开发学习app下载https://itunes.apple.com/cn/app/it-blog-for-ios-developers/id1067787090?mt=8
#import "LBLaunchImageAdView.h"
@interface LBLaunchImageAdView()
{
NSTimer *countDownTimer;
}
@property (strong, nonatomic) NSString *isClick;
@property (assign, nonatomic) NSInteger secondsCountDown; //倒计时总时长
@end
@implementation LBLaunchImageAdView
- (instancetype)initWithWindow:(UIWindow *)window andType:(NSInteger)type andImgUrl:(NSString *)url
{
self = [super init];
if (self) {
self.window = window;
_secondsCountDown = 0;
[window makeKeyAndVisible];
//获取启动图片
CGSize viewSize = window.bounds.size;
//横屏请设置成 @"Landscape"
NSString *viewOrientation = @"Portrait";
NSString *launchImageName = nil;
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"]])
{
launchImageName = dict[@"UILaunchImageName"];
}
}
UIImage * launchImage = [UIImage imageNamed:launchImageName];
self.backgroundColor = [UIColor colorWithPatternImage:launchImage];
self.frame = CGRectMake(0, 0, mainWidth, mainHeight);
if (type == FullScreenAdType) {
self.aDImgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, mainWidth, mainHeight)];
}else{
self.aDImgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, mainWidth, mainHeight - mainWidth/3)];
}
self.skipBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.skipBtn.frame = CGRectMake(mainWidth - 70, 20, 60, 30);
self.skipBtn.backgroundColor = [UIColor brownColor];
self.skipBtn.titleLabel.font = [UIFont systemFontOfSize:14];
[self.skipBtn addTarget:self action:@selector(skipBtnClick) forControlEvents:UIControlEventTouchUpInside];
[self.aDImgView addSubview:self.skipBtn];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.skipBtn.bounds byRoundingCorners:UIRectCornerBottomRight | UIRectCornerTopRight cornerRadii:CGSizeMake(15, 15)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.skipBtn.bounds;
maskLayer.path = maskPath.CGPath;
self.skipBtn.layer.mask = maskLayer;
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) {
[self.aDImgView setImage:[self imageCompressForWidth:image targetWidth:mainWidth]];
}
}];
self.aDImgView.tag = 1101;
self.aDImgView.backgroundColor = [UIColor redColor];
[self addSubview:self.aDImgView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(activiTap:)];
// 允许用户交互
self.aDImgView.userInteractionEnabled = YES;
[self.aDImgView addGestureRecognizer:tap];
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.duration = 0.8;
opacityAnimation.fromValue = [NSNumber numberWithFloat:0.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.8];
opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.aDImgView.layer addAnimation:opacityAnimation forKey:@"animateOpacity"];
countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
[self.window addSubview:self];
}
return self;
}
#pragma mark - 点击广告
- (void)activiTap:(UITapGestureRecognizer*)recognizer{
_isClick = @"1";
[self startcloseAnimation];
}
#pragma mark - 开启关闭动画
- (void)startcloseAnimation{
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.duration = 0.5;
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.3];
opacityAnimation.removedOnCompletion = NO;
opacityAnimation.fillMode = kCAFillModeForwards;
[self.aDImgView.layer addAnimation:opacityAnimation forKey:@"animateOpacity"];
[NSTimer scheduledTimerWithTimeInterval:opacityAnimation.duration
target:self
selector:@selector(closeAddImgAnimation)
userInfo:nil
repeats:NO];
}
- (void)skipBtnClick{
_isClick = @"2";
[self startcloseAnimation];
}
#pragma mark - 关闭动画完成时处理事件
-(void)closeAddImgAnimation
{
[countDownTimer invalidate];
countDownTimer = nil;
self.hidden = YES;
self.aDImgView.hidden = YES;
self.hidden = YES;
if ([_isClick integerValue] == 1) {
if (self.clickBlock) {//点击广告
self.clickBlock(1100);
}
}else if([_isClick integerValue] == 2){
if (self.clickBlock) {//点击跳过
self.clickBlock(1101);
}
}else{
if (self.clickBlock) {//点击跳过
self.clickBlock(1102);
}
}
}
- (void)onTimer {
if (_adTime == 0) {
_adTime = 6;
}
if (_secondsCountDown < _adTime) {
_secondsCountDown++;
[self.skipBtn setTitle:[NSString stringWithFormat:@"%ld | 跳过",_secondsCountDown] forState:UIControlStateNormal];
}else{
[countDownTimer invalidate];
countDownTimer = nil;
[self startcloseAnimation];
}
}
#pragma mark - 指定宽度按比例缩放
- (UIImage *)imageCompressForWidth:(UIImage *)sourceImage targetWidth:(CGFloat)defineWidth {
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = defineWidth;
CGFloat targetHeight = height / (width / targetWidth);
CGSize size = CGSizeMake(targetWidth, targetHeight);
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
if(CGSizeEqualToSize(imageSize, size) == NO){
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if(widthFactor > heightFactor){
scaleFactor = widthFactor;
}
else{
scaleFactor = heightFactor;
}
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
if(widthFactor > heightFactor){
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}else if(widthFactor < heightFactor){
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
// UIGraphicsBeginImageContext(size);
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil){
NSLog(@"scale image fail");
}
UIGraphicsEndImageContext();
return newImage;
}
@end
UI部分由于没有什么需要重用的地方,所以没有再另外抽取出来方法,全部放在init方法里面,显得有点臃肿。UI部分在此不做过多的阐述,里边主要运用了一个渐变的动画,利用CABasicAnimation中的opacity,有兴趣的朋友可以看看源码, 再有就是一个图片重构的方法,防止图片变形。
下面我们说下怎么集成我封装的这个功能吧,挺简单的,首先来看看代码:
首先在AppDelegate.m导入头文件#import “LBLaunchImageAdView.h”,然后在didFinishLaunchingWithOptions方法里面初始化一下,最后就是一些点击的回调事件了。到此,讲解完毕,最后丢上效果图和下载地址。
动图
下载地址
https://github.com/AllLuckly/LBLaunchImageAd
分分钟解决iOS开发中App启动广告的功能的更多相关文章
- ios开发中APP底部上滑不能调出如WiFi、蓝牙、播放等的设置页面的解决的方法
在开发的APP中我们通常通过手动底部上滑来调出WiFi.蓝牙.飞行模式等的设置页面.有时我们开发的APP无法调出. 解决的方法: 进入iPhone "设置" --> &quo ...
- ios UIApplocation 中APP启动方式
iOS app启动的方式有哪些: 自己启动(用户手动点击启动) urlscheme启动(关于urlScheme的详解)http://www.cnblogs.com/sunfuyou/p/6183064 ...
- iOS开发-测量APP启动耗时
冷启动 冷启动就是App被kill掉以后一切从头开始启动的过程. 热启动 当用户按下home键的时候,iOS的App并不会马上被kill掉,还会继续存活若干时间.理想情况下,用户点击App的图标再次回 ...
- 解决ios开发中不合法的网络请求地址
NSString *const kWebsite = @"http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct ...
- IOS开发中如何判断程序第一次启动(根据判断结果决定是否显示新手操作引导)
IOS开发中如何判断程序第一次启动 在软件下载安装完成后,第一次启动往往需要显示一个新手操作引导,来告诉用户怎么操作这个app,这就需要在程序一开始运行就判断程序是否第一次启动,如果是,则显示新手操作 ...
- IOS 开发中 Whose view is not in the window hierarchy 错误的解决办法
在 IOS 开发当中经常碰到 whose view is not in the window hierarchy 的错误,该错误简单的说,是由于 "ViewController" ...
- iOS开发中常见问题集锦
在iOS开发中,会出现各种各样的问题.今天,就把这些常见的问题以及各位大牛的解决方案汇总下,方便以后查阅: 常见错误: 1. linker command failed with exit code ...
- iOS开发中遇到的一些问题及解决方案【转载】
iOS开发中遇到的一些问题及解决方案[转载] 2015-12-29 [385][scrollView不接受点击事件,是因为事件传递失败] // // MyScrollView.m // Creat ...
- 总结iOS开发中的断点续传那些事儿
前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...
随机推荐
- SQL操作(增删改查)
1.一些重要的SQL命令: SELECT - 从数据库中提取数据UPDATE - 更新数据库中的数据DELETE - 从数据库中删除数据INSERT INTO - 向数据库中插入新数据CREATE D ...
- Hibernate 多对一关系中,在多的一方进行数据的插入
先看两个映射关系: 部门: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//H ...
- UCS-2和UTF8的四个新知识点和新的疑问
最初的unicode编码是固定长度的,16位,也就是2两个字节代表一个字符,这样一共可以表示65536个字符.显然,这样要表示各种语言中所有的字符是远远不够的.Unicode4.0规范考虑到了这种情况 ...
- Android Gson使用笔记
最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson,因为之前对于protoco ...
- 查看本机上的端口使用情况netstat -an
1.查找本机上的端口使用情况 netstat -an 2.查找指定端口的使用情况 C:\Windows\System32>netstat -ano | find "8002" ...
- TC598 div2
题意:给一些物品item[],这些物品的重量在101至300之间,要将这些物品全部放进若干个bins中,已知bins盛的重量为300,可以将bins装满也可以不装满, 问放这些物品最少需要几个bins ...
- bzoj1072
还是那句话s<=10 必然想到状压 题目唯一的难点在于怎么转移整除 整除即是mod d=0,我们用f[cur,j]表示选取状况为cur,余数为j的方案数 注意一个数a1a2a3…an (ai表示 ...
- bzoj2342
shoi题目好坑爹 首先自己测发现这道题如果用后缀数组+rmq处理每个点回文串能延伸长度的话会TLE (当然我用的是倍增+ST的方法,如果用三分构建后缀数组+笛卡尔树处理rmq我就不知道了): 关于最 ...
- BZOJ2038小Z的袜子(hose)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 2343 Solved: 1077[Subm ...
- python指定pypi的源地址 镜像地址
python pip源介绍: python装包一般都用easy_install 或者pip. 他们俩的原理跟apt-get差不多,都是去某个地址去下载你所指定的包. pip和easy_install默 ...