Afficher le GIF animé


261

Je souhaite afficher des images GIF animées dans mon application. Comme je l'ai découvert, Android ne prend pas en charge nativement les GIF animés.

Cependant, il peut afficher des animations en utilisant AnimationDrawable :

Développer> Guides> Images et graphiques> Présentation de Drawables

L'exemple utilise une animation enregistrée sous forme de cadres dans les ressources de l'application, mais ce dont j'ai besoin est d'afficher directement le gif animé.

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

Quelqu'un sait-il comment extraire des images d'un GIF animé et convertir chacune d'elles en Drawable ?


3
Voulez-vous dire dans Android, ou extraire des images d'un gif avec un outil externe?
Osmund

c'est définitivement un bug, voir IssueTracker pour plus d'informations.
fbtb

Juste pour tous ceux qui sont venus ici en recherchant une application qui peut afficher des GIF animés: quickPic
rubo77


Utilisez fresco pour afficher le GIF github.com/facebook/fresco Je pense que c'est une solution simple.
kaitian521

Réponses:


191

Android peut réellement décoder et afficher des GIF animés, en utilisant la classe android.graphics.Movie.

Ce n'est pas trop documenté, mais c'est dans la référence SDK . De plus, il est utilisé dans les exemples dans ApiDemos dans l' exemple BitmapDecode avec un indicateur animé.


9
Est-ce stable? Je l'ai implémenté dans mon application, sur mon appareil Ice Cream Sandwich, cela ne fonctionne pas du tout, sur un émulateur 2.3, cela fonctionne, mais certains des cadres GIF sont bogués (couleurs incorrectes). Sur un ordinateur, cela fonctionne bien sûr. Ce qui donne?
Benoit Duffez

12
@Bicou Sur les appareils post-HC, vous devriez setLayerType(LAYER_TYPE_SOFTWARE)sur votre vue. Mais cela ne fonctionne toujours que pour certains gifs et pour certains appareils.
Michał K

9
@ MichałK Merci! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);travaillé!
Chloé

1
@lubosz: LAYER_TYPE_SOFTWARE devrait suffire à définir.
Pointer Null

2
La classe de film n'est pas documentée exprès - elle est faible et non prise en charge. Si vous avez besoin d'animations Gif appropriées, vous feriez mieux de l'implémenter vous-même. Je l'ai fait pour mon application en utilisant NDK.
Pointer Null

60

METTRE À JOUR:

Utilisez glisse:

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

usage:

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

voir les documents


1
Ça me semble bien maintenant, évidemment la réponse ne peut pas inclure toute la bibliothèque, donc l'exemple d'appel semble suffisant.
gaborous

@gaborous De toute évidence, le code n'était pas inclus au moment du signalement.
Jan

1
Je ne recommande pas d'utiliser cette bibliothèque si vous utilisez déjà le NDK. Après avoir ajouté cette bibliothèque à gradle, un module Unity a cessé de fonctionner.
RominaV

Ceci est la meilleure bibliothèque que j'ai trouvée. Une chose dans laquelle je suis coincé est l'implémentation du pincement pour zoomer l'image gif. Est-ce que quelqu'un sait?
viper

28

