สำหรับบทความนี้ขอต่อเนื่องจากบทความเดิมเสียหน่อย Screen Capture หรือ Capture ภาพบน Layout ผ่านโค้ด ซึ่งเป็นการแคปภาพหน้าจอในแอปพลิเคชันของผู้ที่หลงเข้ามาอ่าน

แต่ทว่าถ้าต้องการเซฟภาพที่เป็น Dialog ล่ะ? จะต้องทำยังไง? เพราะว่าคำสั่งจากบทความดังกล่าวนั้นไม่สามารถทำได้เลย ดังนั้นจึงเป็นที่มาของบทความนี้ที่จะเพิ่มเติมในส่วนที่ว่านี้

จุดสำคัญนั้นอยู่ที่การดึง View จาก Dialog มานั่นเอง ซึ่งจะมีคำสั่งดังนี้

Dialog dialog = ..... ... View dialogView = dialog.getWindow().getDecorView(); dialogView.setDrawingCacheEnabled(); Bitmap bm = Bitmap.createBitmap(dialogView.getDrawingCache()); dialogView.setDrawingCacheEnabled();


เท่านี้ก็จะได้ bm ที่เป็น Bitmap สำหรับภาพจาก Dialog แล้ว

ถ้าอยากได้ภาพทั้งหน้าจอและ Dialog ล่ะ?

สาเหตุที่เจ้าของบล็อกทำบทความนี้นั้นมาจากผู้ที่หลงเข้ามาอ่านท่านนึงได้ถามมาว่าจะบันทึกภาพหน้าจอทั้งๆที่มี Dialog แสดงอยู่ด้วยอย่างไร และเจ้าของบล็อกก็เห็นว่าน่าสนใจดีและบทความอันเก่าก็ไม่สามารถทำได้

สำหรับคำตอบของปัญหานี้ เจ้าของบล็อกใช้วิธีการเก็บภาพจากหน้าจอแอปพลิเคชันและ Dialog แยกกันเป็นสองส่วน (เพราะมันดันเก็บได้ทีละส่วนนี่สิ) เมิ่อได้ Bitmap ของทั้งสองส่วนแล้วก็ค่อยนำมาซ้อนกันนั่นเอง เท่านี้ก็ได้ภาพหน้าจอแอปพลิเคชันที่มี Dialog อยู่ด้วยแล้ว~

Dialog dialog = ..... // Get bitmap from root layout View view = findViewById(android.R.id.).getRootView(); view.setDrawingCacheEnabled(); Bitmap bm1 = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(); // Get bitmap from dialog layout View dialogView = dialog.getWindow().getDecorView(); dialogView.setDrawingCacheEnabled(true); Bitmap bm2 = Bitmap.createBitmap(dialogView.getDrawingCache()); dialogView.setDrawingCacheEnabled(); // Merge bitmap Bitmap bitmap = Bitmap.createBitmap(bm1.getWidth() , bm1.getHeight(), bm1.getConfig()); Canvas c = Canvas(bitmap); c.drawBitmap(bm1, Matrix(), ); c.translate((bm1.getWidth() / 2) - (bm2.getWidth() / 2) , (bm1.getHeight() / 2) - (bm2.getHeight() / 2)); c.drawBitmap(bm2, Matrix(), ); // Clear bitmap bm1.recycle(); bm2.recycle();


เท่านี้ก็จะได้ bitmap ที่เป็น Bitmap สำหรับภาพหน้าจอแอปพลิเคชันรวมไปถึง Dialog แล้ว

สำหรับตัวอย่างในบทความนี้ก็จะให้กดที่ภาพแล้วจะมี Dialog ขึ้นมาพร้อมกับมีปุ่ม Save ให้กดเพื่อบันทึกภาพ เมื่อผู้ใช้กดก็จะทำการบันทึกภาพเก็บไว้ในเครื่อง โดยจะอยู่ในโฟลเดอร์ Pictures ของเครื่อง ส่วนชื่อไฟล์ภาพที่บันทึกก็จะอิงจากเวลาและวันที่ ณ ตอนที่กดบันทึกภาพ

