1. 程式人生 > >手機截圖直接分享&反饋

手機截圖直接分享&反饋

前言

       目前市面上的一些主流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

四、分享的效果圖

這裡寫圖片描述