également mis (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éclarer 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é, placez 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 le gif avec des images statiques pour plus d'informations, consultez https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Voilà, j'espère que vous m'aiderez.


2
Si je veux charger un GIF depuis une carte SD?
Jaydev

si vous voulez charger depuis sdcard: remplacez "file: ///android_asset/htmls/name.html" pour l'URI de votre image
Alex Zaraos

En utilisant cette méthode, comment puis-je changer le nom du fichier gif dynamiquement? Je ne veux pas créer un fichier html avec chaque gif que je dois afficher dans mon application
scrayne

Visualisation Web pour un GIF?!? Avez-vous pensé aux performances, à la consommation de mémoire et à la batterie?
Duna

@Duna qui était il y a 5 ans, actuellement nous pouvons utiliser glide par exemple
Alex Zaraos

22

J'ai résolu le problème en divisant les animations gif en images avant de l'enregistrer sur le téléphone, donc je n'aurais pas à le gérer dans 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


2
Quelle est la manière documentée de gérer les animations.
RichieHH

16

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 y a quelques chages à faire 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 EN

public MYGIFView(Context context) {

selon le nom de la classe ...

après avoir fait ces petits changements ça devrait marcher quant à moi ...

j'espère que cette aide


2
Sur quelle version Android vous avez essayé cela? J'ai essayé sur les versions Android 2.2 et 2.3, mais il renvoie l'objet Movie nul. Une idée de ce qui peut mal se passer?
Ashwini Shahapurkar

16
Veuillez nettoyer cette réponse, elle est donc aléatoire.
taxeeta

2
quel est le problème avec la réponse? Je viens de fournir un lien et quelques correctifs nécessaires pour le faire fonctionner
Apperside

10

Façons de montrer un GIF animé sur Android:

  • Cours de cinéma. Comme mentionné ci-dessus, c'est assez buggé.
  • WebView. C'est très simple à utiliser et généralement fonctionne . Mais parfois, il commence à mal se comporter, et il est toujours sur certains appareils obscurs que vous n'avez pas. De plus, vous ne pouvez pas utiliser plusieurs instances dans n'importe quel type d'affichage de liste, car cela fait des choses dans votre mémoire. Pourtant, 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, il est donc plus facile de travailler avec. Toujours assez efficace, même avec des fichiers volumineux.

Vous trouverez également de nombreuses bibliothèques basées sur la classe GifDecoder. C'est également un décodeur basé sur Java, mais il fonctionne en chargeant le fichier entier en mémoire, il n'est donc applicable qu'aux petits fichiers.


10

J'ai eu beaucoup de mal à avoir un gif animé fonctionnant sur Android. Je n'ai eu que deux travaux suivants:

  1. WebView
  2. Ion

WebView fonctionne correctement et très facilement, mais le problème est qu'il ralentit le chargement de la vue et que l'application ne répond plus pendant une seconde environ. Je n'ai pas aimé ça. J'ai donc essayé différentes approches (N'A PAS FONCTIONNÉ):

  1. ImageViewEx est obsolète!
  2. picasso n'a pas chargé le gif animé
  3. android-gif-drawable a fière allure, mais cela a causé des problèmes de NDK câblés dans mon projet. Cela a provoqué l'arrêt de ma bibliothèque NDK locale et je n'ai pas pu le réparer

J'ai eu des allers-retours avec Ion; Enfin, je le fais fonctionner, et c'est vraiment rapide :-)

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

J'ai eu les mêmes problèmes liés à NDK avec android-gif-drawable.
RominaV

Bonjour @RominaV, Avez-vous utilisé la barre de progression dans Ion lors du chargement de gif, car j'ai besoin de montrer la progression lors du chargement de gif.
patel135

9

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

8

Glide

Bibliothèque de chargement d'images 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.

Ce que Glide a, mais pas Picasso

La possibilité de charger une animation GIF sur une simple ImageView pourrait être la caractéristique la plus intéressante de Glide. Et oui, vous ne pouvez pas faire ça avec Picasso. Quelques liens importants-entrez la description de l'image ici

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

Où Google recommande-t-il Glid?
Derzu

1
Voir ceci, où l'équipe de développeur Android a utilisé Glide dans son exemple d'application. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique

1
«Glide est assez similaire à Picasso mais c'est beaucoup plus rapide que Picasso» et «Glide consomme moins de mémoire que Picasso». Désolé, je ne suis pas satisfait de ces idées, veuillez préférer ce lien: medium.com/@multidots/glide-vs-picasso-930eed42b81d . Btw, je ne peux pas tester Glide 4.0 maintenant car je ne peux pas mettre à niveau la version 3.0.1 (connexion Internet lente); mais j'ai testé Glide 3.5.2 sur l'affichage de gif, cela fonctionne mais pas parfaitement comme je m'y attendais sur les gros img (ça scintille), et c'est aussi un problème commun. Veuillez CMIW.
Nguyen Tan Dat

7

Utilisez ImageViewEx , une bibliothèque qui rend l'utilisation d'un gif aussi simple que l'utilisation d'un ImageView.


Ceci est obsolète
Martin Marconcini

J'ai regardé ce code de bibliothèques, il devrait être bon pendant environ 2 ans.
NightSkyCode

1
Oui, je pense que c'est relativement bien, soulignant simplement que l'auteur a décidé de le déprécier. (et donc ne pas le maintenir), soulignant que nous devrions utiliser quelque chose comme Picasso, ce qui est bizarre, car Picasso est un téléchargeur d'images et ne vous aidera pas plus lorsqu'il s'agit d'afficher un gif animé que n'importe lequel des nombreux téléchargements / cache outils là-bas.
Martin Marconcini

6

Essayez ceci, fichier gif d'affichage du code ci-dessous 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 le dossier dessinable)

ici je mets black_gif.gif (dans un dossier dessinable), 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);

    }

}

Je te vois faire pivoter le gif. Pourquoi?
AlikElzin-kilaka

Comment pouvez-vous mettre gif dans un dossier dessinable?
Apurva

6

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

