您的位置:首页 > 移动开发 > IOS开发

iOS截屏分享功能实现

2017-05-02 19:28 351 查看
产品经理今天提出一个新的需求,需要实现类似于每日优鲜、淘宝等客户端的截屏分享的功能,即home+power截屏后弹出分享页面,同时将截取到的图片放在当前页面中展示,如下效果:



之前没有做过这样的需求,但是实现过截屏相关的功能,故初步考虑获取系统截屏事件,然后在该事件中利用程序截屏并按一定比例显示在屏幕上,最后在该事件中调用友盟分享的方式实现了。

首先第一步是考虑如何获取系统截屏的事件,查找之后发现苹果在ios7之后提供了一个新的通知类型:UIApplicationUserDidTakeScreenshotNotification,这个通知会告知注册了此通知的对象已经发生了截屏事件,然后我们就可以在这个事件中实现自己的逻辑。

一、注册通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenShot) name:UIApplicationUserDidTakeScreenshotNotification object:nil];


二、实现接收到通知的方法

- (void)screenShot
{
//每次截屏之前,删除之间添加的存放图片的imageView,不然重复截屏会不断的截取到之前的页面
[self.photoIV removeFromSuperview];
self.photoIV = nil;

//截屏, 获取所截图片(imageWithScreenshot在后面实现)
UIImage *image = [self imageWithScreenshot];

//添加显示
UIImageView *photoIV = [[UIImageView alloc]initWithImage:image];
self.photoIV = photoIV;
photoIV.frame = CGRectMake(20, 50, [UIScreen mainScreen].bounds.size.width-40, [UIScreen mainScreen].bounds.size.height-100);

/*为imageView添加边框和阴影,以突出显示*/
//给imageView添加边框
CALayer * layer = [photoIV layer];
layer.borderColor = [[UIColor whiteColor] CGColor];
layer.borderWidth = 5.0f;

//添加四个边阴影
photoIV.layer.shadowColor = [UIColor blackColor].CGColor;
photoIV.layer.shadowOffset = CGSizeMake(0, 0);
photoIV.layer.shadowOpacity = 0.5;
photoIV.layer.shadowRadius = 10.0;
[self.view addSubview:photoIV];
//调用显示分享的页面
[self share];
}


三、截屏方法实现(网上直接找的比较全面的截屏方法,返回一个NSData对象)

- (UIImage *)imageWithScreenshot
{
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation))
imageSize = [UIScreen mainScreen].bounds.size;
else
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);

UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft)
{
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
}
else if (orientation == UIInterfaceOrientationLandscapeRight)
{
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
{
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
}
else
{
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
return [UIImage imageWithData:imageData];
}


补充:最近无意间发现一个更简单快捷的获取屏幕快照的方式:

(nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates

这个方法是苹果在ios7之后为所有的UIView提供的一个新的API,如果使用这个方法来截屏的话就非常简单了,简单一句话搞定

UIView *snapView = [self.someView snapshotViewAfterScreenUpdates:NO];


这个方法的厉害之处还在于它可以截取当前视图中的任意一个view,产生一个view的快照,以此来实现很多效果。

注意到,这个方法有一个参数AfterScreenUpdates,它有什么用呢?官方文档中是这么说的:

当你要快照的时候,’afterUpdates’就确定了你的快照是当前屏幕中正在展示的还是包含那些view最近的改变。

比如下面这个例子:

- (void)layoutSubviews {
UIView *snapshot = [self snapshotViewAfterScreenUpdates:YES];
self.alpha = 0.0;
}


我们得到的结果会是一个空白的view,因为ScreenUpdates设置为YES,它会自动捕获对self的更改,所以我们看到的是 self.alpha = 0.0的view。

但是这种方法截屏后是一个UIView的结果,截屏分享我们自然是分享一张图片,这个时候就用到如何将一个view转成图片了,方法如下:

- (UIImage *)createImageWithView:(UIView *)view
{

CGSize s = view.bounds.size;

//第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了,设置为[UIScreen mainScreen].scale可以保证转成的图片不失真。
UIGraphicsBeginImageContextWithOptions(s, NO,[UIScreen mainScreen].scale);

[view.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage*image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return image;

}


四、分享的方法:

分享我使用的第三方的友盟分享最新版,导入以下头文件

#import <UMSocialCore/UMSocialCore.h>
#import <UShareUI/UShareUI.h>
#import <UMengUShare/WXApi.h>


- (void)share
{
[UMSocialUIManager showShareMenuViewInWindowWithPlatformSelectionBlock:^(UMSocialPlatformType platformType, NSDictionary *userInfo) {
// 根据platformType调用相关平台进行分享
[self shareImageToPlatformType:platformType];
//分享成功之后移除imageView
[self.photoIV removeFromSuperview];
self.photoIV = nil;

}];
//设置ShareMenuView的代理,实现点击取消分享的时候移除imageView
[UMSocialUIManager setShareMenuViewDelegate:self];
}

- (void)shareImageToPlatformType:(UMSocialPlatformType)platformType
{
//创建分享消息对象
UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
UMShareImageObject *shareObject = [[UMShareImageObject alloc] init];
//设置分享的图片
shareObject.shareImage = self.photoIV.image;
//分享消息对象设置分享内容对象
messageObject.shareObject = shareObject;
//调用分享接口
[[UMSocialManager defaultManager] shareToPlatform:platformType messageObject:messageObject currentViewController:self completion:^(id data, NSError *error) {
if (error) {
NSLog(@"************Share fail with error %@*********",error);
}else{
NSLog(@"response data is %@",data);
}
[self.photoIV removeFromSuperview];
self.photoIV = nil;
}];
}
//ShareMenuViewDelegate
- (void)UMSocialShareMenuViewDidDisappear
{
[self.photoIV removeFromSuperview];
self.photoIV = nil;
}


这样就可以实现整个截屏分享的功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: