Postaram się wyjaśnić, co dokładnie muszę zrobić.
Mam 3 oddzielne ekrany, na przykład A, B, C. Jest jeszcze jeden ekran o nazwie HomeScreen, na którym wszystkie 3 ekrany powinny być wyświetlane w widoku galerii, a użytkownik może wybrać, w którym widoku chce przejść.
Udało mi się uzyskać mapy bitowe wszystkich 3 ekranów i wyświetlić je w widoku galerii, umieszczając cały kod tylko w Aktywności ekranu głównego. To bardzo skomplikowało kod i chciałbym go uprościć.
Czy mogę więc wywołać inną aktywność z HomeScreen i nie wyświetlać jej, a po prostu pobrać mapę bitową tego ekranu. Na przykład, powiedzmy, że po prostu wywołuję HomeScreen i wywołuje działanie A, B, C i żadne działania z A, B, C nie są wyświetlane. Po prostu podaje bitmapę tego ekranu przez getDrawingCache (). Następnie możemy wyświetlić te mapy bitowe w widoku galerii w HomeScreen.
Mam nadzieję, że bardzo jasno wyjaśniłem problem.
Daj mi znać, jeśli jest to rzeczywiście możliwe.
Odpowiedzi:
jest na to sposób. musisz stworzyć Bitmapę i Canvas i wywołać view.draw (canvas);
oto kod:
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(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); v.draw(c); return b; }
jeśli widok nie został wyświetlony przed jego rozmiarem, będzie wynosił zero. Można to zmierzyć w ten sposób:
if (v.getMeasuredHeight() <= 0) { v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); v.draw(c); return b; }
EDIT: według tego postu , Przechodząc
WRAP_CONTENT
jako wartość namakeMeasureSpec()
nie coś dobrego (choć dla niektórych klas widzenia to działa), a metoda zalecana jest:// Either this int specWidth = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.AT_MOST); // Or this int specWidth = MeasureSpec.makeMeasureSpec(0 /* any */, MeasureSpec.UNSPECIFIED); view.measure(specWidth, specWidth); int questionWidth = view.getMeasuredWidth();
źródło
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
to działało poprawnie, ale dzięki za kod :)v.measure(0, 0); v.getMeasuredWidth(); v.getMeasuredHeight();
.Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Działa lepiejoto moje rozwiązanie:
public static Bitmap getBitmapFromView(View view) { Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(returnedBitmap); Drawable bgDrawable =view.getBackground(); if (bgDrawable!=null) bgDrawable.draw(canvas); else canvas.drawColor(Color.WHITE); view.draw(canvas); return returnedBitmap; }
Cieszyć się :)
źródło
Spróbuj tego,
/** * Draw the view into a bitmap. */ public static Bitmap getViewBitmap(View v) { v.clearFocus(); v.setPressed(false); boolean willNotCache = v.willNotCacheDrawing(); v.setWillNotCacheDrawing(false); // Reset the drawing cache background color to fully transparent // for the duration of this operation int color = v.getDrawingCacheBackgroundColor(); v.setDrawingCacheBackgroundColor(0); if (color != 0) { v.destroyDrawingCache(); } v.buildDrawingCache(); Bitmap cacheBitmap = v.getDrawingCache(); if (cacheBitmap == null) { Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException()); return null; } Bitmap bitmap = Bitmap.createBitmap(cacheBitmap); // Restore the view v.destroyDrawingCache(); v.setWillNotCacheDrawing(willNotCache); v.setDrawingCacheBackgroundColor(color); return bitmap; }
źródło
Wiem, że może to być nieaktualny problem, ale miałem problemy z uruchomieniem któregokolwiek z tych rozwiązań. W szczególności stwierdziłem, że jeśli w widoku zostaną wprowadzone jakiekolwiek zmiany po jego zawyżeniu, zmiany te nie zostaną uwzględnione w renderowanej mapie bitowej.
Oto metoda, która sprawdziła się w moim przypadku. Z jednym zastrzeżeniem. przed zadzwonieniem
getViewBitmap(View)
zawyżyłem swój widok i poprosiłem o układ ze znanymi wymiarami. Było to potrzebne, ponieważ mój układ widoku powodowałby zerową wysokość / szerokość do momentu umieszczenia treści w środku.View view = LayoutInflater.from(context).inflate(layoutID, null); //Do some stuff to the view, like add an ImageView, etc. view.layout(0, 0, width, height); Bitmap getViewBitmap(View view) { //Get the dimensions of the view so we can re-layout the view at its current size //and create a bitmap of the same size int width = view.getWidth(); int height = view.getHeight(); int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); //Cause the view to re-layout view.measure(measuredWidth, measuredHeight); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); //Create a bitmap backed Canvas to draw the view into Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); //Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas view.draw(c); return b; }
„Magiczny sos” dla mnie został znaleziony tutaj: https://groups.google.com/forum/#!topic/android-developers/BxIBAOeTA1Q
Twoje zdrowie,
Levi
źródło
measure()
ilayout()
zanim wypełniłem widok, więc miałem dziwne wyniki. Przenosząc te wywołania w dół, powyżejcreateBitmap()
naprawiłem to dla mnie!W systemie Android KTX jest świetna funkcja rozszerzenia Kotlin:
View.drawToBitmap(Bitmap.Config)
źródło
Układ lub widok do mapy bitowej:
private Bitmap createBitmapFromLayout(View tv) { int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); tv.measure(spec, spec); tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight()); Bitmap b = Bitmap.createBitmap(tv.getMeasuredWidth(), tv.getMeasuredWidth(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); c.translate((-tv.getScrollX()), (-tv.getScrollY())); tv.draw(c); return b; }
Metoda wywołania:
Bitmap src = createBitmapFromLayout(View.inflate(this, R.layout.sample, null)/* or pass your view object*/);
źródło
Mam nadzieję że to pomoże
View view="some view instance"; view.setDrawingCacheEnabled(true); Bitmap bitmap=view.getDrawingCache(); view.setDrawingCacheEnabled(false);
getDrawingCache()
Metoda aktualizacji jest przestarzała na poziomie API 28. Poszukaj więc innej alternatywy dla poziomu API> 28.źródło
getDrawingCache
jest obecnie przestarzały.Myślę, że to jest trochę lepsze:
/** * draws the view's content to a bitmap. code initially based on : * http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/ */ @Nullable public static Bitmap drawToBitmap(final View viewToDrawFrom, int width, int height) { boolean wasDrawingCacheEnabled = viewToDrawFrom.isDrawingCacheEnabled(); if (!wasDrawingCacheEnabled) viewToDrawFrom.setDrawingCacheEnabled(true); if (width <= 0 || height <= 0) { if (viewToDrawFrom.getWidth() <= 0 || viewToDrawFrom.getHeight() <= 0) { viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); width = viewToDrawFrom.getMeasuredWidth(); height = viewToDrawFrom.getMeasuredHeight(); } if (width <= 0 || height <= 0) { final Bitmap bmp = viewToDrawFrom.getDrawingCache(); final Bitmap result = bmp == null ? null : Bitmap.createBitmap(bmp); if (!wasDrawingCacheEnabled) viewToDrawFrom.setDrawingCacheEnabled(false); return result; } viewToDrawFrom.layout(0, 0, width, height); } else { viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight()); } final Bitmap drawingCache = viewToDrawFrom.getDrawingCache(); final Bitmap bmp = ThumbnailUtils.extractThumbnail(drawingCache, width, height); final Bitmap result = bmp == null || bmp != drawingCache ? bmp : Bitmap.createBitmap(bmp); if (!wasDrawingCacheEnabled) viewToDrawFrom.setDrawingCacheEnabled(false); return result; }
Używając powyższego kodu, nie musisz określać rozmiaru bitmapy (użyj 0 dla szerokości i wysokości), jeśli chcesz użyć jednego z samego widoku.
Ponadto, jeśli chcesz przekonwertować specjalne widoki (na przykład SurfaceView, Surface lub Window) na mapę bitową, powinieneś zamiast tego rozważyć użycie klasy PixelCopy . Wymaga jednak API 24 i nowszych. Wcześniej nie wiem, jak to zrobić.
źródło
view.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false);
źródło