【IOS】【OC】【應用內打印功能的實現】如何在APP內實現打印功能,連接本地打印機,把想要打印的界面打印成圖片

【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);

以上就是如何通過截屏保存圖片最后打印

上面兩種方法都可以實現打印指定區域的效果,具體實現可以根據自身的項目需求來定

希望能給大家帶來幫助!!!有什么問題不明白的需要討論的都可以評論私信歡迎一起討論~~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82463.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82463.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82463.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AWS WebRTC:獲取信令服務節點和ICE服務節點

建立WebRTC的第一步是獲取信令服務節點和ICE服務節點。 前提條件是有訪問AWS的密鑰&#xff0c;主要是ak&#xff0c;sk&#xff0c;token&#xff0c;我這邊是業務云有接口可以返回這些信息&#xff0c;所以我直接從業務云獲取。 先介紹一下什么是ak&#xff0c;sk&#xff…

C++23 新成員函數與字符串類型的改動

文章目錄 引言std::basic_string::contains 與 std::basic_string_view::contains (P1679R3)功能介紹示例代碼優勢 禁止從 nullptr 構造 std::basic_string 和 std::basic_string_view (P2166R1)背景改動影響 std::basic_string_view 的顯式范圍構造函數 (P1989R2)功能介紹示例…

VMware-MySQL主從

MySQL主從 服務器信息 服務器類型角色主機地址主機名稱虛擬機master192.168.40.128test-1虛擬機slave192.168.40.129test-2 Master 配置&#xff08;192.168.40.128&#xff09; 刪除自動生成的配置 /var/lib/mysql/auto.cnf [roottest-1 ~]# rm -rf /var/lib/mysql/auto.…

Java組合、聚合與關聯:核心區別解析

在Java中&#xff0c;組合、聚合和關聯是描述類之間關系的三種不同方式&#xff0c;它們的核心區別在于對象間的依賴強度和生命周期管理。以下是它們的詳細對比&#xff1a; 1. 關聯&#xff08;Association&#xff09; 定義&#xff1a;最基本的類間關系&#xff0c;表示一個…

如何保護網絡免受零日漏洞攻擊?

零日漏洞&#xff08;Zero-Day Vulnerability&#xff09;是指軟件或系統中尚未被廠商發現或修補的安全漏洞。這個名稱中的“零日”意味著&#xff0c;從漏洞被發現到廠商發布修復補丁的時間是零天&#xff0c;也就是說&#xff0c;黑客可以利用這個漏洞進行攻擊&#xff0c;而…

linux快速入門-VMware安裝linux,配置靜態ip,使用服務器連接工具連接,快照和克隆以及修改相關配置信息

安裝VMWare 省略&#xff0c;自己檢索 安裝操作系統-linux 注意&#xff1a;需要修改的我會給出標題&#xff0c;不要修改的直接點擊下一步就可以 選擇自定義配置 選擇稍后安裝操作系統 選擇合適的內存 選擇NAT模式 僅主機模式 虛擬機只能和主機通信&#xff0c;不能上網…

Nest全棧到失業(一):Nest基礎知識掃盲

Nest 是什么? 問你一個問題,node是不是把js拉出來瀏覽器環境運行了?當然,他使用了v8引擎加上自己的底層模塊從而實現了,在外部編輯處理文件等;然后它使用很多方式來發送請求是吧,你知道的什么http.request 或 https.request; 我們瀏覽器中,使用AJAX以及封裝AJAX和http的Axios…

Streamlit 項目知識點總結

目錄 1. 單選框、下拉框格式化 2. 多媒體資源的引用 2.1 搭建一個簡易的http服務器 2.2 約定多媒體資源的輸入格式 2.3 解析多媒體資源 3. 設置頁面的全局背景圖片 4. 輸出流式文本&#xff08;類似打字效果&#xff09; 4.1 使用內置的 st.write_stream 方法實現 4.2…

maven模塊化開發

使用方法 將項目安裝到本地倉庫 mvn install 的作用 運行 mvn install 時&#xff0c;Maven 會執行項目的整個構建生命周期&#xff08;包括 compile、test、package 等階段&#xff09;&#xff0c;最終將構建的 artifact 安裝到本地倉庫&#xff08;默認路徑為 ~/.m2/repos…

(11)Service Mesh架構下Java應用實現零信任安全模型

Service Mesh架構下Java應用實現零信任安全模型 ?? TL;DR: 本文詳細介紹如何在Service Mesh架構中實現零信任安全模型,包括身份認證、授權控制、加密通信和持續監控四大核心技術,以及與Istio、Envoy等組件的集成方案。 目錄 零信任安全模型概述關鍵技術實現最佳實踐Service…

