手機截圖直接分享&反饋
阿新 • • 發佈:2018-12-29
前言
目前市面上的一些主流App,比如:京東、淘寶、支付寶 等,他們都含所有手機截圖分享或者反饋的功能。它們實現這個功能的作用到底為了什麼?個人感覺是:為了滿足App的應用需求,同時更重要的是使用者不用在點選手機的【Home】鍵返回到主頁,再開啟WeChat、QQ、Sina等App在找到我們擷取的圖片在進行反饋和分享。那麼這個功能怎麼實現呢?請您往下看……
一 、題為手機截圖,那怎麼知道手機截圖了呢?
首先這也是我們要首先介紹的一個重要功能。在我們的 UIKit 裡面的 UIApplication.h 中有一個通知的Key。該通知如下:
// This notification is posted after the user takes a screenshot (for example by pressing both the home and lock screen buttons)
UIKIT_EXTERN NSNotificationName const UIApplicationUserDidTakeScreenshotNotification NS_AVAILABLE_IOS(7_0);
通過上面方法的說明可以知道當我們同時按住 Home 和 鎖屏鍵系統就會觸發該通知。那麼為了能夠在整個App中都能實現觸發該通知,我們就在 App 的 AppDelegate.h
**/**!
新增截圖事件的觀察者
*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenshotsEventMethod) name:UIApplicationUserDidTakeScreenshotNotification object:nil];**
二、我們已經知道使用者觸發了截圖,那麼截圖功能怎麼實現呢?
1、我們首先建立一個大小都為 0 的 CGSize 例項。程式碼如下:
CGSize imageSize = CGSizeZero ;
2、首先截圖我們要知道當前使用者的手機是處於那種方向(豎屏&橫屏),並確定截圖的影象 CGSize 的大小。程式碼如下:
/**
確定當前螢幕的方向
*/
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);
}
3、我們通過 CGSize 開啟影象的上下文,在有影象的 View 獲得 CGContextRef 上下文。程式碼如下:
/**
開啟影象上下文,並設定上下文
*/
UIGraphicsBeginImageContext(imageSize);
/**
獲得上下文
*/
CGContextRef cContext = UIGraphicsGetCurrentContext() ;
4、通過遍歷 App檢視顯示當前的所有視窗,來獲取擷取的影象。關鍵程式碼如下:
for (UIWindow * tempWindow in [UIApplication sharedApplication].windows) {
/**
先儲存上下文,便於恢復場景
*/
CGContextSaveGState(cContext) ;
/**
調整上下文的位置
*/
CGContextTranslateCTM(cContext, tempWindow.center.x, tempWindow.center.y) ;
/**
生成仿射矩陣
*/
CGContextConcatCTM(cContext, tempWindow.transform) ;
/**
調整位置
*/
CGContextTranslateCTM(cContext, -tempWindow.bounds.size.width * tempWindow.layer.anchorPoint.x, -tempWindow.bounds.size.height * tempWindow.layer.anchorPoint.y);
/**
根據方向調整上下文
*/
if (orientation == UIInterfaceOrientationLandscapeLeft){
CGContextRotateCTM(cContext, M_PI_2);
CGContextTranslateCTM(cContext, 0, -imageSize.width);
} else if (orientation == UIInterfaceOrientationLandscapeRight){
CGContextRotateCTM(cContext, -M_PI_2);
CGContextTranslateCTM(cContext, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(cContext, M_PI);
CGContextTranslateCTM(cContext, -imageSize.width, -imageSize.height);
}
/**
判斷是否呈現完整的快照檢視層次為螢幕上可見到當前上下文。
*/
if ([tempWindow respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]){
[tempWindow drawViewHierarchyInRect:tempWindow.bounds afterScreenUpdates:YES];
} else {
[tempWindow.layer renderInContext:cContext];
}
/**
恢復上下文場景
*/
CGContextRestoreGState(cContext);
}
5、通過上下文獲取去擷取的影象,並關閉影象的上下文。程式碼如下:
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
通過上面兩個大的步驟,我們就能獲取到使用者截圖的影象。
三、獲取到使用者截圖的影象,那就可以實現自己的功能。
我們這裡介紹分享截圖對於App的開發人員來說,自己都有自己使用分享的一套。這裡我們介紹我的分享SDK。
第1步、 我們首先下載 NWShareSDK 。
第2步、 我們講下的 NWShareSDK 匯入到您的 Project 裡面。
第3步、 我們新增必要的支援庫,如下圖:
第4步、 我們新增支援分享的白名單,否則將不能開啟WeChat\QQ\Sina等。如圖粉色方框所示:
第5步、 我們支援分享回撥,新增必要的 * URL Types * ,如圖所示:
注意:以上的 URL Schemes 都是我自己編的。請把您的填入進去。然後在 * AppDelegate * 中實現回撥的方法即可。
第6步、 在我們下載的 NWShareSDK 中含有 NWScreenshotsModule ,這就是我們截圖分享模組。如圖所示:
第7步 、 在我們檢測到手勢截圖的通知觸發的方法裡面植入 ScreenshotsShareView 即可實現截圖分享。程式碼如下:
#pragma mark Screenshots to trigger method
-(void)screenshotsEventMethod{
ScreenshotsShareView * SSView = [[ScreenshotsShareView alloc]initWithFrame:[UIScreen mainScreen].bounds];
[[UIApplication sharedApplication].keyWindow addSubview:SSView];
}
ScreenshotsShareView 的程式碼如下:
//
// ScreenshotsShareView.m
// NetWork_NewShareDemo
//
// Created by MAC on 2017/7/10.
// Copyright © 2017年 NetworkCode小賤. All rights reserved.
//
#import "ScreenshotsShareView.h"
@implementation ScreenshotsShareView
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
/**
設定背景色
*/
self.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.5];
/**
新增手勢
*/
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapGestureMethod)];
[self addGestureRecognizer:tapGestureRecognizer];
/**
內建定時器
*/
__weak typeof(self) rootSelf = self ;
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:5 repeats:NO block:^(NSTimer * _Nonnull timer) {
[rootSelf tapGestureMethod];
}];
/**
動態註冊標記
*/
objc_setAssociatedObject(self, @"Timer", timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
/**
新增彈出層
*/
shareShowView = [[UIView alloc]init];
shareShowView.layer.masksToBounds = YES ;
shareShowView.layer.cornerRadius = 4 ;
shareShowView.layer.borderWidth = 0.46 ;
shareShowView.layer.borderColor = [UIColor grayColor].CGColor;
[self addSubview:shareShowView];
}
return self ;
}
#pragma mark 佈局位置
-(void)layoutSubviews{
shareShowView.frame = CGRectMake(0, 0, self.bounds.size.width * 0.628, 50);
shareShowView.center = CGPointMake(self.center.x, CGRectGetHeight(self.frame)-80);
/**
分享內容的佈局
*/
[self makeShareIcon];
}
#pragma mark Set the share icons
-(void)makeShareIcon{
/**
新增標題
*/
UILabel * shareTitleLable = [[UILabel alloc]initWithFrame:CGRectMake(5, 2.5, 20, 45)];
shareTitleLable.font = [UIFont systemFontOfSize:10.0];
shareTitleLable.text = @"分享至";
shareTitleLable.numberOfLines = 3 ;
[shareShowView addSubview:shareTitleLable];
/**
分享的Icons
*/
NSArray * iconNamesArray = @[[UIImage imageNamed:@"ShareAction.bundle/weichat"],[UIImage imageNamed:@"ShareAction.bundle/friends"],[UIImage imageNamed:@"ShareAction.bundle/qq"],[UIImage imageNamed:@"ShareAction.bundle/sina"]];
/**
計算一個Icon 的寬度
*/
CGFloat iconWidth = (CGRectGetWidth(shareShowView.frame) - 20 - CGRectGetWidth(shareTitleLable.frame) - (iconNamesArray.count - 1 )* 15 )/ iconNamesArray.count ;
for (NSInteger i = 0; i < iconNamesArray.count; i++ ) {
UIButton * iconBtn = [UIButton buttonWithType:UIButtonTypeCustom];
iconBtn.frame = CGRectMake(CGRectGetMaxX(shareTitleLable.frame)+10+ i * (iconWidth + 15) , 0.5 * (CGRectGetHeight(shareShowView.frame) - iconWidth ), iconWidth , iconWidth);
[iconBtn setImage:iconNamesArray[i] forState:UIControlStateNormal];
iconBtn.tag = i ;
[iconBtn addTarget:self action:@selector(tapIconBtn:) forControlEvents:UIControlEventTouchUpInside];
[shareShowView addSubview:iconBtn];
}
iconNamesArray = nil;
CFBridgingRelease(CFBridgingRetain(iconNamesArray));
}
#pragma mark Click on the icons button
-(void)tapIconBtn:(UIButton*) iconBtn{
NSInteger indexBtnTag = iconBtn.tag ;
switch (indexBtnTag) {
case 0:{
NWWeChatAPI * weChatApi = [NWWeChatAPI initializeSimpleInterest];
BOOL isInitialize = [weChatApi detectionInstallWeiChat];
if (!isInitialize) {
return ;
}
if (![weChatApi isWXAppSupportApi]) {
return ;
}
weChatApi.shareImageData = UIImagePNGRepresentation([NWImageCompression getScreenshotsImage]);
weChatApi.shareImageThumbData = UIImagePNGRepresentation([NWImageCompression getScreenshotsImage]);
[weChatApi shareWeChatImage:NWWeiChatList];
}
break;
case 1:{
NWWeChatAPI * weChatApi = [NWWeChatAPI initializeSimpleInterest];
BOOL isInitialize = [weChatApi detectionInstallWeiChat];
if (!isInitialize) {
return ;
}
if (![weChatApi isWXAppSupportApi]) {
return ;
}
weChatApi.shareImageData = UIImagePNGRepresentation([NWImageCompression getScreenshotsImage]);
weChatApi.shareImageThumbData = UIImagePNGRepresentation([NWImageCompression imageCompressionRatioValue:0.1 withSourceImage:[NWImageCompression getScreenshotsImage]]);
[weChatApi shareWeChatImage:NWWeiChatFrineds];
}
break;
case 2:{
NWQQShareAPI * QQApi = [NWQQShareAPI initializeSimpleInterest];
BOOL isInitialize = [QQApi detectionApplicationIsInstallation];
if (!isInitialize) {
return ;
}
if (![QQApi isQQSupportApi]) {
return ;
}
QQApi.shareImageData = UIImagePNGRepresentation([NWImageCompression getScreenshotsImage]);
QQApi.sharePreviewImageData = UIImagePNGRepresentation([NWImageCompression getScreenshotsImage]);
[QQApi shareQQImage:NWQQList];
}
break;
case 3:{
}
break;
default:{
return ;
}
break;
}
}
#pragma mark Popup layer clear theme
-(void)tapGestureMethod{
/**
獲取現有的定時器,並清除
*/
NSTimer * timer = (NSTimer*) objc_getAssociatedObject(self, @"Timer");
[timer invalidate];
[UIView animateWithDuration:0.5 delay:0.00 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{
shareShowView.frame = CGRectMake(0, CGRectGetHeight(self.frame),shareShowView.bounds.size.width, shareShowView.bounds.size.height);
shareShowView.center = CGPointMake(self.center.x, shareShowView.center.y);
shareShowView.alpha = 0.0 ;
} completion:^(BOOL finished) {
[shareShowView removeFromSuperview];
CFBridgingRelease(CFBridgingRetain(shareShowView)) ;
[self removeFromSuperview];
CFBridgingRelease(CFBridgingRetain(self)) ;
}];
}
@end