Visualizza GIF animate


261

Voglio visualizzare immagini GIF animate nella mia applicazione. Come ho scoperto nel modo più duro Android non supporta nativamente le GIF animate.

Tuttavia, è possibile visualizzare animazioni utilizzando AnimationDrawable :

Sviluppo> Guide> Immagini e grafica> Panoramica sui disegni

L'esempio utilizza l'animazione salvata come frame nelle risorse dell'applicazione ma ciò di cui ho bisogno è visualizzare direttamente GIF animate.

Il mio piano è di spezzare le GIF animate in cornici e aggiungere ogni cornice come disegnabile in AnimationDrawable.

Qualcuno sa come estrarre i frame dalle GIF animate e convertirli in Drawable ?


3
Intendi all'interno di Android o l'estrazione di frame da una gif con uno strumento esterno?
Osmund,

è sicuramente un bug, vedi IssueTracker per maggiori informazioni.
fbtb,

Solo per tutti coloro che sono venuti qui cercando un'app in grado di visualizzare GIF animate: quickPic
rubo77,


Usa affresco per visualizzare GIF github.com/facebook/fresco Penso che questa sia una soluzione semplice.
kaitian521,

Risposte:


191

Android in realtà può decodificare e visualizzare GIF animate, utilizzando la classe android.graphics.Movie.

Questo non è troppo documentato, ma è nel riferimento SDK . Inoltre, viene utilizzato negli esempi in ApiDemos nell'esempio BitmapDecode con alcuni flag animati.


9
Quanto è stabile questo? L'ho implementato nella mia app, sul mio dispositivo Ice Cream Sandwich non funziona affatto, su un emulatore 2.3 funziona ma alcuni dei frame GIF sono difettosi (colori sbagliati). Ovviamente su un computer funziona bene. Cosa dà?
Benoit Duffez,

12
@Bicou Sui dispositivi post-HC dovresti setLayerType(LAYER_TYPE_SOFTWARE)visualizzare. Ma funziona ancora solo per alcune gif e per alcuni dispositivi.
Michał K,

9
@ MichałK Grazie! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);lavorato!
Chloe,

1
@lubosz: LAYER_TYPE_SOFTWARE dovrebbe essere sufficiente per l'impostazione.
Puntatore Null

2
La classe del film non è documentata apposta - è debole e non supportata. Se hai bisogno di animazioni GIF adeguate, è meglio implementarle tu stesso. L'ho fatto per la mia app usando NDK.
Puntatore Null,

60

AGGIORNARE:

Usa planata:

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

utilizzo:

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

vedi documenti


1
Mi sembra OK ora, ovviamente la risposta non può includere l'intera libreria, quindi l'esempio di chiamata sembra abbastanza.
Gaborous,

@gaborous Ovviamente il codice non era incluso al momento della segnalazione.
Jan

1
Non consiglio di usare questa libreria se stai già utilizzando NDK. Dopo aver aggiunto questa libreria a gradle, un modulo Unity ha smesso di funzionare.
RominaV,

Questa è la migliore biblioteca che ho trovato. Una cosa in cui sono bloccato è l'implementazione del pizzico per ingrandire l'immagine gif. Qualcuno lo sa?
Viper,

28

put put (main / assets / htmls / name.gif) [con questo html aggiusta la dimensione]

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

dichiarare nel proprio Xml ad esempio in questo modo (main / res / layout / name.xml): [si definisce la dimensione, ad esempio]

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

nella tua attività inserisci il codice successivo all'interno di onCreate

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

se vuoi caricare dinamicamente devi caricare la webview con i dati:

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

suggerimento: è meglio caricare gif con immagini statiche per ulteriori informazioni consultare https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Ecco, spero che tu mi aiuti.


2
Se voglio caricare GIF da sdcard?
Jaydev,

se vuoi caricare da sdcard: sostituisci "file: ///android_asset/htmls/name.html" per l'uri della tua immagine
Alex Zaraos,

Utilizzando questo metodo, come posso cambiare dinamicamente il nome del file gif? Non voglio creare un file html per ogni gif che devo visualizzare nella mia app
scrayne,

Webview per una GIF?!? Hai pensato a prestazioni, consumo di memoria e batteria?
Duna,

@Duna di 5 anni fa, al momento possiamo usare glide per esempio
Alex Zaraos,

22

Ho risolto il problema suddividendo GIF animazioni in frame prima di salvarlo sul telefono, quindi non avrei dovuto affrontarlo in Android.

Quindi scarico ogni frame sul telefono, creo Drawable da esso e quindi creo AnimationDrawable - molto simile all'esempio della mia domanda


