I have done a sample painting app using APIDemo's FingerPaint app. Instead of the "usual" pattern of setContentView(R.layout.main) it uses a class MyView that extends View and sets content as setContentView(new MyView(this)); now whatever I draw I want to save it in the SDCard. For this I require to know the rootview using getRootView. This is got by the object of layout(for ex: LinearLayout L1 = new...) L1.getRootView. Because I am using this MyView, I am not able to get the rootview nor able to save the bitmap.
myview.setDrawingCacheEnabled(true);
myview.requestFocus();
myview.getRootView();
System.out.println("MYVIEW = "+myview);
myview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
myview.layout(0, 0, myview.getMeasuredWidth(), myview.getMeasuredHeight());
myview.buildDrawingCache(true);
mBitmap = myview.getDrawingCache();
//System.out.println("myview.getDrawingCache() = "+newview.getDrawingCache());
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
myview.setDrawingCacheEnabled(false); // clear drawing cache
System.out.println("BITMAP = "+mBitmap);
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg");
try {
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
} catch (Exception e)
{
e.printStackTrace();
}
I want to know how do I save my drawing using a menu button click?
Thank you
After a lot of effort into research I bumped into this http://blahti.wordpress.com/2010/11/18/how-to-save-jpeg-files-in-the-android-emulator/ This solved my issue of saving the drawing.
Related
I am trying to capture a "partial screenshot" to an image file by drawing a view to a bitmap canvas, so that it can then be shared.
There are some child views that are initially visible and I need to hide (e.g. the card holding the button that triggers this function), and some other views that are initially hidden and I only want to show in the outputted image (e.g. "Powered by..." text).
The code below is mostly working, but the views that are initially hidden and are being programmatically shown are not drawn to the canvas. The views that I'm programmatically hiding do get hidden and not drawn on the canvas but the layout isn't updated to account for the fact they're no longer visible (there's just a blank space where they were)
I've tried invalidate() and requestLayout(), but I don't think these do anything until the system decides to redraw, which doesn't happen until after I've drawn the view to the canvas.
How can I modify a view, capture it to an image, then return the view to it's initial state, without the user seeing those changes on screen (only in the captured image)?
binding.cardRecording.setVisibility(View.GONE);
binding.cardHistory.setVisibility(View.GONE);
binding.getRoot().setBackground(ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.snowflakes_background, null));
binding.getRoot().setBackgroundTintList(ColorStateList.valueOf(ColorUtils.setAlphaComponent(primaryColor, 20)));
binding.getRoot().setBackgroundTintMode(PorterDuff.Mode.SRC_OUT);
binding.tvHeader.setTextColor(ContextCompat.getColor(mContext, R.color.grey_font));
binding.tvHeader.setText(getName());
binding.tvHeader.setVisibility(View.VISIBLE);
binding.tvPoweredBy.setVisibility(View.VISIBLE);
binding.ivLogo.setVisibility(View.VISIBLE);
Bitmap bitmap;
Canvas canvas;
View view2 = binding.getRoot();
bitmap = Bitmap.createBitmap(view2.getWidth(), view2.getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
view2.draw(canvas);
File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File outFile = new File(storageDir, "temp.png");
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(outFile));
Uri uri = FileProvider.getUriForFile(mContext, fileprovider,outFile);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
// setting type to image
intent.setType("image/png");
// calling startactivity() to share
startActivity(Intent.createChooser(intent, "Share Via"));
} catch (FileNotFoundException e) {
}
binding.cardRecording.setVisibility(View.GONE);
binding.cardHistory.setVisibility(View.VISIBLE);
binding.getRoot().setBackground(null);
binding.tvHeader.setVisibility(View.GONE);
binding.tvPoweredBy.setVisibility(View.GONE);
binding.ivLogo.setVisibility(View.GONE);
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
i created screenshot for my activity in programatically.it work perfectly.i have problem in after taking shot the image showing in my activity.how to hide it?
Mycode :
public class MainActivity extends AppCompatActivity {
File cacheDir;
final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button print = (Button) findViewById(R.id.btn_print);
print.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takeScreenShot();
}
});
}
private void takeScreenShot() {
View u = findViewById(R.id.activity_main);
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
u.measure(spec, spec);
u.layout(0, 0, u.getMeasuredWidth(), u.getMeasuredHeight());
Bitmap b = getBitmapFromView(u,u.getMeasuredHeight(),u.getMeasuredWidth());
final String root = Environment.getExternalStorageDirectory().toString();
File myPath = new File(root + "/saved_img");
myPath.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+n+".jpg";
File file = new File(myPath, fname);
FileOutputStream fos = null;
if(file.exists()) file.delete();
try{
fos = new FileOutputStream(file);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch(FileNotFoundException e){
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
Toast.makeText(this,"screen captured",Toast.LENGTH_SHORT).show();
}
public Bitmap getBitmapFromView(View u, int totalHeight, int totalWidth){
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth,totalHeight , Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = u.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
u.draw(canvas);
return returnedBitmap;
}
}
how to solve this? my output image for before click button,
enter image description here
this is my output 2 for after click the button,
enter image description here
it's my mistake.after getting screenshot i set layout size on capturing image size(based on get measure width & height)i remove the below line in program it work perfectly.
u.layout(0, 0, u.getMeasuredWidth(), u.getMeasuredHeight());
because that line set saved image exact height & width into current layout.so that's error.i solved it.thanks for your help for all.thanks once again...
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bmp = Bitmap.createScaledBitmap(pdfBtm, (int) (pdfBtm.getWidth()), (int) (pdfBtm.getHeight()), true);
bmp.compress(CompressFormat.PNG, 0, stream);
byte[] byteArray = stream.toByteArray();
Image img = Image.getInstance(byteArray);
String pdffile = sharedPref.getString(com.appealsoft.i_file_me.Config.PdffileName, "");
int pageNumber = sharedPref.getInt(com.appealsoft.i_file_me.Config.PdfpageNumber, 0);
PdfReader reader = new PdfReader(pdffile);
String filename = pdffile.substring(pdffile.lastIndexOf("/") + 1, pdffile.length());
System.out.println("file name is :" + filename);
OutputStream newfile = new FileOutputStream(new File("/sdcard/" + filename));
Document newDocs = new Document();
PdfWriter writer = PdfWriter.getInstance(newDocs, newfile);
newDocs.open();
for (int i = 1; i <= reader.getNumberOfPages(); i++)
{
if (i == pageNumber)
{
Image img2 = Image.getInstance(byteArray);
newDocs.add(img2);
System.out.println(" i was inside...");
} else {
Image img2 = Image.getInstance(writer.getImportedPage(reader, i));
newDocs.add(img2);
}
}
newDocs.close();
When I create PDF with this method, contents of PDF get shifted to right side. For wider PDF pages, some of the part of page gets cut.
Anyone know why this is so?
When I create PDF with this method, contents of PDF get shifted to right side. For wider PDF pages, some of the part of page gets cut.
Anyone know why this is so?
Because that is what the code tells iText to do: It takes a complete page from some source document (including its margins) and adds it to the stuff iText is arranging in the body of a new page which already has its own margins.
The OP's actual objective seems to be to replace a single page in some document with some image. A PdfStamper or PdfCopy instance should be used for that.
E.g. using PdfStamper you could do something like this:
PdfReader reader = new PdfReader(SOURCE);
int pageToReplace = NROFPAGETOREPLACE;
List<Integer> pagesToKeep = new ArrayList<Integer>();
for (int i = 1; i <= reader.getNumberOfPages(); i++)
if (i != pageToReplace) pagesToKeep.add(i);
reader.selectPages(pagesToKeep);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(TARGET));
stamper.insertPage(pageToReplace, reader.getPageSizeWithRotation(1));
Image image = Image.getInstance(IMAGESOURCE);
stamper.getOverContent(pageToReplace).addImage(image, image.getWidth(), 0, 0, image.getHeight(), 30, 30);
stamper.close();
PS: Your comments seem to suggest that the image added to the new page actually encompasses all of it. In that case it is appropriate to replace the last lines of the example above with
Image image = Image.getInstance(IMAGESOURCE);
stamper.insertPage(pageToReplace, new Rectangle(image.getWidth(), image.getHeight());
stamper.getOverContent(pageToReplace).addImage(image, image.getWidth(), 0, 0, image.getHeight(), 0, 0);
stamper.close();
Is it possible to get the drawing cache with the views behind the view? For example, I have a semi-transparent view and I can see views behind it. So, can I get the drawing cache of this view with the behind views visible?
Code where I'm adding the view to WM:
final View screenshotView = new View(this) {
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!changed) {
buildDrawingCache();
final Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
final File file = new File("/sdcard/test.png");
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.close();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}
};
WindowManager.LayoutParams screenShotViewLp = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.RGBA_8888);
screenShotViewLp.width = WindowManager.LayoutParams.MATCH_PARENT;
screenShotViewLp.height = WindowManager.LayoutParams.MATCH_PARENT;
screenShotViewLp.gravity = Gravity.LEFT | Gravity.TOP;
wm.addView(screenshotView, screenShotViewLp);
[EDIT] according to last edits of the question I think this answer doesn't fit anymore. Adding a view directly to the WindowManager infact leads the discussion to a well-known problem: taking a screenshot programmatically in Android is not allowed, and then the idea exposed below seems totally impractical.
So please don't undervote.[/EDIT]
AFAIK this can't be achieved via the drawingCache of the single view. In order to get also the other views on the background you should take the drawingCache of the topmost node in the view tree, that is the content of the containing Activity. Getting such a bitmap is quite simple:
View root = currActivity.getWindow().getDecorView().findViewById(android.R.id.content);
root.setDrawingCacheEnabled(true);
Bitmap bmp = root.getDrawingCache();
Then, in order to get only the portion of bitmap you are interested in, you are forced to crop the generated bitmap according to View.getLocatonInWindow(int[]) values.
Haven't proved myself, but I'm quite confident it should work.
This is thebasic idea, but the image is ugly and pixelated. WHY???
public class Main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.iv);
Bitmap bmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_default_normal);
NinePatchDrawable npd = new NinePatchDrawable(bmap, bmap.getNinePatchChunk(), new Rect(0,0,512,512), "name");
npd.mutate();
npd.setBounds(new Rect(0,0,512,512));
npd.invalidateSelf();
Bitmap bp = Bitmap.createBitmap(512,512, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bp);
npd.draw(canvas);
FileOutputStream ofo=null;
try {
ofo = openFileOutput("image", MODE_WORLD_READABLE);
} catch (IOException e) {
e.printStackTrace();
}
bp.compress(Bitmap.CompressFormat.PNG, 100, ofo);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_STREAM, getFileStreamPath("image").toURI());
intent.setType("image/png");
//startActivity(intent);
iv.setImageDrawable(new BitmapDrawable(bp));
}
}
You're making it infinitely more complicated than it needs to be. Just set your view in the XML like so:
<TextView
android:background="#android:drawable/btn_default_small"
android:layout_width="512px"
android:layout_height="wrap_content"
android:text="NinePatch View"
/>
Just using TextView as an example. The same will work for an ImageView, a View, pretty much any widget. The important thing to remember is to use the background attribute instead of the src attribute for an ImageView. The src attribute will stretch the image as is, it won't respect the NinePatch data.
If you're set on doing it in code, just use:
iv.setBackgroundResource(R.drawable.btn_default_small)
As a side note, what device are you displaying it on? Most mobile phones only have up to 480 pixels for the width.