修改 K8S Service 資源類型 NodePort 的端口范圍

在 Kubernetes 中&#xff0c;Service 類型為 NodePort 時&#xff0c;默認分配的端口范圍為 30000~32767。如果你希望使用自定義端口&#xff08;如 8080、8888 等&#xff09;&#xff0c;就需要修改 kube-apiserver 的默認配置。 本文將詳細介紹如何修改 Kubernetes 中 Nod…

MySQL 可觀測性最佳實踐

MySQL 簡介 MySQL 是一個廣泛使用的開源關系型數據庫管理系統&#xff08;RDBMS&#xff09;&#xff0c;以其高性能、可靠性和易用性而聞名&#xff0c;適用于各種規模的應用&#xff0c;從小型網站到大型企業級系統。 監控 MySQL 指標是維護數據庫健康、優化性能和確保數據…

CentOS安裝最新Elasticsearch8支持向量數據庫

大家都知道Elasticsearch是支持向量的存儲和查詢的&#xff0c;今天我們來介紹下如何安裝支持向量數據庫的Elasticsearch &#xff0c; 操作環境是CentOS。 成功安裝截圖 大家進入系統shell&#xff0c;跟我執行下面命令進行安裝。 更新系統 [rootlocalhost ~]# sudo yum u…

SDL2常用函數SDL事件處理:SDL_Event|SDL_PollEvent

SDL_Event SDL_Event是個聯合體&#xff0c;是SDL中所有事件處理的核心。 SDL_Event是SDL中使用的所有事件結構的并集。 只要知道了那個事件類型對應SDL_Event結構的那個成員&#xff0c;使用它是一個簡單的事情。 下表羅列了所有SDL_Event的所有成員和對應類型。 Uint32typ…

webpack吐環境分析

需要解決的問題 扣取下來的webpack文件過大 解決思路 用ast將需要的代碼扣下來 結果展示 實現步驟 第一步&#xff1a;我們得知道需要哪些模塊 在入口處&#xff0c;增加模塊記錄 第二步&#xff0c;分析ast代碼 通過分析發現,key 有三種值 分別為NumbericLiteral、StringLi…

微軟語音合成助手資源下載

微軟語音合成助手資源下載 【下載地址】微軟語音合成助手資源下載 微軟語音合成助手是一款基于先進AI技術的文本轉語音工具&#xff0c;能夠將文字內容快速轉換為自然流暢的語音。它支持高度自定義的語音參數&#xff0c;包括語速、音調、發音和停頓等&#xff0c;滿足多樣化需…

青少年編程與數學 02-020 C#程序設計基礎 01課題、C#編程概要

青少年編程與數學 02-020 C#程序設計基礎 01課題、C#編程概要 一、微軟.NET開發平臺1. 核心組件2. 特點3. 應用場景4. 開源與社區5. 版本與更新6. 學習資源 二、C# 編程語言1. 歷史背景2. 語言特性&#xff08;1&#xff09;面向對象&#xff08;2&#xff09;類型安全&#xf…

圖片文件未正確加載?—— Webpack 無法正確解析圖片,生成了一個空的 Base64 URL

如果你打印出的圖片 URL 是 data:image/png;base64, 后面沒有實際的 Base64 數據&#xff0c;可能有以下幾種原因&#xff1a; ??1. 圖片文件未正確加載?? ??可能原因??&#xff1a;圖片路徑錯誤&#xff0c;導致 Webpack 無法正確解析圖片&#xff0c;生成了一個空的…

3D打印仿造+ AI大腦賦能,造出會思考的全景相機

在自然界的生存競賽里&#xff0c;節肢動物堪稱視覺界的 "卷王"&#xff01;那些長著復眼的小機靈鬼&#xff0c;比如蜜蜂、蜻蜓&#xff0c;別看個頭小&#xff0c;視覺能力卻超強。 現在&#xff0c;科學家把它們的眼睛 " 偷"過來啦 —— 不是真偷&…

rabbitmq單機多實例部署

RabbitMQ 單實例部署 單實例部署是指在一臺服務器上運行一個 RabbitMQ 實例。這種部署方式適用于小型應用或開發環境,配置簡單,資源占用較少。單實例部署的核心是安裝 RabbitMQ 并啟動服務,通常需要配置 Erlang 環境,因為 RabbitMQ 是基于 Erlang 編寫的。單實例部署的優勢…