【问题标题】:Taking Screenshot programmatically after orientation change方向更改后以编程方式截取屏幕截图
【发布时间】:2014-06-13 11:26:19
【问题描述】:

我正在开发一个应用程序,它会截取布局的屏幕截图,将其保存为 PDF,然后将其发送到通过 Google 云打印进行打印。一切正常,但我对屏幕截图的方向有疑问。

对于宿主片段,我做了横向和纵向布局。屏幕截图必须始终是纵向的,因此想法是以编程方式将屏幕旋转为纵向,截取屏幕截图,然后将屏幕方向设置回传感器。我用这种方法更改配置:

public void lockScreenOrientation(String orientation) {     
    if (orientation.contains("portrait")) {
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);            
    } else if (orientation.contains("auto")) {
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }
}

屏幕截图和 PDF 创建发生在 AsyncTask 中,由 Host Fragment 中的确认对话框触发

if (print) {            
        new AsyncPDF(mActivity).execute(field_client_name_txt, "birthday");
        prefs.edit().putBoolean("Print", false).commit();
}

当方向为纵向时,一切正常!当必须将方向旋转为纵向以进行屏幕截图和打印时,就会出现问题。 屏幕截图是横向而不是纵向的,最终的 pdf 乱七八糟并且被裁剪了!

这里是我的 Asynctask 供参考:

public class AsyncPDF extends AsyncTask<String, Void, Void> {

Activity mActivity;
Context mContext;

private static final int REQUEST_CODE = 4;

private static String SDCARD = Environment.getExternalStorageDirectory().getPath();
private static String DIRECTORY = SDCARD + "/Amorino";
private static String DIR_CACHE = DIRECTORY + "/Cache/";
private static String DIR_BIRTHDAY_ORDERS = DIRECTORY + "/Orders/Birthday/";
private static String DIR_WEDDING_ORDERS = DIRECTORY + "/Orders/Wedding/";
private static String DIR_OTHER_ORDERS = DIRECTORY + "/Orders/Other/";
private static String DIR_PRODUCTION = DIRECTORY + "/Production/";

String pdfName, pdfType = "";
Utils mUtility;

public AsyncPDF(Activity activity) {
    this.mActivity = activity;
    this.mContext = activity;
}

@Override
protected void onPreExecute() {
    mUtility = new Utils(mContext);
    Toast.makeText(mActivity, "Αποθήκευση αρχείου...", Toast.LENGTH_SHORT)
            .show();
        screenCapture();
};

@Override
protected Void doInBackground(String... params) {

    pdfName = params[0];
    pdfType = params[1];

    createPdf();

    return null;
}

@Override
protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);

}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    clearCacheFolder(); 
    Toast.makeText(mActivity, "Το αρχείο αποθηκέυτηκε επιτυχώς!",
            Toast.LENGTH_SHORT).show();

}

private void screenCapture() {

    try {

        ScrollView mLayoutRoot = (ScrollView) mActivity
                .findViewById(R.id.print_screen_layout);

        mLayoutRoot.setDrawingCacheEnabled(true);
        mLayoutRoot.buildDrawingCache();

        Bitmap mBitmap = mLayoutRoot.getDrawingCache();
        File file, f = null;
        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            file = new File(DIR_CACHE);
            if (!file.exists()) {
                file.mkdirs();
            }

            f = new File(file.getAbsolutePath() + File.separator
                    + "temp_layout" + ".png");
        }
        FileOutputStream ostream = new FileOutputStream(f);
        mBitmap.compress(CompressFormat.PNG, 10, ostream);
        ostream.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

}

