Как сделать снимок экрана UIView?
мне интересно, как мое приложение iPhone может сделать снимок экрана определенного UIView как UIImage.
я попробовал этот код, но все, что я получаю пустую картинку.
UIGraphicsBeginImageContext(CGSizeMake(320,480));
CGContextRef context = UIGraphicsGetCurrentContext();
[myUIView.layer drawInContext:context];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
myUIView имеет размеры 320x480 и имеет некоторые подвиды.
Как правильно это сделать?
15 ответов:
Я думаю, что вы хотите
renderInContext, а неdrawInContext. drawInContext-это скорее метод, который вы бы переопределили...обратите внимание, что он может не работать во всех видах, в частности, год или около того назад, когда я пытался использовать это с видом на живую камеру, он не работал.
iOS 7 имеет новый метод, который позволяет рисовать иерархию представлений в текущем графическом контексте. Это может быть использовано для получения UIImage очень быстро.
я реализовал метод категории на
UIViewчтобы получить представление какUIImage:- (UIImage *)pb_takeSnapshot { UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }это значительно быстрее, чем существующие
renderInContext:метод.Ссылка:https://developer.apple.com/library/content/qa/qa1817/_index.html
ОБНОВЛЕНИЕ ДЛЯ Свифт: расширение, которое делает то же самое:
extension UIView { func pb_takeSnapshot() -> UIImage { UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale) drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true) // old style: layer.renderInContext(UIGraphicsGetCurrentContext()) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }ОБНОВЛЕНИЕ ДЛЯ SWIFT 3
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale) drawHierarchy(in: self.bounds, afterScreenUpdates: true) let image = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image
вы должны захватить ключ окна для скриншота или UIView. Вы можете сделать это Разрешение Retina С помощью UIGraphicsBeginImageContextWithOptions и установить его масштаб параметр 0.0 f. он всегда захватывает в собственном разрешении (retina для iPhone 4 и более поздних версий).
Это делает полноэкранный скриншот (ключевое окно)
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; CGRect rect = [keyWindow bounds]; UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); [keyWindow.layer renderInContext:context]; UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();этот код захватывает UIView в собственном разрешении
CGRect rect = [captureView bounds]; UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f); CGContextRef context = UIGraphicsGetCurrentContext(); [captureView.layer renderInContext:context]; UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();это сохраняет UIImage в jpg формат с качеством 95% в папке документа приложения, если вам нужно это сделать.
NSString *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/capturedImage.jpg"]]; [UIImageJPEGRepresentation(capturedImage, 0.95) writeToFile:imagePath atomically:YES];
iOS7 вперед, у нас есть ниже методы по умолчанию:
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdatesвызов метода выше быстрее, чем попытка самостоятельно отобразить содержимое текущего представления в растровое изображение.
Если вы хотите применить графический эффект, например размытие, к снимку, используйте метод.
Я создал полезное расширение для UIView, чтобы сделать снимок экрана в Swift:
extension UIView{ var screenshot: UIImage{ UIGraphicsBeginImageContext(self.bounds.size); let context = UIGraphicsGetCurrentContext(); self.layer.renderInContext(context) let screenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screenShot } }чтобы использовать его просто введите:
let screenshot = view.screenshot
- (void)drawRect:(CGRect)rect { UIGraphicsBeginImageContext(self.bounds.size); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil); }этот метод может поместить в ваш класс контроллера.
есть новый API от iOS 10
extension UIView { func makeScreenshot() -> UIImage { let renderer = UIGraphicsImageRenderer(bounds: self.bounds) return renderer.image { (context) in self.layer.render(in: context.cgContext) } } }
CGImageRef UIGetScreenImage();Apple теперь позволяет нам использовать его в публичном приложении, даже если это частный API
Apple не позволяют:
CGImageRef UIGetScreenImage();приложения должны сделать снимок экрана с помощью
drawRectметод, как указано в: http://developer.apple.com/library/ios/#qa/qa2010/qa1703.html
следующий фрагмент используется для создания скриншота:
UIGraphicsBeginImageContext(self.muUIView.bounds.size); [myUIView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();использовать
renderInContext:вместоdrawInContext:метод
renderInContext:метод отображает приемник и его подслои в текущий контекст. Этот метод визуализация непосредственно из дерева слоев.
подробности
xCode 8.2.1, Swift 3
снимок экрана UIView в Swift
import UIKit extension UIView { var screenShot: UIImage? { UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0); if let _ = UIGraphicsGetCurrentContext() { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } }использование
screenShotRenderer.image = viewForScreenShot.screenShotпример использования
контроллер вида с расширением UIView
import UIKit class ViewController: UIViewController { @IBOutlet var viewForScreenShot: UIView! @IBOutlet var screenShotRenderer: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } @IBAction func makeViewScreenShotButtonTapped2(_ sender: UIButton) { screenShotRenderer.image = viewForScreenShot.screenShot } } extension UIView { var screenShot: UIImage? { UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0); if let _ = UIGraphicsGetCurrentContext() { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } }Главная.раскадровка
<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_2214957" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Acg-GO-mMN"> <rect key="frame" x="67" y="28" width="240" height="128"/> <subviews> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="4Fr-O3-56t"> <rect key="frame" x="72" y="49" width="96" height="30"/> <constraints> <constraint firstAttribute="height" constant="30" id="cLv-es-h7Q"/> <constraint firstAttribute="width" constant="96" id="ytF-FH-gdm"/> </constraints> <nil key="textColor"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> </subviews> <color key="backgroundColor" red="0.0" green="0.47843137250000001" blue="1" alpha="0.49277611300000002" colorSpace="custom" customColorSpace="sRGB"/> <color key="tintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/> <constraints> <constraint firstItem="4Fr-O3-56t" firstAttribute="centerX" secondItem="Acg-GO-mMN" secondAttribute="centerX" id="egj-rT-Gz5"/> <constraint firstItem="4Fr-O3-56t" firstAttribute="centerY" secondItem="Acg-GO-mMN" secondAttribute="centerY" id="ymi-Ll-WIV"/> </constraints> </view> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SQq-IE-pvj"> <rect key="frame" x="109" y="214" width="157" height="30"/> <state key="normal" title="make view screen shot"/> <connections> <action selector="makeViewScreenShotButtonTapped2:" destination="BYZ-38-t0r" eventType="touchUpInside" id="KSY-ec-uvA"/> </connections> </button> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CEZ-Ju-Tpq"> <rect key="frame" x="67" y="269" width="240" height="128"/> <constraints> <constraint firstAttribute="width" constant="240" id="STo-iJ-rM4"/> <constraint firstAttribute="height" constant="128" id="tfi-zF-zdn"/> </constraints> </imageView> </subviews> <color key="backgroundColor" red="0.95941069162436543" green="0.95941069162436543" blue="0.95941069162436543" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="CEZ-Ju-Tpq" firstAttribute="top" secondItem="SQq-IE-pvj" secondAttribute="bottom" constant="25" id="6x1-iB-gKF"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="leading" secondItem="CEZ-Ju-Tpq" secondAttribute="leading" id="LUp-Be-FiC"/> <constraint firstItem="SQq-IE-pvj" firstAttribute="top" secondItem="Acg-GO-mMN" secondAttribute="bottom" constant="58" id="Qu0-YT-k9O"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Qze-zd-ajY"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="trailing" secondItem="CEZ-Ju-Tpq" secondAttribute="trailing" id="b1d-sp-GHD"/> <constraint firstItem="SQq-IE-pvj" firstAttribute="centerX" secondItem="CEZ-Ju-Tpq" secondAttribute="centerX" id="qCL-AF-Cro"/> <constraint firstItem="Acg-GO-mMN" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" symbolic="YES" id="u5Y-eh-oSG"/> <constraint firstItem="CEZ-Ju-Tpq" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="vkx-JQ-pOF"/> </constraints> </view> <connections> <outlet property="screenShotRenderer" destination="CEZ-Ju-Tpq" id="8QB-OE-ib6"/> <outlet property="viewForScreenShot" destination="Acg-GO-mMN" id="jgL-yn-8kk"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="32.799999999999997" y="37.331334332833585"/> </scene> </scenes> </document>результат
-(UIImage *)convertViewToImage { UIGraphicsBeginImageContext(self.bounds.size); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
вы можете использовать следующую категорию UIView -
@implementation UIView (SnapShot) - (UIImage *)snapshotImage { UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale); [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO]; // old style [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } @end
Swift 4 обновлено:
extension UIView { var screenShot: UIImage? { if #available(iOS 10, *) { let renderer = UIGraphicsImageRenderer(bounds: self.bounds) return renderer.image { (context) in self.layer.render(in: context.cgContext) } } else { UIGraphicsBeginImageContextWithOptions(bounds.size, false, 5); if let _ = UIGraphicsGetCurrentContext() { drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } return nil } } }


Comments