Il est plus facile à gérer par rapport à une WebView.


5

J'ai eu du succès avec la solution proposée dans cet article , une classe appelée GifMovieView, qui rend un Viewqui peut ensuite être affiché ou ajouté à un spécifiqueViewGroup . 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'anticrénelage sur le film n'est pas si bon (cela doit être un effet secondaire de l'utilisation de la Movieclasse Android "ombragée" ). Il est alors préférable de définir l'arrière-plan sur une couleur unie dans votre GIF animé.


4

Quelques réflexions sur l'exemple BitmapDecode ... Fondamentalement, il utilise la classe Movie ancienne, mais plutôt sans particularité , provenant d'android.graphics. Sur les versions d'API récentes, vous devez désactiver l'accélération matérielle, comme décrit ici . Sinon, c'était une faute pour moi.

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

Voici l'exemple BitmapDecode raccourci avec seulement la partie GIF. Vous devez créer votre propre Widget (Affichage) et le dessiner par 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();
            }
        }
    }
}

2 autres méthodes, une avec ImageView et une autre avec WebView peuvent être trouvées dans ce fin tutoriel . La méthode ImageView utilise le android-gifview sous licence Apache de Google Code.


1
@luboz pouvez-vous s'il vous plaît me dire quelle méthode est bonne pour les performances Android ... je veux utiliser un gif animé pour la barre de chargement de l'écran de démarrage. pouvez-vous donc suggérer quelle méthode est la meilleure. Je veux aussi savoir qu'en utilisant la méthode de vue d'image, est-il possible d'utiliser la propriété de type échelle?
Swap-IOS-Android

4

@PointerNull a donné une bonne solution, mais ce n'est pas parfait. Il ne fonctionne pas sur certains appareils avec de gros fichiers et affiche une animation Gif buggée avec des images delta sur la version pré ICS. J'ai trouvé une solution sans ces bugs. C'est une bibliothèque avec un décodage natif vers drawable: android-gif-drawable de koral .


2

Mettez-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)


Ce n'est pas vrai. Tous les navigateurs ne prennent pas en charge GIF.
RichieHH

4
J'espère que nous n'avons pas besoin de tous les navigateurs ... Le navigateur Stock le prend en charge depuis Android 2.2, alors ne me votez pas, s'il vous plaît. Une WebView affichera certainement le GIF!
keybee

2

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

1) Utiliser Glide pour charger le gif dans un fichier 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 un WebView

Créez le html avec l'adresse du 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 des ressources:

entrez la description de l'image ici

Chargez ce html dans la WebView 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");

Heres est un exemple complet de ces deux options .

entrez la description de l'image ici


2

Uniquement pour l'API Android (Android Pie) 28 et +

utiliser AnimatedImageDrawable comme

// 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, ajoutez une 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.decodeDrawablequi nécessitait en outre l'instance de ImageDecoder.Sourcecréé par ImageDecoder.createSource.

ImageDecoder.createSourcepeut uniquement prendre la source comme nom, ByteBuffer, File, resourceId, URI, ContentResolver pour créer un objet source et l'utilise pour créer AnimatedImageDrawablecomme 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 à l' Bitmapaide d' ImageDecoder # decodeBitmap .

Production:

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


1

Je pense que la meilleure bibliothèque pour gérer les fichiers gif est celle-ci: par koral

Je l'ai utilisé et j'ai du succès et cette bibliothèque est dédiée aux GIF; mais où comme le picasso et le glissement 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

Je voulais juste ajouter que la classe Movie est désormais obsolète.

Cette classe est déconseillée au niveau API P.

Il est recommandé d'utiliser ce

AnimatedImageDrawable

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


1

Créez un package nommé «Utils» sous le dossier src et créez une classe nommée «GifImageView»

public class GifImageView extends View {
    private InputStream mInputStream;
    private Movie mMovie;
    private int mWidth, mHeight;
    private long mStart;
    private Context mContext;
    public GifImageView(Context context) {
        super(context);
        this.mContext = context;
    }
    public GifImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public GifImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        if (attrs.getAttributeName(1).equals("background")) {
            int id = Integer.parseInt(attrs.getAttributeValue(1).substring(1));
            setGifImageResource(id);
        }
    }
    private void init() {
        setFocusable(true);
        mMovie = Movie.decodeStream(mInputStream);
        mWidth = mMovie.width();
        mHeight = mMovie.height();
        requestLayout();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(mWidth, mHeight);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        long now = SystemClock.uptimeMillis();
        if (mStart == 0) {
            mStart = now;
        }
        if (mMovie != null) {
            int duration = mMovie.duration();
            if (duration == 0) {
                duration = 1000;
            }
            int relTime = (int) ((now - mStart) % duration);
            mMovie.setTime(relTime);
            mMovie.draw(canvas, 0, 0);
            invalidate();
        }
    }
    public void setGifImageResource(int id) {
        mInputStream = mContext.getResources().openRawResource(id);
        init();
    }
    public void setGifImageUri(Uri uri) {
        try {
            mInputStream = mContext.getContentResolver().openInputStream(uri);
            init();
        } catch (FileNotFoundException e) {
            Log.e("GIfImageView", "File not found");
        }
    }
}

