Swift:裁剪没有 TabBar 和 NavigationBar 的屏幕截图
Posted
技术标签:
【中文标题】Swift:裁剪没有 TabBar 和 NavigationBar 的屏幕截图【英文标题】:Swift: Cropping a Screenshot without TabBar and NavigationBar 【发布时间】:2015-08-15 03:24:51 【问题描述】:我有整个屏幕的屏幕截图,screenshot
,使用以下内容生成:
let layer = UIApplication.sharedApplication().keyWindow!.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
我想裁剪它以便不包含标签栏,我尝试使用以下代码:
let crop = CGRectMake(0, 0, //"start" at the upper-left corner
self.view.bounds.width, //include half the width of the whole screen
self.view.bounds.height + self.navigationController!.navigationBar.frame.height) //include the height of the navigationBar and the height of view
let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop)
let image: UIImage = UIImage(CGImage: cgImage)!
此代码导致image
仅显示屏幕的一小部分,从屏幕左上角 (0, 0) 开始的矩形,向右延伸不到屏幕宽度的一半,然后向下低于屏幕高度的一半。不过,我希望它包含 整个 屏幕,但标签栏占据的区域除外。有没有这样的裁剪方法?
【问题讨论】:
【参考方案1】:据此
新图像由创建 1) 通过调用
CGRectIntegral
将rect
调整为整数范围; 2) 将结果与具有原点 (0, 0) 和大小的矩形相交 等于image
的大小; 3) 引用生成的矩形内的像素,处理 图像数据的第一个像素作为图像的原点。 如果生成的矩形是空矩形,则此函数返回 空。如果 W 和 H 分别是图像的宽度和高度,则 point (0,0) 对应图像数据的第一个像素;重点 (W-1, 0) 是图像数据第一行的最后一个像素; (0, H-1) 是图像数据最后一行的第一个像素; (W-1, H-1) 是 图像数据最后一行的最后一个像素。
你需要有这样的裁剪功能。您可能需要调整bottomBarHeight
的计算方式
func takeScreenshot(sender: AnyObject)
let layer = UIApplication.sharedApplication().keyWindow!.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let croppedImage = self.cropImage(screenshot)
func cropImage(screenshot: UIImage) -> UIImage
let scale = screenshot.scale
let imgSize = screenshot.size
let screenHeight = UIScreen.mainScreen().applicationFrame.height
let bound = self.view.bounds.height
let navHeight = self.navigationController!.navigationBar.frame.height
let bottomBarHeight = screenHeight - navHeight - bound
let crop = CGRectMake(0, 0, //"start" at the upper-left corner
(imgSize.width - 1) * scale, //include half the width of the whole screen
(imgSize.height - bottomBarHeight - 1) * scale) //include the height of the navigationBar and the height of view
let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop)
let image: UIImage = UIImage(CGImage: cgImage)!
return image
【讨论】:
【参考方案2】:迅速:
let contextImage: UIImage = <<screenshot>>!
let cropRect: CGRect = CGRectMake(x, y, width, height)
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, cropRect)
let image: UIImage = UIImage(CGImage: imageRef, scale: originalImage.scale, orientation: originalImage.imageOrientation)!
obj-c:
UIImage *image = <<screenshot>>;
CGRect croprect = CGRectMake(0, 0,
self.view.bounds.width,
self.view.bounds.height + self.navigationController!.navigationBar.frame.height));
// Draw new image in current graphics context
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], croprect);
// Create new cropped UIImage
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
【讨论】:
这个问题在 Swift 中寻找答案,而不是在 Objective-C 中。 我的错...我加了 swift【参考方案3】:您有两种选择:
首先,您可以使用UIApplication.sharedApplication().keyWindow
截取屏幕截图,然后我们将拥有这个:
UIGraphicsBeginImageContext(UIApplication.sharedApplication().keyWindow!.bounds.size)
UIApplication.sharedApplication().keyWindow!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
因此,您必须像这样裁剪图像:
let yPosition = self.navigationController!.navigationBar.frame.height + UIApplication.sharedApplication().statusBarFrame.size.height
let crop = CGRectMake(0, yPosition,
self.view.bounds.width,
self.view.bounds.height)
let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop)
let image: UIImage = UIImage(CGImage: cgImage)!
第二种选择是直接截取您的视图,如下所示:
UIGraphicsBeginImageContext(self.view!.bounds.size)
self.view!.layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
在这种情况下,您不需要裁剪导航栏。
这是github上的示例代码https://github.com/gazolla/crop
【讨论】:
您关于裁剪图像的建议似乎没有达到我想要的效果——它仍然只是屏幕左上角的一小部分。 这会裁剪出导航栏,而不是标签栏。 我只是赞成你的回答,但我只是意识到它并不排除 tabBar【参考方案4】:我认为你的作物CGRect
是错误的。
let crop = CGRectMake(0,
0,
self.view.frame.size.width,
self.view.frame.size.height + self.navigationController!.navigationBar.frame.height - self.tabBar.frame.size.height
)
X: 0 和 Y: 0 - 分别从 0 和 0 开始。
宽度:捕获视图的整个宽度
高度:整个视图的高度加上UINavigationBar
的高度减去UITabBar
的高度。
【讨论】:
对不起,这仍然不适合我,我仍然只看到左上象限。这可能与我正在使用的显示器类型(iPhone 6 Plus)有关吗? 你在哪里调用这个代码?视图控制器?子视图? 视图控制器,特别是导航栏按钮的操作。 “左上象限”是什么意思?你是指整个屏幕的左上象限吗?只有按钮?你能发布一个截图和一个可以重现问题的独立项目吗?【参考方案5】:我在 Swift 4.2 中的回答,步骤在函数 getScreenshot()
代码上方的 cmets 中
@IBAction fileprivate func takeScreenshotButtonTapped(_ sender: UIButton)
guard let croppedScreenshotImage = getScreenshot() else return
// do something with the croppedScreenshotImage
func getScreenshot() -> UIImage?
// 1. get screenshot of the entire screen
UIGraphicsBeginImageContext(UIApplication.shared.keyWindow!.bounds.size)
UIApplication.shared.keyWindow!.layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// 2. height of statusBar
let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
// 3. height of navigationBar
var navBarHeight: CGFloat = 0
if let navigationBarHeight = navigationController?.navigationBar.frame.height
navBarHeight = navigationBarHeight
// 4. total height of statusBar + navigationBar
let topBarHeight = statusBarHeight + navBarHeight
// 5. get the height of the tabBar
var tabBarHeight: CGFloat = 0
if let tabBarController = tabBarController
tabBarHeight = tabBarController.tabBar.frame.size.height
// 6. to exclude the navigationBar, statusBar, and tabBar from your screenshot start the rect's y-axis at everything below the topBarHeight. For the height subtract the topBarHeight and tabBarHeight from the view's height
let rectWithoutNavStatusAndTabBar = CGRect(x: 0, y: topBarHeight, width: self.view.bounds.width, height: self.view.bounds.height - topBarHeight - tabBarHeight)
guard let safeScreenshot = screenshot else return nil
// 7. crop the screenshot to the rectWithoutNavStatusAndTabBar
guard let cgImage = safeScreenshot.cgImage?.cropping(to: rectWithoutNavStatusAndTabBar) else return nil
// 8. create an image from the cgImage
let yourCroppedScreenshotImage = UIImage(cgImage: cgImage)
return yourCroppedScreenshotImage
这也是公认答案的 Swift 4.2 版本:
func takeScreenshot(sender: AnyObject)
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let croppedImage = self.cropImage(screenshot: screenshot!)
func cropImage(screenshot: UIImage) -> UIImage
let scale = screenshot.scale
let imgSize = screenshot.size
let screenHeight = UIScreen.main.bounds.height
let bound = self.view.bounds.height
let navHeight = self.navigationController!.navigationBar.frame.height
let bottomBarHeight = screenHeight - navHeight - bound
let crop = CGRect(x: 0, y: 0, width: (imgSize.width - 1) * scale, height: (imgSize.height - bottomBarHeight - 1) * scale)
let cgImage = screenshot.cgImage?.cropping(to: crop)
let image: UIImage = UIImage(cgImage: cgImage!)
return image
【讨论】:
以上是关于Swift:裁剪没有 TabBar 和 NavigationBar 的屏幕截图的主要内容,如果未能解决你的问题,请参考以下文章
Swift 防止 TabBar 在键盘处于活动状态时向上移动