Ich möchte animierte GIF-Bilder in meiner Anwendung anzeigen. __ Wie ich herausfand, wie schwierig es ist, dass Android animierte GIF-Dateien nicht nativ unterstützt.
Es können jedoch Animationen mit AnimationDrawable angezeigt werden:
Entwickeln> Hilfslinien> Bilder & Grafiken> Drawables-Übersicht
In diesem Beispiel werden Animationen verwendet, die als Frames in Anwendungsressourcen gespeichert sind, aber ich muss animierte GIFs direkt anzeigen.
Mein Plan ist es, animierte GIFs in Frames aufzuteilen und jeden Frame so zu zeichnen, dass er in AnimationDrawable gezeichnet werden kann.
Weiß jemand, wie Frames aus animierten GIF-Dateien extrahiert und in Drawable konvertiert werden?
Android kann mit der Klasse Android.graphics.Movie animierte GIFs dekodieren und anzeigen.
Dies ist nicht zu viel dokumentiert, befindet sich jedoch in SDK-Referenz . Außerdem wird es in Samples in ApiDemos im Beispiel BitmapDecode mit einem animierten Flag verwendet.
UPDATE:
Verwenden Sie Gleiten:
dependencies {
implementation 'com.github.bumptech.glide:glide:4.0.0'
}
verwendungszweck:
Glide.with(context).load(GIF_URI).into(new GlideDrawableImageViewTarget(IMAGE_VIEW));
auch put (main/assets/htmls/name.gif) [mit diesem html an die größe anpassen]
<html style="margin: 0;">
<body style="margin: 0;">
<img src="name.gif" style="width: 100%; height: 100%" />
</body>
</html>
deklarieren Sie in Ihrer XML-Datei zum Beispiel wie folgt (main/res/layout/name.xml): [Sie definieren zum Beispiel die Größe]
<WebView
Android:layout_width="70dp"
Android:layout_height="70dp"
Android:id="@+id/webView"
Android:layout_gravity="center_horizontal" />
geben Sie in Ihrer Aktivität den nächsten Code in onCreate ein
web = (WebView) findViewById(R.id.webView);
web.setBackgroundColor(Color.TRANSPARENT); //for gif without background
web.loadUrl("file:///Android_asset/htmls/name.html");
wenn Sie dynamisch laden möchten, müssen Sie die Webansicht mit Daten laden:
// 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);
vorschlag: Es ist besser, GIF mit statischen Bildern zu laden, um weitere Informationen zu erhalten. https://developer.Android.com/reference/Android/graphics/drawable/AnimationDrawable.html
Das war's, ich hoffe du hilfst.
Ich löste das Problem, indem ich gif -Animationen in Frames aufteilte, bevor ich es auf dem Telefon speichere, sodass ich mich in Android nicht damit befassen müsste.
Dann lade ich jeden Frame auf das Handy herunter, erstelle daraus Drawable und erstelle dann AnimationDrawable - sehr ähnlich dem Beispiel aus meiner Frage
ich fand einen sehr einfachen Weg mit einem Nizza und einfachen Arbeitsbeispiel hier
Bevor es funktioniert, gibt es einige Möglichkeiten, die im Code zu tun sind
IM FOLGENDEN
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceStated);
setContentView(new MYGIFView());
}
}
einfach austauschen
setContentView(new MYGIFView());
im
setContentView(new MYGIFView(this));
UND IN
public GIFView(Context context) {
super(context);
Stellen Sie Ihre eigene GIF-Animationsdatei bereit
is = context.getResources().openRawResource(R.drawable.earth);
movie = Movie.decodeStream(is);
}
ERSTE DIE ERSTE LINIE EIN
public MYGIFView(Context context) {
entsprechend dem Namen der Klasse ...
nach diesen kleinen Änderungen sollte es wie bei mir funktionieren ...
ich hoffe das hilft
Möglichkeiten, animiertes GIF auf Android anzuzeigen:
https://github.com/koral--/Android-gif-drawable - Der Decoder ist in C implementiert.
https://code.google.com/p/giffiledecoder - Der Decoder ist in Java implementiert und kann daher einfacher verwendet werden. Auch bei großen Dateien noch einigermaßen effizient.
Sie finden auch viele Bibliotheken, die auf der GifDecoder-Klasse basieren. Dies ist auch ein Java-basierter Decoder, aber es funktioniert, indem die gesamte Datei in den Arbeitsspeicher geladen wird, also nur für kleine Dateien.
Es fiel mir wirklich schwer, animierte GIFs in Android zu erstellen. Ich hatte nur folgende zwei Arbeiten:
WebView funktioniert gut und sehr einfach, aber das Problem ist, dass die Ansicht langsamer geladen wird und die App etwa eine Sekunde lang nicht reagiert. Ich mochte das nicht. Also habe ich verschiedene Ansätze ausprobiert (NICHT gearbeitet):
Ich hatte einiges hin und her mit Ion
; Endlich habe ich es funktioniert und es geht wirklich schnell :-)
Ion.with(imgView)
.error(R.drawable.default_image)
.animateGif(AnimateGifMode.ANIMATE)
.load("file:///Android_asset/animated.gif");
Verwenden Sie ImageViewEx , eine Bibliothek, die die Verwendung einer GIF so einfach wie die Verwendung einer ImageView
macht.
Glide
Image Loader Library für Android, empfohlen von Google.
Was dieser Glide hat, aber Picasso nicht
Die Möglichkeit, GIF-Animationen in eine einfache ImageView zu laden, ist möglicherweise die interessanteste Funktion von Glide. Und ja, mit Picasso ist das nicht möglich . Einige wichtige Links-
Versuchen Sie es mit dieser untenstehenden Code-Anzeige-GIF-Datei
loading_activity.xml (im Layoutordner)
<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 (im Zeichnungsordner)
hier lege ich black_gif.gif (in einem Ordner mit Zeichnungsfunktion) an. Sie können hier Ihr eigenes Gif einfügen
<?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 (im Ordner 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);
}
}
Ich hatte Erfolg mit der vorgeschlagenen Lösung in diesem Artikel , einer Klasse namens GifMovieView
, die eine View
rendert, die dann angezeigt oder einer bestimmten ViewGroup
hinzugefügt werden kann. Überprüfen Sie die anderen in den Abschnitten 2 und 3 des angegebenen Artikels beschriebenen Methoden.
Der einzige Nachteil dieser Methode ist, dass das Antialiasing des Films nicht so gut ist (muss ein Nebeneffekt der Verwendung der "zwielichtigen" Android-Klasse "Movie
" sein). Sie sollten den Hintergrund dann besser in Ihrer animierten GIF auf eine einfarbige Farbe einstellen.
@PointerNull gab eine gute Lösung, ist aber nicht perfekt. Auf einigen Geräten mit großen Dateien funktioniert es nicht und es wird eine fehlerhafte Gif-Animation mit Delta-Frames in der Version ICS angezeigt. Es ist eine Bibliothek mit nativer Decodierung zum Zeichnen: korals Android-Gif-Drawable .
Glide 4.6
1. gif laden
GlideApp.with(context)
.load(R.raw.gif) // or url
.into(imageview);
2. So erhalten Sie das Dateiobjekt
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);
}
});
Einige Überlegungen zum BitmapDecode-Beispiel ... Im Grunde verwendet es die uralte, aber eher unkomplizierte Movie -Klasse von Android.graphics .. Bei den letzten API-Versionen müssen Sie die Hardwarebeschleunigung ausschalten, wie hier beschrieben . Ansonsten war es für mich segfault.
<activity
Android:hardwareAccelerated="false"
Android:name="foo.GifActivity"
Android:label="The state of computer animation 2014">
</activity>
Hier ist das BitmapDecode-Beispiel nur mit dem GIF-Teil verkürzt. Sie müssen Ihr eigenes Widget (View) erstellen und es selbst zeichnen. Nicht ganz so mächtig wie eine 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 andere Methoden, eine mit ImageView, eine andere mit WebView, finden Sie in diesem feinen Tutorial . Die ImageView-Methode verwendet den von Apache lizenzierten Android-gifview von Google Code.
Legen Sie es in einem WebView ab. Es muss in der Lage sein, es korrekt anzuzeigen, da der Standardbrowser GIF-Dateien unterstützt. (Froyo +, wenn ich mich nicht irre)
// 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()
XML-Code, fügen Sie eine ImageView hinzu
<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
ist ein untergeordnetes Element von Drawable und wurde von ImageDecoder.decodeDrawable
erstellt.
ImageDecoder.decodeDrawable
, der außerdem die von ImageDecoder.Source
erstellte Instanz von ImageDecoder.createSource
erforderte.
ImageDecoder.createSource
kann Quelle nur als Name, ByteBuffer, File, resourceId, URI, ContentResolver zum Erstellen des Quellobjekts verwenden und verwendet es, um AnimatedImageDrawable
als Drawable
(polymorpher Aufruf) zu erstellen
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)
Hinweis: Sie können Bitmap
auch mit ImageDecoder # decodeBitmap erstellen.
Ausgabe:
AnimatedDrawable unterstützt auch die Größenanpassung, Rahmen- und Farbmanipulation
Verwenden Sie ein Fresko. So geht's:
http://frescolib.org/docs/animations.html
Hier ist das Repo mit der Probe:
https://github.com/facebook/fresco/tree/master/samples/animation
Vorsicht, Fresco unterstützt keine Wrap-Inhalte!
Ich denke, die bessere Bibliothek für GIF-Dateien ist diese: von koral
Ich habe es benutzt und bin erfolgreich. Diese Bibliothek ist GIF'S gewidmet. aber wo als picasso und gleiten sind allgemeine Bildrahmen; Ich denke, die Entwickler dieser Bibliothek haben sich ganz auf GIF-Dateien konzentriert
Es gibt zwei Möglichkeiten, animierte Gifs in unsere Android-Apps zu laden
1) Verwenden von Glide , um das Gif in eine ImageView
zu laden.
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) Verwenden eines HTML-Codes zum Laden des Gifs in eine WebView
Erstellen Sie die HTML-Datei mit der Adresse in der GIF-Datei:
<html style="margin: 0;">
<body style="margin: 0;">
<img src="https://..../myimage.gif" style="width: 100%; height: 100%" />
</body>
</html>
speichern Sie diese Datei im Assets-Verzeichnis:
Laden Sie diese HTML in das WebView Ihrer Anwendung:
WebView webView = (WebView)findViewById(R.id.webView);
webView = (WebView) findViewById(R.id.webView);
webView.loadUrl("file:///Android_asset/html/webpage_gif.html");
Heres ist ein komplettes Beispiel für diese beiden Optionen .
Ich wollte nur hinzufügen, dass die Movie Klasse jetzt veraltet ist.
Diese Klasse wurde auf API-Ebene P nicht mehr unterstützt.
Es wird empfohlen, dies zu verwenden
Zeichnet zum Zeichnen von animierten Bildern (wie GIF).
Etwas, was ich für das Anzeigen von GIFs in Apps getan habe. Ich habe ImageView erweitert, damit die Benutzer seine Attribute frei verwenden können. Es kann Gifs aus der URL oder aus dem Assets-Verzeichnis anzeigen .. Die Bibliothek macht es auch einfach, Klassen zu erweitern, um davon zu erben, und es so erweitern, dass verschiedene Methoden zur Initialisierung des GIF unterstützt werden.
https://github.com/Gavras/GIFView
Es gibt eine kleine Anleitung auf der Github-Seite.
Es wurde auch auf Android Arsenal veröffentlicht:
https://Android-arsenal.com/details/1/4947
Beispiel verwenden:
Aus 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" />
In der Tätigkeit:
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) {
}
});
Das programmgesteuerte Festlegen des GIF:
mGifView.setGifResource("asset:gif1");
Einfachste Möglichkeit - Der untenstehende Code kann berücksichtigt werden
Wir können Imageview setImageResource nutzen, siehe den gleichen Code.
Der folgende Code kann verwendet werden, um das Bild wie bei GIF anzuzeigen, wenn Sie ein mehrteiliges Bild von GIF haben. Teilen Sie einfach das GIF in ein einzelnes PNG aus einem Online-Tool auf und setzen Sie das Bild in die Zeichenfolge wie in der folgenden Reihenfolge
image_1.png, image_2.png usw.
Bitten Sie den Handler, das Bild dynamisch zu ändern.
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);
//
}
});
}
Zunächst sollte der Android-Browser Animated GIFs unterstützen. Wenn nicht, ist es ein Fehler! Schauen Sie sich die Issue-Tracker an.
Wenn Sie diese animierten GIFs außerhalb eines Browsers anzeigen, kann dies eine andere Geschichte sein. Um das zu tun, was Sie fragen, ist eine externe Bibliothek erforderlich, die die Decodierung von animierten GIFs unterstützt.
Der erste Anlaufpunkt wäre ein Blick auf die Java2D- oder JAI-API (Java Advanced Imaging), obwohl ich sehr überrascht wäre, wenn Android Dalvik diese Bibliotheken in Ihrer App unterstützt.
Ich löste dies, indem ich GIF in Frames aufteilte und Standard-Android-Animationen verwendete
Ähnlich wie bei @Leonti, aber mit etwas mehr Tiefe:
Was ich tat, um das gleiche Problem zu lösen, war das Öffnen von GIMP, das Ausblenden aller Ebenen mit Ausnahme einer Ebene, das Exportieren als eigenes Bild, das Ausblenden der Ebene und das Ausblenden der nächsten Ebene usw., bis ich für jedes einzelne Ressource-Dateien hatte . Dann könnte ich sie als Rahmen in der AnimationDrawable-XML-Datei verwenden.
Die einfachste Möglichkeit, animierte GIF-Dateien direkt von der URL zu Ihrem App-Layout anzuzeigen, ist die Verwendung der WebView-Klasse.
Schritt 1: In Ihrem Layout XML
<WebView
Android:id="@+id/webView"
Android:layout_width="50dp"
Android:layout_height="50dp"
/>
Schritt 2: In Ihrer Aktivität
WebView wb;
wb = (WebView) findViewById(R.id.webView);
wb.loadUrl("https://.......);
Schritt 3: Machen Sie in Ihrem Manifest.XML die Internet-Berechtigung
<uses-permission Android:name="Android.permission.INTERNET" />
Schritt 4: Wenn Sie Ihren GIF-Hintergrund transparent machen und GIF an Ihr Layout anpassen möchten
wb.setBackgroundColor(Color.TRANSPARENT);
wb.getSettings().setLoadWithOverviewMode(true);
wb.getSettings().setUseWideViewPort(true);