2
Qual è il modo documentato di gestire le animazioni.
RichieHH,

16

ho trovato un modo molto semplice, con un esempio di lavoro piacevole e semplice qui

mostra widget animati

Prima di farlo funzionare ci sono alcuni chages da fare nel codice

NEL SEGUENTE

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

basta sostituire

setContentView(new MYGIFView());

nel

setContentView(new MYGIFView(this));

E IN

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

Fornisci il tuo file di animazione gif

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

SOSTITUISCI LA PRIMA LINEA IN

public MYGIFView(Context context) {

secondo il nome della classe ...

dopo aver fatto questi piccoli cambiamenti dovrebbe funzionare come per me ...

spero che questo aiuto


2
Su quale versione di Android hai provato questo? Ho provato su Android versione 2.2 e 2.3 ma restituisce null oggetto Movie. Qualche idea di cosa può essere sbagliato?
Ashwini Shahapurkar,

16
Per favore ripulisci questa risposta, è così, casuale.
taxeeta,

2
qual è il problema con la risposta? Ho appena fornito un link e alcune correzioni necessarie per farlo funzionare
Apperside

10

Modi per mostrare GIF animate su Android:

  • Lezione di cinema. Come accennato in precedenza, è abbastanza difettoso.
  • WebView. È molto semplice da usare e di solito funziona. Ma a volte inizia a comportarsi male, ed è sempre su alcuni dispositivi oscuri che non hai. Inoltre, non è possibile utilizzare più istanze in qualsiasi tipo di vista elenco, perché fa cose nella memoria. Tuttavia, potresti considerarlo come un approccio primario.
  • Codice personalizzato per decodificare gif in bitmap e mostrarle come Drawable o ImageView. Citerò due biblioteche:

https://github.com/koral--/android-gif-drawable - il decoder è implementato in C, quindi è molto efficiente.

https://code.google.com/p/giffiledecoder - il decodificatore è implementato in Java, quindi è più facile da lavorare. Ancora ragionevolmente efficiente, anche con file di grandi dimensioni.

Troverai anche molte librerie basate sulla classe GifDecoder. Questo è anche un decodificatore basato su Java, ma funziona caricando l'intero file in memoria, quindi è applicabile solo a file di piccole dimensioni.


10

Ho avuto davvero delle difficoltà a far funzionare le gif animate su Android. Ho avuto solo due lavori seguenti:

  1. WebView
  2. ione

WebView funziona bene e è davvero semplice, ma il problema è che la visualizzazione si carica più lentamente e l'app non risponde per circa un secondo. Non mi è piaciuto. Quindi ho provato diversi approcci (DID NOT WORK):

  1. ImageViewEx è obsoleto!
  2. picasso non ha caricato gif animate
  3. android-gif-drawable sembra fantastico, ma ha causato alcuni problemi NDK cablati nel mio progetto. Ha causato l'interruzione del funzionamento della mia libreria NDK locale e non sono stato in grado di risolverlo

Ne ho avuti alcuni avanti e indietro Ion; Finalmente ce l'ho, ed è davvero veloce :-)

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

Ho avuto gli stessi problemi relativi all'NDK con android-gif-drawable.
RominaV,

Ciao @RominaV, hai usato la barra di avanzamento in Ion quando carica gif, perché devo mostrare i progressi quando carica gif.
patel135,

9

Glide 4.6

1. Per caricare gif

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

2. Per ottenere l'oggetto file

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

Libreria caricatore di immagini per Android, consigliata da Google.

  • Glide è abbastanza simile a Picasso, ma questo è molto più veloce di Picasso.
  • Glide consuma meno memoria di Picasso.

Quello che ha Glide ma Picasso no

La possibilità di caricare l'animazione GIF su un semplice ImageView potrebbe essere la caratteristica più interessante di Glide. E sì, non puoi farlo con Picasso. Alcuni link importantiinserisci qui la descrizione dell'immagine

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

Dove consiglia Google Glid?
Derzu,

1
Vedi questo, dove il team di sviluppatori Android ha usato Glide nella sua app di esempio. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique

1
"Glide è abbastanza simile a Picasso ma è molto più veloce di Picasso" e "Glide consuma meno memoria di Picasso." Spiacenti, non sono soddisfatto di queste idee, preferisci questo link: medium.com/@multidots/glide-vs-picasso-930eed42b81d . A proposito, non posso testare Glide 4.0 ora perché non riesco ad aggiornare build a 3.0.1 (connessione Internet lenta); ma ho provato Glide 3.5.2 a mostrare gif, funziona ma non perfettamente come mi aspettavo su img di grandi dimensioni (sfarfallio), e anche questo è un problema comune. Per favore, CMIW.
Nguyen Tan Dat,

7

Usa ImageViewEx , una libreria che semplifica l'utilizzo di un GIF come un ImageView.


Questo è stato deprecato
Martin Marconcini,

Ho esaminato questo codice delle librerie, dovrebbe essere valido per 2 o più anni.
NightSkyCode

1
Sì, penso che vada relativamente bene, sottolineando che l'autore ha deciso di deprecarlo. (e quindi non mantenerlo), indicando che dovremmo usare qualcosa come Picasso, il che è strano, perché Picasso è un downloader di immagini e non ti aiuterà quando si tratta di visualizzare un GIF animato più di qualsiasi dei tanti download / cache strumenti là fuori.
Martin Marconcini,

6

Prova questo, il codice qui sotto mostra il file gif nella barra di avanzamento

loading_activity.xml (nella cartella 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 (nella cartella disegnabile)

qui ho messo black_gif.gif (nella cartella disegnabile), puoi mettere la tua gif qui

<?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 (nella cartella 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);

    }

}

