web-dev-qa-db-fra.com

Conversion d'une vue en bitmap sans l'afficher dans Android?

Je vais essayer d'expliquer ce que je dois faire exactement.

J'ai 3 écrans séparés dire A, B, C. Il existe un autre écran appelé HomeScreen dans lequel les 3 écrans bitmap doivent être affichés dans la vue Galerie et l'utilisateur peut sélectionner la vue dans laquelle il souhaite se rendre.

J'ai pu obtenir les bitmaps de tous les 3 écrans et les afficher en mode Galerie en plaçant tout le code dans l'activité HomeScreen uniquement. Maintenant, cela a beaucoup compliqué le code et j'aimerai le simplifier.

Ainsi, puis-je appeler une autre activité à partir de HomeScreen sans l'afficher, mais simplement obtenir le bitmap de cet écran. Par exemple, disons que je viens d'appeler HomeScreen et qu'il appelle les activités A, B, C et qu'aucune des activités de A, B, C ne s'affiche. Il donne juste le bitmap de cet écran par getDrawingCache (). Et ensuite, nous pouvons afficher ces bitmaps dans la vue Galerie de HomeScreen.

J'espère avoir expliqué le problème très clairement.

S'il vous plaît laissez-moi savoir si cela est réellement possible.

120
sunil

il existe un moyen de le faire. vous devez créer un bitmap et une toile et appeler view.draw (canvas);

voici le code:

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;
}

si la vue n'a pas été affichée, sa taille sera égale à zéro. Il est possible de le mesurer comme ceci:

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: selon this post , Passer WRAP_CONTENT Comme valeur à makeMeasureSpec() ne sert à rien (bien que pour certaines classes de vues cela fonctionne), et la méthode recommandée est:

// 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();
192
Simon Heinen

voici ma solution:

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;
}

Prendre plaisir :)

24
Gil SH

Essaye ça,

        /**
         * 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;
        }
20
Dwivedi Ji

Je sais que la question est peut-être périmée, mais j’avais de la difficulté à obtenir l’une de ces solutions pour qu’elle fonctionne pour moi. Plus précisément, j'ai constaté que si des modifications étaient apportées à la vue une fois gonflée, ces modifications ne seraient pas incorporées dans l'image bitmap rendue.

Voici la méthode qui a fini par fonctionner pour mon cas. Avec une mise en garde, cependant. avant d'appeler getViewBitmap(View), j'ai gonflé ma vue et lui ai demandé de disposer d'une mise en page avec des dimensions connues. Cela était nécessaire car ma disposition de vue le rendrait zéro hauteur/largeur jusqu'à ce que le contenu soit placé à l'intérieur.

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;
}

La "sauce magique" pour moi a été trouvée ici: https://groups.google.com/forum/#!topic/Android-developers/BxIBAOeTA1Q

À votre santé,

Levi

15
levigroker

J'espère que cela t'aides

View view="some view instance";        
view.setDrawingCacheEnabled(true);
Bitmap bitmap=view.getDrawingCache();
view.setDrawingCacheEnabled(false);

Mise à jour
La méthode getDrawingCache() est obsolète dans le niveau 28 de l'API. Recherchez donc une autre alternative pour le niveau> 28.

2
Akhilesh Kumar

Je pense que c'est un peu mieux:

/**
 * 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;
}

En utilisant le code ci-dessus, vous n'avez pas besoin de spécifier la taille du bitmap (utilisez 0 pour width & height) si vous voulez utiliser celui de la vue elle-même.

De même, si vous souhaitez convertir des vues spéciales (SurfaceView, Surface ou Window, par exemple) en bitmap, vous devez envisager d'utiliser PixelCopy classe à la place. Cela nécessite une API 24 et supérieure cependant. Je ne sais pas comment le faire avant.

0
android developer

Mise en page ou affichage en bitmap:

 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;
}

Méthode d'appel:

Bitmap src = createBitmapFromLayout(View.inflate(this, R.layout.sample, null)/* or pass your view object*/);
0
Shyam Kumar

Il existe une excellente fonction d’extension Kotlin dans Android KTX: View.drawToBitmap(Bitmap.Config) )

0
a.ch.