web-dev-qa-db-fra.com

Afficher le GIF animé

Je souhaite afficher des images GIF animées dans mon application. Comme je l'ai découvert à la dure, Android ne prend pas en charge les images GIF animées de manière native.

Cependant, il peut afficher des animations avec AnimationDrawable :

Développez> Guides> Images et graphiques> Aperçu des tirages

L'exemple utilise une animation enregistrée en tant qu'images dans les ressources de l'application, mais ce dont j'ai besoin, c'est d'afficher directement un gif animé.

Mon plan est de casser le GIF animé en images et d'ajouter chaque image comme dessinable à AnimationDrawable.

Est-ce que quelqu'un sait comment extraire des images d'un GIF animé et les convertir en Drawable ?

234
Leonti

Android peut réellement décoder et afficher des GIF animés à l'aide de la classe Android.graphics.Movie.

Ce n'est pas trop documenté, mais se trouve dans SDK Reference . De plus, il est utilisé dans Exemples dans ApiDemos dans BitmapDecode example avec un indicateur animé.

183
Pointer Null

METTRE À JOUR:

Utilisez la glisse:

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.0.0'
}

usage:

Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));

voir docs

43
itzhar

aussi mettre (main/assets/htmls/name.gif) [avec ce html ajuster à la taille]

<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>

déclarez dans votre XML par exemple comme ceci (main/res/layout/name.xml): [vous définissez la taille, par exemple]

<WebView
Android:layout_width="70dp"
Android:layout_height="70dp"
Android:id="@+id/webView"
Android:layout_gravity="center_horizontal" />

dans votre activité, insérez le code suivant dans onCreate

web = (WebView) findViewById(R.id.webView); 
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///Android_asset/htmls/name.html");

si vous voulez charger dynamiquement, vous devez charger la vue Web avec des données:

// or "[path]/name.gif" (e.g: file:///Android_asset/name.gif for resources in asset folder), and in loadDataWithBaseURL(), you don't need to set base URL, on the other hand, it's similar to loadData() method.
String gifName = "name.gif";
String yourData = "<html style=\"margin: 0;\">\n" +
        "    <body style=\"margin: 0;\">\n" +
        "    <img src=" + gifName + " style=\"width: 100%; height: 100%\" />\n" +
        "    </body>\n" +
        "    </html>";
// Important to add this attribute to webView to get resource from outside.
webView.getSettings().setAllowFileAccess(true);

// Notice: should use loadDataWithBaseURL. BaseUrl could be the base url such as the path to asset folder, or SDCard or any other path, where your images or the other media resides related to your html
webView.loadDataWithBaseURL("file:///Android_asset/", yourData, "text/html", "utf-8", null);
// Or if you want to load image from SD card or where else, here is the idea.
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
webView.loadDataWithBaseURL(base + '/', yourData, "text/html", "utf-8", null);

suggestion: est préférable de charger gif avec des images statiques pour plus d'informations, consultez https://developer.Android.com/reference/Android/graphics/drawable/AnimationDrawable.html

Ça y est, j'espère que vous aidez.

28
Alex Zaraos

J'ai résolu le problème en scindant gif animations en images avant de l'enregistrer sur le téléphone. Je n'aurais donc pas à le gérer sous Android.

Ensuite, je télécharge chaque image sur le téléphone, crée Drawable à partir de celui-ci, puis crée AnimationDrawable - très similaire à l'exemple de ma question.

21
Leonti

j'ai trouvé un moyen très facile, avec un exemple de travail simple et agréable ici

afficher un widget animé

Avant de le faire fonctionner, il faut faire quelques modifications dans le code

DANS CE QUI SUIT

    @Override
    public void onCreate(Bundle savedInstanceState){    
        super.onCreate(savedInstanceStated);   
        setContentView(new MYGIFView());
    }    
}

il suffit de remplacer 

setContentView(new MYGIFView());

dans

setContentView(new MYGIFView(this));

ET EN