package app.akexorcist.screenshotdialog; java.io.ByteArrayOutputStream; java.io.File; java.io.FileNotFoundException; java.io.FileOutputStream; java.io.IOException; java.util.Date; android.app.Activity; android.app.Dialog; android.content.Intent; android.graphics.Bitmap; android.graphics.Canvas; android.graphics.Matrix; android.net.Uri; android.os.Bundle; android.os.Environment; android.text.format.DateFormat; android.view.View; android.view.View.OnClickListener; android.view.Window; android.widget.Button; android.widget.ImageView; android.widget.Toast;public class  Main Activity {protected void onCreate(Bundle savedInstanceState) { .onCreate(savedInstanceState); setContentView(R.layout.); ImageView imgDialog = (ImageView)findViewById(R.id.); imgDialog.setOnClickListener(OnClickListener() {public void  onClick(View v) { Dialog dialog = Dialog(Main.); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(R.layout.customdialog ); dialog.setCancelable(); Button btnSave = (Button)dialog.findViewById(R.id.); btnSave.setOnClickListener(OnClickListener() {public void  onClick(View v) { saveScreen(dialog); } }); dialog.show(); } }); }public void  saveScreen(Dialog dialog) { // Get bitmap from root layout View view = findViewById(android.R.id.).getRootView(); view.setDrawingCacheEnabled(); Bitmap bm1 = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(); // Get bitmap from dialog layout View dialogView = dialog.getWindow().getDecorView(); dialogView.setDrawingCacheEnabled(); Bitmap bm2 = Bitmap.createBitmap(dialogView.getDrawingCache()); dialogView.setDrawingCacheEnabled(); // Merge bitmap Bitmap bitmap = Bitmap.createBitmap(bm1.getWidth() , bm1.getHeight(), bm1.getConfig()); Canvas c = Canvas(bitmap); c.drawBitmap(bm1, Matrix(), null); c.translate((bm1.getWidth() / 2) - (bm2.getWidth() / 2) , (bm1.getHeight() / 2) - (bm2.getHeight() / 2)); c.drawBitmap(bm2, Matrix(), ); // Clear bitmap bm1.recycle(); bm2.recycle(); try { // Save bitmap to storage Date d = Date(); String filename = (String)DateFormat.format("hhmmss-MMddyyyy" , d.getTime()); File dir = File(Environment.getExternalStorageDirectory() , "/Pictures/" + filename + ".jpg"); FileOutputStream out = FileOutputStream(dir); ByteArrayOutputStream bos = ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat., 100, bos); out.write(bos.toByteArray()); // Clear bitmap bitmap.recycle(); // Update image to media system Intent intent =ACTION_MEDIA_SCANNER_SCAN_FILE ); intent.setData(Uri.fromFile(dir)); sendBroadcast(intent); Toast.makeText(getApplicationContext(), "Saved!" , Toast.LENGTH_SHORT ).show(); }new Intent(Intent.catch(FileNotFoundException e) { e.printStackTrace(); } (IOException e) { e.printStackTrace(); } } }


สำหรับในตัวอย่างเจ้าของบล็อกเพิ่มเข้าไปบางส่วน เพื่อให้รวมภาพทั้งสองเข้าด้วยกันแล้วทำการบันทึกภาพลงในเครื่อง แล้วทำการอัปเดตให้กับ Media Scanner เพื่อให้ภาพแสดงใน Gallery ทันที แล้วแสดงผ่าน Toast เพื่อให้รู้ว่าบันทึกภาพเรียบร้อยแล้ว และส่วนที่สำคัญก็คือการ Recycle เหล่า Bitmap ที่เก็บไว้ทั้งหลายครับ เมื่อ Bitmap ตัวไหนใช้เรียบร้อยแล้วก็ควรจะทำการ Recycle เพื่อเคลียร์หน่วยความจำซะ ไม่เช่นนั้นจะ Memory Leak

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.akexorcist.screenshotdialog" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".Main" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>