How to capture image of any layout in background - android

I want to send graphs in email. So for that I have captured bitmap of that graph and save it in sdcard as image. that works successfully
private Bitmap TakeImage(View v) {
Bitmap screen = null;
try {
v.setDrawingCacheEnabled(true);
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
screen = v.getDrawingCache();
v.setDrawingCacheEnabled(false); // clear drawing cache
} catch (Exception e) {
e.printStackTrace();
}
return screen;
}
But now I want to capture that in background without showing that layout, without notify by user. My previous code does not work for that.

Inflate the view using LayoutInflater, populate the values and pass it on to the same takeImage(View v) method.
I'm not sure, and I've not tried, don't know whether this works or not. but give it a try.

Have you tried changing v.getMeasuredWidth(), v.getMeasuredHeight() to whatever values you desire?

can you use
view.getLocationOnScreen(l);

Related

cannot seem to get bitmap from view in android

My problem is similar to the one in Android View.getDrawingCache returns null, only null.
My code used to work with the method
private Bitmap getBitmapFromView(View v) {
v.setDrawingCacheEnabled(true);
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false); // clear drawing cache
return b;
}
But today I changed the xml layout file. Since the change I have been getting NullPointerException at the line Bitmap b = Bitmap.createBitmap(v.getDrawingCache()). So I tried changing the method getBitmapFromView to
public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
But that didn't help. I get the null in the very first line.
The situation is this: I am trying to convert the view into a bitmap. But I am doing this without first displaying the view on screen. Again, this all used to work until I changed the content of the xml layout file. The change was not even that big. I just moved stuff around and removed -- yes removed -- some of the subviews.
In any case, I know for certain there is no problem with my layout file because I can display it on screen if I want; which I have done as part of troubleshooting.
Someone suggested using a handler to call getDrawingCache(). If that's the answer, how would I write that code?
UPDATE
View view = activity.getLayoutInflater().inflate(R.layout.my_view, null, false);
findViewsByIds(view);//where I inflate subviews and add content to them.
Execute createBitmapFromView when the view is measured.
public static void executeWhenViewMeasured(final View view, final Runnable runnable) {
if(view.getMeasuredHeight() == 0 || view.getMeasuredWidth() == 0){
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
runnable.run();
removeGlobalOnLayoutListener(view, this);
}
});
} else {
runnable.run();
}
}
public static Bitmap createBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void removeGlobalOnLayoutListener(View view,
ViewTreeObserver.OnGlobalLayoutListener listener) {
try {
view.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
} catch (NoSuchMethodError e) {
view.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
}
}
executeWhenViewMeasured(view, new Runnable() {
#Override
public void run() {
Bitmap bitmap = createBitmapFromView(view);
}
});
Since you are not showing the view it's easier to just draw the view on a canvas.
You are already trying to do that but I would merge both methods into one without using drawing cache.
private Bitmap getBitmapFromView(View v) {
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredWidth());
Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredWidth(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
Also check that MeasureSpec.UNSPECIFIED may not work well without the view in layout so you may need to specify a width and height.

Saving View bitmap with getDrawingCache gives a black image

Everything I tried with setDrawingCacheEnabled and getDrawingCache was not working. The system was making an image but it just looked black.
Other people on SO seemed to be having a similar problem but the answers seemed either too complicated or irrelevant to my situation. Here are some of the ones I looked at:
Save view like bitmap, I only get black screen
Screenshot shows black
getDrawingCache always returns the same Bitmap
Convert view to bitmap on Android
bitmap is not saving properly only black image
Custom view converting to bitmap returning black image
And here is my code:
view.setDrawingCacheEnabled(true);
Bitmap bitmap = view.getDrawingCache();
try {
FileOutputStream stream = new FileOutputStream(getApplicationContext().getCacheDir() + "/image.jpg");
bitmap.compress(CompressFormat.JPEG, 80, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
view.setDrawingCacheEnabled(false);
I'm sharing my answer below in case anyone else makes the same mistake I did.
My problem was that my view was a TextView. The text on the TextView was black (naturally) and in the app the background looked white. However, I later recalled reading that a view's background is by default transparent so that whatever color is below shows through.
So I added android:background="#color/white" to the layout xml for the view and it worked. When I had been viewing the image before I had been looking at black text over a black background.
See the answer by #BraisGabin for an alternate way that does not require overdrawing the UI.
I just found a good option:
final boolean cachePreviousState = view.isDrawingCacheEnabled();
final int backgroundPreviousColor = view.getDrawingCacheBackgroundColor();
view.setDrawingCacheEnabled(true);
view.setDrawingCacheBackgroundColor(0xfffafafa);
final Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheBackgroundColor(backgroundPreviousColor);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
view.setDrawingCacheEnabled(cachePreviousState);
Where 0xfffafafa is the desired background color.
Used below code to get bitmap image for view it work fine.
public Bitmap loadBitmapFromView(View v) {
DisplayMetrics dm = getResources().getDisplayMetrics();
v.measure(View.MeasureSpec.makeMeasureSpec(dm.widthPixels,
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(dm.heightPixels,
View.MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap returnedBitmap =
Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
v.draw(c);
return returnedBitmap;
}

Convert ExpandableListview to bitmap

I am unable to get bitmap of expandable listview
This is what I tried
private Bitmap convertViewToBitMap() {
View printlayout = (View) getActivity().findViewById(R.id.expandableList);
printlayout.setDrawingCacheEnabled(true);
printlayout.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
printlayout.layout(0, 0, printlayout.getMeasuredWidth(),
printlayout.getMeasuredHeight());
printlayout.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(printlayout.getDrawingCache());
printlayout.setDrawingCacheEnabled(false); // clear drawing cache
return b;
}
Following method helped me
private Bitmap convertViewToBitMap() {
View printlayout = (View) getActivity().findViewById(R.id.expandableList);
printlayout.setDrawingCacheEnabled(true);
Bitmap b = printlayout.getDrawingCache();
return b;
}
I think all you need it to get the hold of the view and convert that view into the bitmap and then print the bitmap.
You can get the view using findViewById();
For converting view into bitmap, a quick google may help more, but i found this
And once you have bitmap, do what ever you want.
#Pietu1998 pointed correctly, also show your attempt so reduce chance for downvoting.
You can re-draw your list into a bitmap which you can then use.
Here I'm issuing a re-draw on an instance variable mListView and then using that bitmap for my ImageView. Note that I'm using a Handler to force the re-draw on the UI thread.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Bitmap bitmap = Bitmap.createBitmap(mListView.getWidth(),
mListView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
mListView.draw(canvas);
// Do something the
((ImageView)mContext.findViewById(R.id.img)).setImageBitmap(bitmap);
}
}, 1);
Also note that you will need to have the ImageView inside of your xml already and the ListView not taking up all the space in the layout.

Achartengine create bitmap from chart always null

I tried various methods after googling for hours. Some of the methods seem to help some people, but not for me. What am I missing here? Maybe a permission? I know this is a common bug or something, but there must be a solution.
All the methods are similar.
First:
GraphicalView v = ChartFactory.getBarChartView(ChartsDuration.this, buildBarDataset(titles, values), renderer, Type.DEFAULT);
v.setDrawingCacheEnabled(true);
v.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
v.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(v.toBitmap()); //bitmap is null
v.setDrawingCacheEnabled(false);
or this:
Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache()); //bitmap is null
I also tried the solution here which is:
v.setDrawingCacheEnabled(true);
// this is the important code :)
// Without it the view will have a dimension of 0,0 and the bitmap will be null
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false); // clear drawing cache
Then the method on the bottom of this page:
v.setDrawingCacheEnabled(false);
if (!v.isDrawingCacheEnabled()) {
v.setDrawingCacheEnabled(true);
}
if (renderer.isApplyBackgroundColor()) {
v.setDrawingCacheBackgroundColor(renderer.getBackgroundColor());
}
v.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
v.getDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
I also did not get any luck with this:
v.setDrawingCacheEnabled(true);
v.requestFocus();
v.getRootView();
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
Bitmap mBitmap = v.getDrawingCache();
The bitmaps are always null.
just an idea , not sure if it would work:
put the Achartengine view in another view (a frameLayout , for example) , and then capture it instead of the Achartengine view.
also , sure your code runs only after some time , that all of the views have drawn themselves? in order to check it , try getting the width or height of the view.
you also don't have any exceptions or special logs?

Android -- Displaying background WebView as a Bitmap

I would like to load a webview in the background and only display a bitmap of the page it loads. I have a webview in my view hierarchy that has visibility set to "invisible" and an imageview that I wish to display a bitmap of the webview.
imageView = (ImageView)findViewById(R.id.imageview);
webView = (WebView)findViewById(R.id.webview);
webView.setBackgroundColor(Color.parseColor("#006330"));
webView.setDrawingCacheEnabled(true);
webView.loadDataWithBaseURL(SiteAPI.URL, html, "text/html", "iso-8859-1", null);
webView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
Bitmap b = webView.getDrawingCache();
webView.setDrawingCacheEnabled(false);
if(b != null) {
Toast.makeText(getBaseContext(), "Not null", Toast.LENGTH_LONG).show();
imageView.setImageBitmap(Bitmap.createBitmap(b));
}
else {
Toast.makeText(getBaseContext(), "Null.", Toast.LENGTH_LONG).show();
}
The call to getDrawingCache() returns null everytime. I've tried setContentView(webView) and the page displays fine. I've made sure that isDrawingCacheEnabled() returns true, yet the bitmap is still null. Where am I going wrong?
You have two options:
Use webView.capturePicture() method, but note that this will return a picture of the whole webpage, so you have to crop it to display just the part that you want.
Manually draw your webView in the Canvas object you want, using webView.draw(Canvas).

Categories

Resources