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 ?
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é.
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));
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.
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.
j'ai trouvé un moyen très facile, avec un exemple de travail simple et agréable ici
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
Façons d'afficher des GIF animés sur Android:
_ { 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.
J'ai eu beaucoup de mal à faire fonctionner un gif animé sous Android. J'en ai eu seulement deux après:
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):
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");
Utilisez ImageViewEx , une bibliothèque qui permet d’utiliser un gif aussi facilement que d’utiliser une variable ImageView
.
Glide
Bibliothèque Image Loader pour Android, recommandée par Google.
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 . Quelques liens importants-
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);
}
}
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é.
@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 .
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);
}
});
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.
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)
// 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:
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!
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
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:
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 .
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
Dessins pour dessiner des images animées (comme GIF).
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");
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);
//
}
});
}
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.
J'ai résolu ce problème en scindant gif dans des cadres et en utilisant l'animation Android standard
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.
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);