Définissez maintenant GifImageView dans le fichier MainActivity: src / activity / MainActivity.class

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GifImageView gifImageView = (GifImageView) findViewById(R.id.GifImageView);
        gifImageView.setGifImageResource(R.drawable.smartphone_drib);
    }
}

Maintenant, le fichier de partie d'interface utilisateur: res / layout / activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:gravity="center"
    android:background="#111E39"
    tools:context=".Activity.MainActivity">
    <com.android.animatedgif.Utils.GifImageView
        android:id="@+id/GifImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

Code de ressource: exemple Android


comment redimensionner l'image, pls
The Dead Guy

0

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

Si vous affichez ces GIF animés en dehors d'un navigateur, cela pourrait être une autre histoire. Pour faire ce que vous demandez, il faudrait une bibliothèque externe qui prend en charge le décodage des GIF animés.

Le premier port d'escale serait d'examiner l'API Java2D ou JAI (Java Advanced Imaging), bien que je serais très surpris si Android Dalvik prendrait en charge ces bibliothèques dans votre application.


certains appareils n'affichent pas de gifs animés, même sur un navigateur Web. à titre d'exemple, je sais que galaxy mini avec android 2.3.6 ne les montre pas.
développeur Android

0

Similaire à 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 en tant que sa propre image, puis de masquer ce calque et d'afficher le suivant, etc., jusqu'à ce que j'aie des fichiers de ressources individuels pour chacun . Ensuite, je pourrais les utiliser comme images dans le fichier XML AnimationDrawable.


1
Vous pouvez utiliser gifsicle pour extraire les images si vous n'avez pas beaucoup de temps. Python ou bash sont également très utiles lors de la génération de fichiers xml.
lubosz

0

J'ai résolu cela en divisant le gif en cadres et en utilisant une animation Android standard


0

Quelque chose que j'ai fait pour afficher des gifs dans les applications. J'ai étendu ImageView pour que les gens puissent utiliser ses attributs librement. Il peut afficher des gifs depuis l'URL ou depuis le répertoire des ressources. La bibliothèque facilite également l'extension des classes pour en hériter et l'étendre pour prendre en charge différentes méthodes pour initialiser le 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) {

        }
});

Définition du gif par programme:

mGifView.setGifResource("asset:gif1");

0

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

Nous pouvons profiter d'Imageview setImageResource, reportez-vous au code ci-dessous pour la même chose.

Le code ci-dessous peut être utilisé pour afficher l'image comme gif incase si vous avez l'image divisée multiple de gif. Il suffit de diviser le gif en png individuel à partir d'un outil en ligne et de mettre l'image dans le dessin comme 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

La manière simple d'afficher le GIF animé directement à partir de l'URL dans la disposition 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 Manifest.XML, autorisez Internet

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

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

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


Merci pour la solution de contournement, mais un développeur considérable pourrait ne pas vouloir avoir un rendu non natif en raison de certaines implications comme l'impact sur la mémoire, l'utilisation du processeur et la durée de vie de la batterie
ruX


