iOS屏幕截图事件

时间:2022-09-26 15:24:18

一直想做这个功能,相信完善后加入我们项目中,会很有效的方便用户截屏反馈问题。目前ios11版本已经有了屏幕截图编辑并分享的功能,现在才写有点多余了。
将截取到的图片放在当前页面中展示,初步利用程序截图并按一定比例显示在屏幕上。截图同时触发分享弹框,点击任意分享按钮则释放imgView并关闭视图。此处贴图暂未把分享功能加入,仅仅是个小demo。如下效果: iOS屏幕截图事件

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

一、注册通知

+ (AppDelegate* )shareAppDelegate
{
    // 发送通知信息
 [[NSNotificationCenter defaultCenter] postNotificationName:@"Screens" object:nil userInfo:@{@"ScreensState":[NSNumber numberWithBool:YES]}];

    return (AppDelegate*)[UIApplication sharedApplication].delegate;

}

在APPDelegate.h中声明+ (AppDelegate* )shareAppDelegate;

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

我们需要创建一个UIView来显示截到的图片

#import "showView.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface showView ()

+ (instancetype)instance;

@property (nonatomic ,strong) UIImageView *_imgView;
@property (nonatomic ,strong) UIWindow *_window;
@property (nonatomic ,strong) UIButton *_btn;

@end

@implementation showView

static showView *instance;

+ (instancetype)instance
{
    if (!instance)
    {
        instance = [[showView alloc] init];
    }
    return instance;
}

- (instancetype)init
{
    if ((self = [super initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)]))
    {
        self.backgroundColor = [UIColor clearColor];
        if (self.window == nil)
        {
            self._window = [[UIWindow alloc] init];
            self._window.frame = self.frame;
            self._window.windowLevel = UIWindowLevelAlert+1;
            self._window.backgroundColor = [UIColor blackColor];
            self._window.alpha = .5;
            [self._window addSubview:self];
            [self._window makeKeyAndVisible];
        }

        self._imgView = [[UIImageView alloc] init];
        self._imgView.frame = CGRectMake(0, 0, kScreenWidth-80, (kScreenWidth-80)*kScreenHeight/kScreenWidth);//尺寸按屏幕比例截图比较美观
        self._imgView.center = self.center;
        [self addSubview:self._imgView];

        //此处只是设置了一个取消按钮(removeFromSuperview)用以关闭弹框
        self._btn = [UIButton buttonWithType:UIButtonTypeCustom];
        self._btn.backgroundColor = [UIColor blueColor];
        self._btn.frame = CGRectMake((self.frame.size.width - 100)/2, self.frame.size.height - 60, 100, 50);
        [self._btn setTitle:@"点击" forState:UIControlStateNormal];
        [self._btn addTarget:self action:@selector(dismissView) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self._btn];

    }
    return self;
}


+ (void)showWelcomeView:(UIImage *)images
{
    [self instance];
    instance._imgView.image = images;
}

- (void)dismissView
{
    [self removeFromSuperview];
    instance = nil;
}

三、实现截图的关键代码

写在APPdelegate.m实现全局调用

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //查找之后发现苹果在ios7之后提供了一个新的通知类型:UIApplicationUserDidTakeScreenshotNotification,这个通知会告知注册了此通知的对象已经发生了截屏事件,然后我们就可以在这个事件中实现自己的逻辑。
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        // executes after screenshot
        NSLog(@"截屏咯");
        [self userDidTakeScreenshot];
    }];
    return YES;
}
//截屏响应
- (void)userDidTakeScreenshot
{
    NSLog(@"检测到截屏");
    //人为截屏, 模拟用户截屏行为, 获取所截图片
    UIImage *image = [self imageWithScreenshot];
    [showView showWelcomeView:image];//此处调用之前创建的用于显示截图的UIView,showView
}
/** * 返回截取到的图片 * * @return UIImage * */
- (UIImage *)imageWithScreenshot
{
    NSData *imageData = [self dataWithScreenshotInPNGFormat];
    return [UIImage imageWithData:imageData];
}

/** * 截取当前屏幕 * * @return NSData * */
- (NSData *)dataWithScreenshotInPNGFormat
{
    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();

    return UIImagePNGRepresentation(image);
}

分享的方法在这里就不赘述了,网上一搜一大堆。
如需要demo,请点附件下载