Ti vedo ruotare la gif. Perché?
AlikElzin-Kilaka,

Come puoi mettere GIF in una cartella disegnabile?
Apurva,

6

Nessuno ha menzionato la libreria Ion o Glide . funzionano molto bene.

È più facile da gestire rispetto a un WebView.


5

Ho avuto successo con la soluzione proposta in questo articolo , una classe chiamata GifMovieView, che rende un Viewche può quindi essere visualizzato o aggiunto a uno specificoViewGroup . Scopri gli altri metodi presentati nelle parti 2 e 3 dell'articolo specificato.

L'unico inconveniente di questo metodo è che l'antialiasing nel film non è così buono (deve essere un effetto collaterale dell'utilizzo della Movieclasse "ombreggiata" di Android ). È quindi meglio impostare lo sfondo su un colore solido all'interno della GIF animata.


4

Alcuni pensieri sull'esempio BitmapDecode ... Fondamentalmente usa l'antica, ma piuttosto informe classe Movie di android.graphics. Nelle versioni API recenti è necessario disattivare l'accelerazione hardware, come descritto qui . In caso contrario, è stato un segreto.

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

Ecco l'esempio BitmapDecode abbreviato con solo la parte GIF. Devi creare il tuo Widget (Visualizza) e disegnarlo da solo. Non abbastanza potente come 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 altri metodi, uno con ImageView un altro con WebView, sono disponibili in questo tutorial . Il metodo ImageView utilizza Android-gifview con licenza Apache da Google Code.


1
@luboz puoi per favore dirmi quale metodo è buono per le prestazioni di Android ... voglio usare GIF animate per la barra di caricamento della schermata iniziale. quindi puoi suggerire quale metodo è migliore. anche io voglio sapere che usando il metodo di visualizzazione delle immagini è possibile usare la proprietà del tipo di scala?
Swap-IOS-Android

4

@PointerNull ha dato una buona soluzione, ma non è perfetta. Non funziona su alcuni dispositivi con file di grandi dimensioni e mostra animazioni Gif buggy con frame delta nella versione pre ICS. Ho trovato una soluzione senza questi bug. È una libreria con decodifica nativa in drawable: koral's android-gif-drawable .


2

Inseriscilo in un WebView, deve essere in grado di visualizzarlo correttamente, poiché il browser predefinito supporta i file gif. (Froyo +, se non sbaglio)


Questo non è vero. Non tutti i browser supportano GIF.
RichieHH,

4
Speriamo di non aver bisogno di tutti i browser ... Il browser Stock lo supporta da Android 2.2, quindi non sottovalutarmi, per favore. Un WebView mostrerà sicuramente la GIF!
keybee,

2

Esistono due opzioni per caricare gif animate nelle nostre app Android

1) Usare Glide per caricare il GIF in un 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) Utilizzando un HTML per caricare GIF in a WebView

Crea l'html con l'indirizzo nel file .gif:

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

archivia questo file nella directory delle risorse:

inserisci qui la descrizione dell'immagine

Carica questo html nel WebView della tua applicazione:

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

Ecco un esempio completo di queste due opzioni .

inserisci qui la descrizione dell'immagine


2

Solo per API Android (Android Pie) 28 e +

usa AnimatedImageDrawable come

// 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()

Codice XML, aggiungi 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 è un figlio di Drawable e creato da ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawableche ha richiesto ulteriormente l'istanza di ImageDecoder.Sourcecreato da ImageDecoder.createSource.

