Um einen Screenshot einer View
zu erzeugen, wird gemeinhin empfohlen, den Drawing Cache der View zu missbrauchen, indem man ihn gegebenenfalls erzwingt und dann kopiert:
public class LameFooView extends SurfaceView { @NotNull public final Bitmap getScreenCopy() { boolean cacheEnabled = isDrawingCacheEnabled(); if (!cacheEnabled) buildDrawingCache(); Bitmap cache = getDrawingCache(); // <-- there be dragons Bitmap screenshot = new Bitmap(cache); // destroy the cache if it wasn't enabled, then return if(!cacheEnabled) destroyDrawingCache(); return screenshot; } }
Aus Gründen purer Gehässigkeit lieferte der Aufruf von getDrawingCache()
in meiner vererbten SurvaceView
allerdings immer null
, womit die ganze Aktion gestorben war.
Faszinierenderweise funktionierte stattdessen der Ansatz, die View
erneut auf eine eigene Bitmap
zu rendern, indem man der eigenen draw()
-Methode ein raubkopiertes Canvas
übergibt:
public class AwesomeFooView extends SurfaceView { @NotNull public final Bitmap getScreenCopy() { Bitmap bitmap = Bitmap.createBitmap( getWidth(), getHeight(), Bitmap.Config.ARGB_8888 ); Canvas temporaryCanvas = new Canvas(bitmap); draw(temporaryCanvas); // Voodoo. return bitmap; } }
Wer also vor einem ähnlichen Problem steht — so geht es auch.
Pro-Tipp
Wie der Dokumentation von View.draw()
zu entnehmen ist, muss die View zum Zeitpunkt des Abpausens bereits den Layout-Durchgang durchlaufen haben. Dies lässt sich mit einem gewissenhaften Aufruf von View.layout()
erzwingen:
measure(getWidth(), getHeight()); layout(0, 0, getWidth(), getHeight());
Problem gelöst.