2017-04-20 215 views
1

フォームから印刷ダイアログを使用する必要があります。私はiOSのソリューションを見つけましたが、アンドロイドの実装は私に問題をもたらしています。Xamarin.Forms経由でAndroidにローカルファイルを印刷する

私が見る限り、Androidのプリントマネージャを呼び出してファイルを解析することはできません。 AndroidView.Viewのみ表示できますが、それは本当ですか? これは私の理想的な解決策です。

私は自分のコンテンツ(ローカルPDFを表示しているwebview)をこのアンドロイドビューに変換しようとしましたが、これも実際には機能していないようですが、ここで私の奥行きを外しています。

以下のコードでは、forms.webviewをandroid.viewに変換し、それを印刷マネージャーに解析してみます。 これは印刷ダイアログを生成しますが、黒い白いページです。

var size = new Rectangle(webview.X, webview.Y, webview.Width, webview.Height); 
var vRenderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(webview); 
var viewGroup = vRenderer.ViewGroup; 
vRenderer.Tracker.UpdateLayout(); 
var layoutParams = new Android.Views.ViewGroup.LayoutParams((int)size.Width, (int)size.Height); 
viewGroup.LayoutParameters = layoutParams; 
webview.Layout(size); 
viewGroup.Layout(0, 0, (int)webview.WidthRequest, (int)webview.HeightRequest); 

var printMgr = (Android.Print.PrintManager)Forms.Context.GetSystemService(Android.Content.Context.PrintService); 
var docAdt = new Droid.GenericPrintAdapter(Forms.Context, viewGroup); 

printMgr.Print("test", docAdt, null); 

次は、私は今、 "ワーキング" のソリューションを持っている "GenericPrintAdapter"

public class GenericPrintAdapter : PrintDocumentAdapter 
{ 
    View view; 
    Context context; 
    PrintedPdfDocument document; 
    float scale; 

    public GenericPrintAdapter(Context context, View view) 
    { 
     this.view = view; 
     this.context = context; 
    } 

    public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 
            CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) 
    { 
     document = new PrintedPdfDocument(context, newAttributes); 

     CalculateScale(newAttributes); 

     var printInfo = new PrintDocumentInfo 
      .Builder("MyPrint.pdf") 
      .SetContentType(PrintContentType.Document) 
      .SetPageCount(1) 
      .Build(); 

     callback.OnLayoutFinished(printInfo, true); 
    } 

    void CalculateScale(PrintAttributes newAttributes) 
    { 
     int dpi = Math.Max(newAttributes.GetResolution().HorizontalDpi, newAttributes.GetResolution().VerticalDpi); 

     int leftMargin = (int)(dpi * (float)newAttributes.MinMargins.LeftMils/1000); 
     int rightMargin = (int)(dpi * (float)newAttributes.MinMargins.RightMils/1000); 
     int topMargin = (int)(dpi * (float)newAttributes.MinMargins.TopMils/1000); 
     int bottomMargin = (int)(dpi * (float)newAttributes.MinMargins.BottomMils/1000); 

     int w = (int)(dpi * (float)newAttributes.GetMediaSize().WidthMils/1000) - leftMargin - rightMargin; 
     int h = (int)(dpi * (float)newAttributes.GetMediaSize().HeightMils/1000) - topMargin - bottomMargin; 

     scale = Math.Min((float)document.PageContentRect.Width()/w, (float)document.PageContentRect.Height()/h); 
    } 

    public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination, 
            CancellationSignal cancellationSignal, WriteResultCallback callback) 
    { 
     PrintedPdfDocument.Page page = document.StartPage(0); 

     page.Canvas.Scale(scale, scale); 

     view.Draw(page.Canvas); 

     document.FinishPage(page); 

     WritePrintedPdfDoc(destination); 

     document.Close(); 

     document.Dispose(); 

     callback.OnWriteFinished(pages); 
    } 

    void WritePrintedPdfDoc(ParcelFileDescriptor destination) 
    { 
     var javaStream = new Java.IO.FileOutputStream(destination.FileDescriptor); 
     var osi = new OutputStreamInvoker(javaStream); 
     using (var mem = new MemoryStream()) 
     { 
      document.WriteTo(mem); 
      var bytes = mem.ToArray(); 
      osi.Write(bytes, 0, bytes.Length); 
     } 
    } 
} 
+0

'WebView'には、' PrintDocumentAdapter'を返す 'CreatePrintDocumentAdapter'というメソッドがあり、' PrintManager'インスタンスに渡されます。 – SushiHangover

+0

@SushiHangover thatsネイティブAndroid WebView :(Xamarin.Forms WebViewには、アンドロイドのみのものがありません。フォームをネイティブに変換する方法を知っていますか? – rrr

+1

ネイティブにアクセスする必要があります。 'WebView'コントロールには複数のオプションがあります...カスタムレンダラーを介して' native'コントロールを公開し、それを依存サービスに渡したり、ネイティブレンダラー自体にネイティブ印刷ルーチンを埋め込んだり、依存関係サービスを繰り返したりすることができます現在の 'Activity'(GetChildCount/GetChildAt/...)のすべての子ビューがネイティブのアンドロイド' WebView'を見つけて、 'CreatePrintDocumentAdapter'などを呼び出します。 – SushiHangover

答えて

1

です。

これは現在のAndroid.Webkir.WebViewを取得し、そこからprintAdapterを作成します。

正しい方向に私を向けるため@SushiHangoverに感謝します。

これはちょっとしたハックですが、私のニーズに合っています。

他にもこれが必要な人は、AndroidとiOSコードの両方が含まれています。

#if __ANDROID__ 
      var vRenderer = Xamarin.Forms.Platform.Android.Platform.GetRenderer(webview); 
      var viewGroup = vRenderer.ViewGroup; 

      for (int i = 0; i < viewGroup.ChildCount; i++) 
      { 
       if (viewGroup.GetChildAt(i).GetType().Name == "WebView") 
       { 
        var AndroidWebView = viewGroup.GetChildAt(i) as Android.Webkit.WebView; 
        var tmp = AndroidWebView.CreatePrintDocumentAdapter("print"); 
        var printMgr = (Android.Print.PrintManager)Forms.Context.GetSystemService(Android.Content.Context.PrintService); 
        printMgr.Print("print", tmp, null); 
        break; 
       } 
      } 
#elif __IOS__ 
      var printInfo = UIKit.UIPrintInfo.PrintInfo; 
      printInfo.Duplex = UIKit.UIPrintInfoDuplex.LongEdge; 
      printInfo.OutputType = UIKit.UIPrintInfoOutputType.General; 
      printInfo.JobName = "AppPrint"; 
      var printer = UIKit.UIPrintInteractionController.SharedPrintController; 
      printer.PrintInfo = printInfo; 
      printer.PrintingItem = Foundation.NSData.FromFile(pdfPath); 
      printer.ShowsPageRange = true; 
      printer.Present(true, (handler, completed, err) => 
      { 
       if (!completed && err != null) 
       { 
        System.Diagnostics.Debug.WriteLine("Printer Error"); 
       } 
      }); 
#endif 
関連する問題