ImageDecoder.createSourcepuò solo prendere l'origine come nome, ByteBuffer, File, resourceId, URI, ContentResolver per creare l'oggetto sorgente e lo usa per creare AnimatedImageDrawablecome Drawable(chiamata polimorfica)

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)

Nota: è anche possibile creare Bitmaputilizzando ImageDecoder # decodeBitmap .

Produzione:

AnimatedDrawable supporta anche il ridimensionamento, la manipolazione di cornici e colori


1

Penso che la migliore libreria per gestire i file GIF sia questa: di koral

L'ho usato e ho successo e questa libreria è dedicata a GIF'S; ma dove picasso e glide sono quadri di immagini generici ; quindi penso che gli sviluppatori di questa libreria si siano completamente concentrati sui file gif



1

Volevo solo aggiungere che la classe Movie è ora obsoleta.

Questa classe è stata deprecata nel livello API P.

Si consiglia di utilizzare questo

AnimatedImageDrawable

Disegnabile per disegnare immagini animate (come GIF).


1

Crea un pacchetto chiamato "Utils" nella cartella src e crea una classe chiamata "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");
        }
    }
}

Ora definisci GifImageView nel file 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);
    }
}

Ora UI Part File: 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>

Codice risorsa: esempio Android


come ridimensionare l'immagine, pls
The Dead Guy

0

Innanzitutto il browser Android dovrebbe supportare GIF animate. In caso contrario, è un bug! Dai un'occhiata ai tracker dei problemi.

Se stai visualizzando queste GIF animate al di fuori di un browser, potrebbe trattarsi di una storia diversa. Per fare ciò che stai chiedendo richiederebbe una libreria esterna che supporti la decodifica di GIF animate.

Il primo punto di riferimento sarebbe quello di guardare l'API Java2D o JAI (Java Advanced Imaging), anche se sarei molto sorpreso se Android Dalvik supportasse quelle librerie nella tua app.


alcuni dispositivi non mostrano gif animate, nemmeno su un browser web. ad esempio, so che galaxy mini con Android 2.3.6 non li mostra.
sviluppatore Android il

0

Simile a quello che ha detto @Leonti, ma con un po 'più di profondità:

Quello che ho fatto per risolvere lo stesso problema è stato aprire GIMP, nascondere tutti i livelli tranne uno, esportarlo come immagine propria, quindi nascondere quel livello e scoprire quello successivo, ecc., Fino a quando non ho avuto singoli file di risorse per ognuno . Quindi potrei usarli come frame nel file XML AnimationDrawable.


1
Puoi usare gifsicle per estrarre i frame se non hai molto tempo. Anche python o bash sono molto utili quando si generano file XML.
lubosz

0

Ho risolto questo problema dividendo GIF in frame e usando l'animazione Android standard


0

Qualcosa che ho fatto per mostrare gif nelle app. Ho esteso ImageView in modo che le persone possano usare liberamente i suoi attributi. Può mostrare gif dall'URL o dalla directory delle risorse. La libreria semplifica inoltre l'estensione delle classi da ereditare da essa e la estende per supportare diversi metodi per inizializzare il GIF.

https://github.com/Gavras/GIFView

C'è una piccola guida sulla pagina di github.

È stato anche pubblicato su Android Arsenal:

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

Usa esempio:

Da 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" />

Nell'attività:

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

        }
});

Impostazione gif a livello di codice:

mGifView.setGifResource("asset:gif1");

0

Il modo più semplice - Può essere considerato il codice seguente

Possiamo sfruttare Imageview setImageResource, fare riferimento al codice seguente per lo stesso.

Il codice seguente può essere usato per mostrare l'immagine come gif incase se hai l'immagine divisa in più di gif. Basta dividere la gif in png individuale da uno strumento online e mettere l'immagine nel disegno come nell'ordine seguente

image_1.png, image_2.png, ecc.

Chiedi al gestore di modificare l'immagine in modo dinamico.

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

Il modo semplice per visualizzare le GIF animate direttamente dall'URL al layout dell'app è utilizzare la classe WebView.

Passaggio 1: nel layout XML

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

Passaggio 2: nella tua attività

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

Passaggio 3: In Manifest.XML, autorizza Internet

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

Passaggio 4: Nel caso in cui si desideri rendere trasparente lo sfondo GIF e adattarlo al layout

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


Grazie per la soluzione alternativa, ma un considerevole sviluppatore potrebbe non voler avere un rendering non nativo a causa di alcune implicazioni come impatto sulla memoria, utilizzo della CPU e durata della batteria
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());

      }
    }
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.