public GIFView(Context context) {
    super(context);

Fournissez votre propre fichier d'animation gif

    is = context.getResources().openRawResource(R.drawable.earth);
    movie = Movie.decodeStream(is);
}

REMPLACER LA PREMIÈRE LIGNE DE

public MYGIFView(Context context) {

selon le nom de la classe ...

après avoir fait ce petit changement ça devrait marcher comme pour moi ...

espérons que cette aide

16
Apperside

Façons d'afficher des GIF animés sur Android:

  • Classe de film. Comme mentionné ci-dessus, c'est assez buggy.
  • WebView. C'est très simple à utiliser et habituellement fonctionne. Mais parfois, il commence à mal se comporter, et c'est toujours sur des dispositifs obscurs que vous n'avez pas. De plus, vous ne pouvez pas utiliser plusieurs instances dans tout type d’affichage de liste, car cela a des effets sur votre mémoire. Néanmoins, vous pourriez le considérer comme une approche principale. 
  • Code personnalisé pour décoder les gifs en bitmaps et les afficher en tant que Drawable ou ImageView. Je mentionnerai deux bibliothèques:

_ { https://github.com/koral--/Android-gif-drawable } _ - le décodeur est implémenté en C, il est donc très efficace. 

https://code.google.com/p/giffiledecoder - le décodeur est implémenté en Java, ce qui facilite son utilisation. Toujours raisonnablement efficace, même avec des fichiers volumineux.

Vous trouverez également de nombreuses bibliothèques basées sur la classe GifDecoder. C'est aussi un décodeur basé sur Java, mais cela fonctionne en chargeant la totalité du fichier en mémoire, de sorte qu'il ne s'applique qu'aux petits fichiers.

9
Nick Frolov

J'ai eu beaucoup de mal à faire fonctionner un gif animé sous Android. J'en ai eu seulement deux après:

  1. WebView
  2. Ion

WebView fonctionne correctement et très facilement, mais le problème est qu’il ralentit le chargement des vues et que l’application ne répond plus pendant une seconde ou deux. Je n'ai pas aimé ça. J'ai donc essayé différentes approches (DID NOT WORK):

  1. ImageViewEx est obsolète!
  2. picasso n'a pas chargé de gif animé
  3. Android-gif-drawable est superbe, mais cela a causé des problèmes de connexion NDK dans mon projet. Cela a provoqué l'arrêt de la bibliothèque NDK locale et je n'ai pas pu le réparer.

J'avais quelques allers et retours avec Ion; Enfin, je le fais et c'est vraiment rapide :-)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///Android_asset/animated.gif");
8

Utilisez ImageViewEx , une bibliothèque qui permet d’utiliser un gif aussi facilement que d’utiliser une variable ImageView

7
NightSkyCode

Glide

Bibliothèque Image Loader pour Android, recommandée par Google.

  • Glide est assez similaire à Picasso mais c'est beaucoup plus rapide que Picasso.
  • Glide consomme moins de mémoire que Picasso.

Qu'est-ce que Glide a mais que Picasso n'a pas

La possibilité de charger une animation GIF dans un simple ImageView pourrait être la fonctionnalité la plus intéressante de Glide. Et oui, vous ne pouvez pas faire cela avec Picasso .  enter image description here Quelques liens importants-

  1. https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
7
Shoeb Siddique

Personne n'a mentionné la Ion ou Glide library. ils fonctionnent très bien.

C'est plus facile à manipuler qu'un WebView.

6
bapho

Essayez ceci, le code ci-dessous affiche le fichier gif dans la barre de progression

loading_activity.xml (dans le dossier Layout)

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/container"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="#ffffff" >

    <ProgressBar
        Android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        Android:layout_width="70dp"
        Android:layout_height="70dp"
        Android:layout_centerHorizontal="true"
        Android:layout_centerVertical="true"
        Android:indeterminate="true"
        Android:indeterminateDrawable="@drawable/custom_loading"
        Android:visibility="gone" />

</RelativeLayout>

custom_loading.xml (dans un dossier pouvant être dessiné)

ici je mets black_gif.gif (dans un dossier pouvant être dessiné), vous pouvez mettre votre propre gif ici

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:drawable="@drawable/black_gif"
    Android:pivotX="50%"
    Android:pivotY="50%" />

LoadingActivity.Java (dans le dossier res)

public class LoadingActivity extends Activity {

    ProgressBar bar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading);
        bar = (ProgressBar) findViewById(R.id.progressBar);
        bar.setVisibility(View.VISIBLE);

    }

}
5
nirav kalola

