【IOS】【OC】【應用內打印功能的實現】如何在APP內實現打印功能,連接本地打印機,打印想打印的界面
設備/引擎:Mac(14.1.1)/cocos
開發工具:Xcode
開發語言:OC/C++
開發需求:工程中需要為用戶提供一個打印功能,讓用戶可以隨時打印自己想要打印的界面
APP屬于iOS工程,所以打印代碼考慮直接用OC代碼調用iOS原生界面就可以,很好用,也不用自己去寫UI,也比較適合短周期開發的情況,話不多說,直接正文
1.打印代碼
大致過程是這樣的,OC代碼判斷獲取到的圖片信息是否合法,再調用iOS原生的打印控制器,判斷是否有可用的打印機,最后用戶點擊打印即可……
獲取圖像部分
@autoreleasepool {// 獲取 Document 路徑NSString* docsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;NSString* imagePath = [docsDir stringByAppendingPathComponent:[NSString stringWithUTF8String:filename]];UIImage* image = [UIImage imageWithContentsOfFile:imagePath];if (!image) {NSLog(@"[PrintHelper] 圖片未找到:%@", imagePath);return;}.........
Tips:整段代碼用autoreleasepool包裹起來可以讓其中的臨時對象在代碼塊結束后及時釋放,避免內存泄露
判斷打印控制器是否可用并設置打印內容
UIPrintInteractionController* printController = [UIPrintInteractionController sharedPrintController];if (!printController || ![UIPrintInteractionController canPrintData:UIImagePNGRepresentation(image)]) {NSLog(@"[PrintHelper] 當前設備無法打印圖片。");return;}printController.printingItem = image; //設置打印內容
異步顯示iOS原生打印對話框
dispatch_async(dispatch_get_main_queue(), ^{
彈出打印界面 + 打印結果回調
[printController presentAnimated:YES completionHandler:^(UIPrintInteractionController * _Nonnull controller, BOOL completed, NSError * _Nullable error) {if (error) {NSLog(@"[PrintHelper] 打印失敗:%@", error.localizedDescription);} else if (completed) {NSLog(@"[PrintHelper] 打印完成。");} else {NSLog(@"[PrintHelper] 用戶取消打印。");}
}];
至此iOS原生打印代碼就算完成了
2.獲取打印圖片代碼
這個就是你想打印的部分,我們的工程中涉及打印的就是涂色相關的玩法,所以有兩種方法可以獲取打印區域,一種是獲取你需要打印的多個畫布,將這些畫布內容渲染出來保存為圖片文件再打印;還有一種方法是直接對屏幕內容進行局部截圖處理,將截好的圖直接傳過去進行打印
1)獲取多個畫布節點,將他們都渲染到一張新畫布上,然后再打印出來
創建畫布
// 1. 創建一張足夠大的 renderTextureCCSize targetSize = CCSizeMake(winSize.width, winSize.height); // 設置尺寸CCRenderTexture* rt = CCRenderTexture::create(targetSize.width, targetSize.height);rt->beginWithClear(1,1,1,1); // 白底
獲取多張ColoringClippingNode畫布并渲染
for (int i = 0; i < m_ClipDrawArray->count(); i++) {ColoringClippingNode* clip = (ColoringClippingNode*)m_ClipDrawArray->objectAtIndex(i);if (!clip) continue;// 保存原始位置CCPoint oldClipPos = clip->getPosition();// 計算偏移,使其居中繪制CCPoint centeredPos = ccp(winSize.width/2, winSize.height/2);if(i==0){clip->setPosition(ccp(winSize.width*0.65, winSize.height/2));}else{clip->setPosition(centeredPos);}// 直接visit整個clip節點,節點上的遮罩也會生效clip->visit();// 恢復原始位置clip->setPosition(oldClipPos);}
如果有需要渲染的sprite精靈也需要加進來
auto sprite = whiteCanvas;if (sprite){// 保存auto oldA = sprite->getAnchorPoint();auto oldP = sprite->getPosition();// 設置錨點和位置到大圖中心sprite->setAnchorPoint(ccp(0.5f,0.5f));sprite->setPosition(ccp(targetSize.width/2, targetSize.height/2));sprite->visit();// 恢復sprite->setAnchorPoint(oldA);sprite->setPosition(oldP);}
都渲染之后就是結束畫布渲染
rt->end();
保存渲染好的畫布;調用打印代碼
rt->saveToFile("printScene.png", kCCImageFormatPNG); //將畫布保存為PNG并命名
// 延遲調用打印代碼,避免未渲染保存就打印CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(ColorCanvasView::callPrintImage),this, 0, 0, 0.3f, false);
以上就是通過將多張畫布及精靈渲染到一張畫布再保存成文件,最后打印的過程,下面再說說如何通過截屏操作來打印
2)對屏幕想要打印的區域進行截屏保存,再打印
截屏代碼
@autoreleasepool {// 獲取根控制器和屏幕信息AppController *app = (AppController *)[UIApplication sharedApplication].delegate;UIViewController *viewController = [app viewController];UIView *targetView = viewController.view;CGFloat scale = [UIScreen mainScreen].scale;CGSize viewSize = targetView.bounds.size;
// 1. 截屏UIGraphicsBeginImageContextWithOptions(viewSize, NO, scale);[targetView drawViewHierarchyInRect:CGRectMake(0, 0, viewSize.width, viewSize.height) afterScreenUpdates:YES];UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();if (!fullImage) {NSLog(@"截屏失敗");return;}
// 2. 裁剪區域CGRect cropRect = CGRectMake(x * scale, y * scale, width * scale, height * scale);CGImageRef croppedCGImage = CGImageCreateWithImageInRect(fullImage.CGImage, cropRect);if (!croppedCGImage) {NSLog(@"裁剪失敗");return;}UIImage *croppedImage = [UIImage imageWithCGImage:croppedCGImagescale:scaleorientation:fullImage.imageOrientation];CGImageRelease(croppedCGImage);CGSize targetSize = CGSizeMake(width, height);UIGraphicsBeginImageContextWithOptions(targetSize, NO, scale);
一般還是需要對截屏區域進行縮放,保證打印時圖像大小位置合適
縮放居中代碼
CCSize winSizes = GameManager::sharedManager()->getViewVisibleSize();// 4. 縮放CGFloat shrinkScale = 0.85;CGFloat offX_x=0.3;CGSize scaledSize = CGSizeMake(croppedImage.size.width * shrinkScale, croppedImage.size.height * shrinkScale);// 5. 計算居中位置CGPoint origin = CGPointMake((targetSize.width - scaledSize.width) *offX_x, (targetSize.height - scaledSize.height) / 2.0);// 6. 居中繪制縮小后的圖像[croppedImage drawInRect:CGRectMake(origin.x, origin.y, scaledSize.width, scaledSize.height)];// 7. 得到最終圖像UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();
最后就是將圖像保存為文件
// 8. 保存圖像到文件NSData *imageData = UIImagePNGRepresentation(finalImage);if (!imageData) {NSLog(@"圖片數據為空");return;}NSString *docsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;NSString *imagePath = [docsDir stringByAppendingPathComponent:[NSString stringWithUTF8String:filename]];if ([imageData writeToFile:imagePath atomically:YES]) {NSLog(@"圖片保存成功:%@", imagePath);} else {NSLog(@"圖片保存失敗");}
以上就是如何通過OC代碼來進行截屏操作,接下來就是在工程中如何調用
float x = winSize.width*widthX_x; // 起始橫坐標(point)float y = winSize.height*heightOffY; // 起始縱坐標(point)float w = winSize.width*widthOffX; // 寬度float h = winSize.height; // 高度const char* filename = "printScene.png";DeviceManager::sharedManager()->printSceneAddedToFile(filename, x, y, w, h);
// 延遲調用打印代碼,避免未渲染保存就打印CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(ColorCanvasView::callPrintImage),this, 0, 0, 0.3f, false);
以上就是如何通過截屏保存圖片最后打印
上面兩種方法都可以實現打印指定區域的效果,具體實現可以根據自身的項目需求來定
希望能給大家帶來幫助!!!有什么問題不明白的需要討論的都可以評論私信歡迎一起討論~~~