private void createPdf() {

    Document document = new Document();
    Image header_img, main_img;
    InputStream inputStream_header = null;
    String current_directory = "";

    try {

        AssetManager mngr = mContext.getAssets();

        if (pdfType.contains("birthday")) {
            inputStream_header = mngr.open("header_birthday.png");
            current_directory = DIR_BIRTHDAY_ORDERS;
        } else if (pdfType.contains("wedding")) {
            inputStream_header = mngr.open("header_wedding.png");
            current_directory = DIR_WEDDING_ORDERS;
        } else if (pdfType.contains("other")) {
            inputStream_header = mngr.open("header_order.png");
            current_directory = DIR_OTHER_ORDERS;
        } else if (pdfType.contains("production")) {
            inputStream_header = mngr.open("header_order.png");
            current_directory = DIR_PRODUCTION;
        }

        File file = new File(current_directory);
        if (!file.exists()) {
            file.mkdirs();
        }

        PdfWriter.getInstance(document, new FileOutputStream(
                current_directory + "/" + pdfName + ".pdf"));
        document.open();

        Bitmap bmp = BitmapFactory.decodeStream(inputStream_header);
        ByteArrayOutputStream stream_header = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, stream_header);
        header_img = Image.getInstance(stream_header.toByteArray());
        header_img.scalePercent(24f);
        header_img.setAbsolutePosition(-1f, 750f);
        document.add(header_img);

        Paragraph paragraph = new Paragraph(
                header_img.getScaledHeight() + 50f);
        document.add(paragraph);

        main_img = Image.getInstance(DIR_CACHE
                + "/temp_layout.png");

        main_img.scaleToFit(520f, 2000f);
        main_img.setAlignment(Image.ALIGN_CENTER);

        Log.d("Original Width: ", String.valueOf(main_img.getWidth()));
        Log.d("Original Height ", String.valueOf(main_img.getHeight()));
        Log.d("Scaled Width: ", String.valueOf(main_img.getScaledWidth()));
        Log.d("Scaled Height ", String.valueOf(main_img.getScaledHeight()));

        document.add(main_img);

        document.close();
        File f = new File(current_directory + "/" + pdfName + ".pdf");
        printPdf(f, pdfName);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private void printPdf(File f, String name) {
    Uri docUri = Uri.fromFile(f);
    Intent printIntent = new Intent(mContext, PrintDialogActivity.class);
    printIntent.setDataAndType(docUri, "application/pdf");
    printIntent.putExtra("title", name + ".pdf");
    mActivity.startActivityForResult(printIntent, REQUEST_CODE);
}

private void clearCacheFolder() {
    File dir = new File(DIR_CACHE);
    if (dir.isDirectory()) {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++) {
            new File(dir, children[i]).delete();
        }
    }
}

}

我相信故障发生在 mActivity 参数上。我认为它通过原始横向布局而不是纵向布局的片段。我尝试使用存储在 SharedPreference 中的“打印”标志,然后从 onResume 方法执行 AsyncTask,但没有成功。屏幕截图仍然是横向布局。有什么想法吗?

我应该在片段生命周期的哪个时间点之后执行 AsyncTask 以获得正确的(纵向)布局?

附:问的第一个问题!!

【问题讨论】:

    标签: android android-fragments screenshot screen-orientation


    【解决方案1】:

    大约一周前我终于想通了,这就是解决方案!

    this answer 的提示解决了该问题。我添加了一个GlobalLayoutListener,以便在新布局解决后启动AsyncPDF类,问题几乎解决了。后来我不得不处理一个新问题......!

    现在 PDF 上打印了正确的布局,但某些 EditText 字段显示为空!!在经历了很多挫折、挠头和反复试验之后,我发现了问题所在。 GlobalLayoutListener 正在按预期工作,但似乎它启动打印功能有点太早了,因此字段没有时间正确绘制/填充。

    为了解决这个问题,我使用 Handler 类添加了一个最小延迟(100 毫秒),然后一切都按预期工作!下面是打印方法的代码:

    public void print(String orientation) {
    
        print = prefs.getBoolean("print", false);
    
        if (print)
            if (orientation.contains("portrait")) {
                new AsyncPDF(mActivity, v).execute(field_client_name_txt,
                        "birthday");
            } else {
                ViewTreeObserver observer = v.getViewTreeObserver();
                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        /* Adds a minimal wait time for the view to settle */
                        final Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                new AsyncPDF(mActivity, v).execute(
                                        field_client_name_txt, "birthday");
                            }
                        }, 100);
    
                        v.getViewTreeObserver().removeOnGlobalLayoutListener(
                                this);
                    }
                });
            }
        /* Reset the print flag to false */
        prefs.edit().putBoolean("print", false).commit();
    }
    

    该方法从 ActionBar 中的打印按钮启动,如果我们已经在 Portrait 中,它会启动 AsyncPDF 类 imm。在横向的情况下,它会等待纵向布局稳定​​,然后添加 100ms 的延迟,然后它会启动 AsyncTask。

    public void onClick(DialogInterface dialog, int id) {
         prefs.edit().putBoolean("print", true).commit();
         if (mUtility.getScreenOrientation() == 1)
              print("portrait");
         else
              mUtility.lockScreenOrientation("portrait");
         }
    });
    

    print(Stringorientation) 方法,放置在 onActivityCreated() 方法中,所以当配置发生变化时,它会检查打印标志是否被触发并采取相应的行动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2011-04-06
      相关资源
      最近更新 更多