J'ai eu du succès avec la solution proposée dans cet article , une classe appelée GifMovieView, qui rend une View qui peut ensuite être affichée ou ajoutée à une ViewGroup spécifique. Découvrez les autres méthodes présentées dans les parties 2 et 3 de l'article spécifié. 

Le seul inconvénient de cette méthode est que l'anti-crénelage sur le film n'est pas très bon (il doit s'agir d'un effet secondaire de l'utilisation de la classe "shady" Android Movie). Il est alors préférable de définir l’arrière-plan sur une couleur unie dans votre GIF animé.

5
Dr1Ku

@PointerNull a donné une bonne solution, mais ce n'est pas parfait. Cela ne fonctionne pas sur certains appareils avec de gros fichiers et montre une animation Gif avec des images delta sur la version pré ICS . J'ai trouvé une solution sans ce bogue. C'est une bibliothèque avec un décodage natif à drawable: koral's Android-gif-drawable .

4
Sergei Vasilenko

Glide 4.6

1. Pour charger gif

GlideApp.with(context)
            .load(R.raw.gif) // or url
            .into(imageview);

2. Pour obtenir l'objet fichier

GlideApp.with(context)
                .asGif()
                .load(R.raw.gif) //or url
                .into(new SimpleTarget<GifDrawable>() {
                    @Override
                    public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {

                        resource.start();
                      //resource.setLoopCount(1);
                        imageView.setImageDrawable(resource);
                    }
                });
4
Gowsik K C

Quelques réflexions sur l’exemple BitmapDecode ... Il utilise essentiellement l’ancien, mais plutôt sans particularité Movie class de Android.graphics . Sur les versions récentes de l’API, vous devez désactiver l’accélération matérielle, comme décrit ici . C'était segfaulting pour moi autrement.

<activity
            Android:hardwareAccelerated="false"
            Android:name="foo.GifActivity"
            Android:label="The state of computer animation 2014">
</activity>

Voici l'exemple BitmapDecode abrégé avec uniquement la partie GIF. Vous devez créer votre propre widget (Voir) et le dessiner vous-même. Pas aussi puissant qu'un ImageView.

import Android.app.Activity;
import Android.content.Context;
import Android.graphics.*;
import Android.os.*;
import Android.view.View;

public class GifActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GifView(this));
    }

    static class GifView extends View {
        Movie movie;

        GifView(Context context) {
            super(context);
            movie = Movie.decodeStream(
                    context.getResources().openRawResource(
                            R.drawable.some_gif));
        }
        @Override
        protected void onDraw(Canvas canvas) {   
            if (movie != null) {
                movie.setTime(
                    (int) SystemClock.uptimeMillis() % movie.duration());
                movie.draw(canvas, 0, 0);
                invalidate();
            }
        }
    }
}

Deux autres méthodes, une avec ImageView, une autre avec WebView peuvent être trouvées dans ce bon tutoriel . La méthode ImageView utilise la licence Apache Android-gifview de Google Code.

4
lubosz

Placez-le dans une WebView, il doit pouvoir l'afficher correctement, car le navigateur par défaut prend en charge les fichiers gif. (Froyo +, si je ne me trompe pas)

2
keybee

Pour seulement l'API Android (Android Pie) 28 et +

utiliser AnimatedImageDrawable as

// ImageView from layout
val ima : ImageView = findViewById(R.id.img_gif)
// create AnimatedDrawable 
val decodedAnimation = ImageDecoder.decodeDrawable(
        // create ImageDecoder.Source object
        ImageDecoder.createSource(resources, R.drawable.tenor))