-8
public class Test extends GraphicsActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));
  }

  private static class SampleView extends View {
    private Bitmap mBitmap;
    private Bitmap mBitmap2;
    private Bitmap mBitmap3;
    private Bitmap mBitmap4;
    private Drawable mDrawable;

    private Movie mMovie;
    private long mMovieStart;

    // Set to false to use decodeByteArray
    private static final boolean DECODE_STREAM = true;

    private static byte[] streamToBytes(InputStream is) {
      ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
      byte[] buffer = new byte[1024];
      int len;
      try {
        while ((len = is.read(buffer)) >= 0) {
          os.write(buffer, 0, len);
        }
      } catch (java.io.IOException e) {
      }
      return os.toByteArray();
    }

    public SampleView(Context context) {
      super(context);
      setFocusable(true);

      java.io.InputStream is;
      is = context.getResources().openRawResource(R.drawable.icon);

      BitmapFactory.Options opts = new BitmapFactory.Options();
      Bitmap bm;

      opts.inJustDecodeBounds = true;
      bm = BitmapFactory.decodeStream(is, null, opts);

      // now opts.outWidth and opts.outHeight are the dimension of the
      // bitmap, even though bm is null

      opts.inJustDecodeBounds = false; // this will request the bm
      opts.inSampleSize = 4; // scaled down by 4
      bm = BitmapFactory.decodeStream(is, null, opts);

      mBitmap = bm;

      // decode an image with transparency
      is = context.getResources().openRawResource(R.drawable.icon);
      mBitmap2 = BitmapFactory.decodeStream(is);

      // create a deep copy of it using getPixels() into different configs
      int w = mBitmap2.getWidth();
      int h = mBitmap2.getHeight();
      int[] pixels = new int[w * h];
      mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
      mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_8888);
      mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
          Bitmap.Config.ARGB_4444);

      mDrawable = context.getResources().getDrawable(R.drawable.icon);
      mDrawable.setBounds(150, 20, 300, 100);

      is = context.getResources().openRawResource(R.drawable.animated_gif);

      if (DECODE_STREAM) {
        mMovie = Movie.decodeStream(is);
      } else {
        byte[] array = streamToBytes(is);
        mMovie = Movie.decodeByteArray(array, 0, array.length);
      }
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawColor(0xFFCCCCCC);

      Paint p = new Paint();
      p.setAntiAlias(true);

      canvas.drawBitmap(mBitmap, 10, 10, null);
      canvas.drawBitmap(mBitmap2, 10, 170, null);
      canvas.drawBitmap(mBitmap3, 110, 170, null);
      canvas.drawBitmap(mBitmap4, 210, 170, null);

      mDrawable.draw(canvas);

      long now = android.os.SystemClock.uptimeMillis();
      if (mMovieStart == 0) { // first time
        mMovieStart = now;
      }
      if (mMovie != null) {
        int dur = mMovie.duration();
        if (dur == 0) {
          dur = 1000;
        }
        int relTime = (int) ((now - mMovieStart) % dur);
        mMovie.setTime(relTime);
        mMovie.draw(canvas, getWidth() - mMovie.width(), getHeight()
            - mMovie.height());
        invalidate();
      }
    }
  }
}

class GraphicsActivity extends Activity {
  // set to true to test Picture
  private static final boolean TEST_PICTURE = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public void setContentView(View view) {
    if (TEST_PICTURE) {
      ViewGroup vg = new PictureLayout(this);
      vg.addView(view);
      view = vg;
    }

    super.setContentView(view);
  }
}

class PictureLayout extends ViewGroup {
  private final Picture mPicture = new Picture();

  public PictureLayout(Context context) {
    super(context);
  }

  public PictureLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public void addView(View child) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child);
  }

  @Override
  public void addView(View child, int index) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index);
  }

  @Override
  public void addView(View child, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, params);
  }

  @Override
  public void addView(View child, int index, LayoutParams params) {
    if (getChildCount() > 1) {
      throw new IllegalStateException(
          "PictureLayout can host only one direct child");
    }

    super.addView(child, index, params);
  }

  @Override
  protected LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int count = getChildCount();

    int maxHeight = 0;
    int maxWidth = 0;

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
      }
    }

    maxWidth += getPaddingLeft() + getPaddingRight();
    maxHeight += getPaddingTop() + getPaddingBottom();

    Drawable drawable = getBackground();
    if (drawable != null) {
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    }

    setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
        resolveSize(maxHeight, heightMeasureSpec));
  }

  private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
      float sy) {
    canvas.save();
    canvas.translate(x, y);
    canvas.clipRect(0, 0, w, h);
    canvas.scale(0.5f, 0.5f);
    canvas.scale(sx, sy, w, h);
    canvas.drawPicture(mPicture);
    canvas.restore();
  }

  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
    mPicture.endRecording();

    int x = getWidth() / 2;
    int y = getHeight() / 2;

    if (false) {
      canvas.drawPicture(mPicture);
    } else {
      drawPict(canvas, 0, 0, x, y, 1, 1);
      drawPict(canvas, x, 0, x, y, -1, 1);
      drawPict(canvas, 0, y, x, y, 1, -1);
      drawPict(canvas, x, y, x, y, -1, -1);
    }
  }

  @Override
  public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    location[0] = getLeft();
    location[1] = getTop();
    dirty.set(0, 0, getWidth(), getHeight());
    return getParent();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    final int count = super.getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != GONE) {
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        child.layout(childLeft, childTop,
            childLeft + child.getMeasuredWidth(),
            childTop + child.getMeasuredHeight());

      }
    }
  }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.