我正在开发一款应用程序,它可以截取布局的屏幕截图,将其保存为PDF格式,然后通过谷歌云打印将其发送。一切都很好,但我有一个问题,关于屏幕截图的方向。
对于主机片段,我做了一个横向和纵向布局。截图必须始终是纵向的,所以我们的想法是通过编程将屏幕旋转到纵向,截取截图,然后将屏幕方向设置回Sensor。我使用以下方法更改配置:
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中,这是由主机片段中的确认对话框触发的
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,以获得适当的(肖像)布局?
注:第一个问题!!
我终于在一个星期前弄明白了,这是解决方案!
这个问题用这个答案的提示解决了。我添加了一个GlobalLayoutListener,以便在新布局解决后启动AsyncPDF类,问题几乎解决了。后来我不得不处理一个新问题…!
PDF现在打印了正确的布局,但是一些EditText字段显示为空!!在经历了很多挫折、挠头和反复试验之后,我找到了问题所在。GlobalLayoutListener按预期工作,但似乎它启动打印功能有点太早了,因此字段没有时间被正确绘制/填充。
为了解决这个问题,我使用Handler类添加了最小延迟(100ms),之后一切都像他们应该的那样工作!下面是print方法的代码:
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(String orientation)方法,被放置在onActivityCreated()方法中,所以当配置发生变化时,它会检查打印标志是否被触发并相应地采取行动。