// set the drawble as image source of ImageView
ima.setImageDrawable(decodedAnimation)
// play the animation
(decodedAnimation as? AnimatedImageDrawable)?.start()

Code XML, ajouter un ImageView

<ImageView
    Android:id="@+id/img_gif"
    Android:background="@drawable/ic_launcher_background" <!--Default background-->
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    Android:layout_width="200dp"
    Android:layout_height="200dp" />

AnimatedImageDrawable est un enfant de Drawable et créé par ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawable qui nécessitait en outre l'instance de ImageDecoder.Source créée par ImageDecoder.createSource.

ImageDecoder.createSource ne peut prendre la source que comme nom, ByteBuffer, File, resourceId, URI, ContentResolver pour créer un objet source et l’utilise pour créer AnimatedImageDrawable en tant que Drawable (appel polymorphe)

static ImageDecoder.Source  createSource(AssetManager assets, String fileName)
static ImageDecoder.Source  createSource(ByteBuffer buffer)
static ImageDecoder.Source  createSource(File file)
static ImageDecoder.Source  createSource(Resources res, int resId)
static ImageDecoder.Source  createSource(ContentResolver cr, Uri uri)

Remarque: Vous pouvez également créer Bitmap à l’aide de ImageDecoder # decodeBitmap .

Sortie:

AnimatedDrawable prend également en charge le redimensionnement, la manipulation des cadres et des couleurs

2
Pavneet_Singh

Utilisez des fresques. Voici comment le faire:

http://frescolib.org/docs/animations.html

Voici le repo avec l'exemple:

https://github.com/facebook/fresco/tree/master/samples/animation

Attention, la fresque ne prend pas en charge le contenu!

1
Andrea Aranguren

Je pense que la meilleure librairie pour gérer les fichiers gif est celle-ci: by koral

Utilisé et j'ai du succès et cette bibliothèque est dédiée à GIF'S; mais où, comme picasso et glide sont un cadre d'image à usage général; donc je pense que les développeurs de cette bibliothèque se sont entièrement concentrés sur les fichiers gif

1
DJphy

Il y a deux options pour charger des gifs animés dans nos applications Android.

1) Utiliser Glide pour charger le gif dans une ImageView.

    String urlGif = "https://cdn.dribbble.com/users/263558/screenshots/1337078/dvsd.gif";
    //add Glide implementation into the build.gradle file.
    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    Uri uri = Uri.parse(urlGif);
    Glide.with(getApplicationContext()).load(uri).into(imageView);

2) Utiliser un html pour charger le gif dans une WebView

Créez le code HTML avec l'adresse dans le fichier .gif:

<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>

stockez ce fichier dans le répertoire assets:

 enter image description here

Le charger ce html dans la vue Web de votre application:

    WebView webView =  (WebView)findViewById(R.id.webView);
    webView = (WebView) findViewById(R.id.webView);
    webView.loadUrl("file:///Android_asset/html/webpage_gif.html");

Voici un exemple complet de de ces deux options .

 enter image description here

1
Elenasys

Je voulais juste ajouter que la classe Movie est maintenant obsolète. 

Cette classe était obsolète dans le niveau API P. 

Il est recommandé d’utiliser cette 

AnimatedImageDrawable

Dessins pour dessiner des images animées (comme GIF).

0
Sushobh Nadiger

Quelque chose que j'ai fait pour afficher des gifs dans les applications. J'ai étendu ImageView afin que les utilisateurs puissent utiliser ses attributs librement. Elle peut afficher les gifs à partir de l'URL ou du répertoire des actifs . La bibliothèque facilite également l'extension des classes pour en hériter et l'étendre pour prendre en charge différentes méthodes d'initialisation du gif.

https://github.com/Gavras/GIFView

Il y a un petit guide sur la page github.

Il a également été publié sur Android Arsenal:

https://Android-arsenal.com/details/1/4947

Exemple d'utilisation:

De XML:

<com.whygraphics.gifview.gif.GIFView xmlns:gif_view="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/main_activity_gif_vie"
        Android:layout_width="200dp"
        Android:layout_height="200dp"
        Android:scaleType="center"
        gif_view:gif_src="url:http://pop.h-cdn.co/assets/16/33/480x264/gallery-1471381857-gif-season-2.gif" />

Dans l'activité:

    GIFView mGifView = (GIFView) findViewById(R.id.main_activity_gif_vie);

    mGifView.setOnSettingGifListener(new GIFView.OnSettingGifListener() {
                @Override
                public void onSuccess(GIFView view, Exception e) {
                    Toast.makeText(MainActivity.this, "onSuccess()", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(GIFView view, Exception e) {

        }
});

Paramétrer le gif par programme:

mGifView.setGifResource("asset:gif1");
0
Tzlil Gavra

Manière la plus simple - Peut être considéré comme le code ci-dessous

Nous pouvons tirer parti de la méthode imageview setImageResource, reportez-vous au code ci-dessous.

Le code ci-dessous peut être utilisé pour afficher l'image comme gif si vous avez l'image divisée en plusieurs parties de gif. Séparez simplement le gif en png individuel à partir d'un outil en ligne et mettez l'image dans le dessin comme dans l'ordre ci-dessous

image_1.png, image_2.png, etc.

Demandez au gestionnaire de modifier l'image dynamiquement.

int imagePosition = 1;
    Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            public void run() {
                updateImage();
            }
        };




    public void updateImage() {

                appInstance.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        int resId = getResources().getIdentifier("image_" + imagePosition, "drawable", appInstance.getPackageName());
                        gifImageViewDummy.setImageResource(resId);
                        imagePosition++;
    //Consider you have 30 image for the anim
                        if (imagePosition == 30) {
//this make animation play only once
                            handler.removeCallbacks(runnable);

                        } else {
    //You can define your own time based on the animation
                            handler.postDelayed(runnable, 50);
                        }

//to make animation to continue use below code and remove above if else
// if (imagePosition == 30)
//imagePosition = 1;
// handler.postDelayed(runnable, 50);
// 
                    }
                });
              }
0
Lakshmanan

Tout d'abord, le navigateur Android devrait prendre en charge les GIF animés. Si ce n'est pas le cas, c'est un bug! Jetez un coup d'œil aux détecteurs de problème.

Si vous affichez ces GIF animés en dehors d'un navigateur, l'histoire peut être différente. Pour faire ce que vous demandez, vous aurez besoin d'une bibliothèque externe prenant en charge le décodage des fichiers GIF animés.

La première étape serait de regarder les API Java2D ou JAI (Java Advanced Imaging), bien que je serais très surpris que Android Dalvik prenne en charge ces bibliothèques dans votre application.

0
Eurig Jones

J'ai résolu ce problème en scindant gif dans des cadres et en utilisant l'animation Android standard

0
Raluca Lucaci

Semblable à ce que @Leonti a dit, mais avec un peu plus de profondeur: 

Ce que j'ai fait pour résoudre le même problème a été d'ouvrir GIMP, de masquer tous les calques sauf un, de l'exporter sous sa propre image, puis de masquer ce calque et de révéler le suivant, etc., jusqu'à ce que je dispose de fichiers de ressources individuels pour chacun. . Ensuite, je pourrais les utiliser comme images dans le fichier XML AnimationDrawable.

0
Jon O

Le moyen le plus simple d'afficher des GIF animés directement à partir d'une URL vers la présentation de votre application consiste à utiliser la classe WebView. 

Étape 1: Dans votre mise en page XML

<WebView
Android:id="@+id/webView"
Android:layout_width="50dp"
Android:layout_height="50dp"
/>

Étape 2: Dans votre activité

WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);

Étape 3: Dans votre manifeste Manifest.XML, autorisez Internet

<uses-permission Android:name="Android.permission.INTERNET" />

Étape 4: Si vous souhaitez rendre votre arrière-plan GIF transparent et l’adapter au mieux à votre mise en page

wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);

0
Ovais Chaudhry