Exibir GIF animado

261

Quero exibir imagens GIF animadas em minha aplicação. Como descobri da maneira mais difícil, o Android não suporta GIF animado nativamente.

No entanto, ele pode exibir animações usando o AnimationDrawable :

Desenvolver> Guias> Imagens e gráficos> Visão geral de Drawables

O exemplo usa animação salva como quadros nos recursos do aplicativo, mas o que eu preciso é exibir gif animado diretamente.

Meu plano é dividir o GIF animado em quadros e adicionar cada quadro como extraível ao AnimationDrawable.

Alguém sabe como extrair quadros de GIF animado e converter cada um deles em Drawable ?

Leonti
fonte
3
Você quer dizer no android, ou extrair quadros de um gif com uma ferramenta externa?
Osmund
definitivamente é um bug, consulte o IssueTracker para obter mais informações.
Fbtb
Apenas para todos aqueles que veio aqui procurando por um aplicativo que pode exibir GIFs animados: QuickPic
rubo77
Use afresco para exibir GIF github.com/facebook/fresco Acho que essa é uma solução simples.
kaitian521

Respostas:

191

O Android pode decodificar e exibir GIFs animados, usando a classe android.graphics.Movie.

Isso não está muito documentado, mas está na Referência do SDK . Além disso, é usado em exemplos no ApiDemos no exemplo BitmapDecode com algum sinalizador animado.

Ponteiro nulo
fonte
9
Quão estável é isso? Eu o implementei no meu aplicativo, no meu dispositivo Ice Cream Sandwich ele não está funcionando, em um emulador 2.3 está funcionando, mas alguns dos quadros GIF estão com erros (cores incorretas). Em um computador, é claro que está funcionando bem. O que da?
Benoit Duffez
12
@Bicou Nos dispositivos pós-HC, você deve estar setLayerType(LAYER_TYPE_SOFTWARE)no seu modo de exibição. Mas ainda funciona apenas para alguns gifs e para alguns dispositivos.
Michał K
9
@ MichałK Obrigado! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);trabalhou!
Chloe
1
@lubosz: LAYER_TYPE_SOFTWARE deve ser suficiente para definir.
Ponteiro Nulo
2
A aula de cinema não é documentada de propósito - é fraca e sem suporte. Se você precisar de animações GIF adequadas, é melhor implementá-lo. Eu fiz isso para o meu aplicativo usando NDK.
Pointer Null
60

ATUALIZAR:

Use planar:

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

uso:

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

ver documentos

itzhar
fonte
1
Parece bom para mim agora, obviamente, a resposta não pode incluir toda a biblioteca, portanto o exemplo de chamada parece suficiente.
gaborous
@gaborous Obviamente, o código não foi incluído no momento da sinalização.
Jan
1
Não recomendo usar esta biblioteca se você já estiver usando o NDK. Após adicionar esta lib ao gradle, um módulo do Unity parou de funcionar.
RominaV 5/07
Esta é a melhor biblioteca que encontrei. Uma coisa que eu estou preso é implementar pitada para ampliar a imagem gif. Alguém sabe?
víbora
28

coloque também (main / assets / htmls / name.gif) [com este html ajustado ao tamanho]

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

declare no seu XML por exemplo assim (main / res / layout / name.xml): [você define o tamanho, por exemplo]

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

em sua atividade, coloque o próximo código dentro do onCreate

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

se você deseja carregar dinamicamente, é necessário carregar a visualização da web com dados:

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

sugestão: é melhor carregar gif com imagens estáticas para obter mais informações, consulte https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

É isso, espero que você ajude.

Alex Zaraos
fonte
2
Se eu quiser carregar o GIF do sdcard?
Jaydev 31/05
se você deseja carregar a partir do sdcard: substitua "file: ///android_asset/htmls/name.html" pelo uri da sua imagem
Alex Zaraos
Usando esse método, como posso alterar o nome do arquivo gif dinamicamente? Eu não quero fazer um arquivo html para ir com todos os gif eu preciso para exibir em meu aplicativo
scrayne
Visualização da Web para um GIF?!? Você pensou em desempenho, consumo de memória e bateria?
Duna
@Duna que foi há 5 anos, atualmente podemos usar glide, por exemplo
Alex Zaraos
22

Resolvi o problema dividindo animações gif em quadros antes de salvá-lo no telefone, para que eu não tivesse que lidar com isso no Android.

Em seguida, faço o download de todos os quadros no telefone, crio Drawable a partir dele e, em seguida, crio AnimationDrawable - muito semelhante ao exemplo da minha pergunta

Leonti
fonte
2
Qual é a maneira documentada de lidar com animações.
18714 RichieHH
16

eu encontrei uma maneira muito fácil, com um exemplo de trabalho simples e agradável aqui

exibir widget animado

Antes de fazê-lo funcionar, há algumas mudanças no código

NA SEQUÊNCIA

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

apenas substitua

setContentView(new MYGIFView());

no

setContentView(new MYGIFView(this));

E EM

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

Forneça seu próprio arquivo de animação gif

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

SUBSTITUIR A PRIMEIRA LINHA EM

public MYGIFView(Context context) {

de acordo com o nome da classe ...

depois de fazer essas pequenas mudanças, deve funcionar como para mim ...

espero que isso ajude

Apperside
fonte
2
Em qual versão do Android você tentou isso? Eu tentei no Android versão 2.2 e 2.3, mas ele retorna o objeto Movie nulo. Alguma idéia do que pode estar errado?
Ashwini Shahapurkar
16
Por favor, limpe esta resposta, é tão aleatória.
Taxeeta #
2
qual é o problema com a resposta? Eu só forneceu um link e alguns correção necessária para fazê-lo funcionar
Apperside
10

Maneiras de mostrar GIF animado no Android:

  • Aula de cinema. Como mencionado acima, é bastante incorreto.
  • WebView. É muito simples de usar e geralmente funciona. Mas às vezes começa a se comportar mal, e sempre está em alguns dispositivos obscuros que você não possui. Além disso, você não pode usar várias instâncias em nenhum tipo de exibição de lista, porque isso faz coisas em sua memória. Ainda assim, você pode considerá-lo como uma abordagem primária.
  • Código personalizado para decodificar gifs em bitmaps e mostrá-los como Drawable ou ImageView. Vou mencionar duas bibliotecas:

https://github.com/koral--/android-gif-drawable - o decodificador é implementado em C, por isso é muito eficiente.

https://code.google.com/p/giffiledecoder - o decodificador é implementado em Java, para facilitar o trabalho. Ainda razoavelmente eficiente, mesmo com arquivos grandes.

Você também encontrará muitas bibliotecas baseadas na classe GifDecoder. Esse também é um decodificador baseado em Java, mas funciona carregando o arquivo inteiro na memória, sendo aplicável apenas a arquivos pequenos.

Nick Frolov
fonte
10

Eu tive muita dificuldade em ter gifs animados trabalhando no Android. Eu só tinha dois trabalhos seguintes:

  1. WebView
  2. Íon

O WebView funciona bem e é muito fácil, mas o problema é que isso torna a exibição mais lenta e o aplicativo não responde por um segundo ou mais. Eu não gostei disso. Então, eu tentei abordagens diferentes (não funcionou):

  1. ImageViewEx está obsoleto!
  2. picasso não carregou gif animado
  3. O android-gif-drawable parece ótimo, mas causou alguns problemas de NDK com fio no meu projeto. Isso fez com que minha biblioteca NDK local parasse de funcionar e não consegui corrigi-lo

Eu tive algumas idas e vindas com Ion; Finalmente, eu estou trabalhando, e é muito rápido :-)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///android_asset/animated.gif");
Roozbeh Zabihollahi
fonte
Eu tive os mesmos problemas relacionados ao NDK com android-gif-drawable.
RominaV 5/07
Olá @RominaV, Você usou a barra de progresso no Ion ao carregar o gif, porque eu preciso mostrar o progresso ao carregar o gif.
precisa saber é o seguinte
9

Glide 4.6

1. Para carregar gif

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

2. Para obter o objeto de arquivo

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);
                    }
                });
Gowsik KC
fonte
8

Glide

Biblioteca do Image Loader para Android, recomendada pelo Google.

  • O deslize é bastante semelhante ao Picasso, mas é muito mais rápido que o Picasso.
  • Glide consome menos memória que Picasso.

O que esse Glide tem, mas Picasso não

A capacidade de carregar animação GIF em um simples ImageView pode ser o recurso mais interessante do Glide. E sim, você não pode fazer isso com Picasso. Alguns links importantes -insira a descrição da imagem aqui

  1. https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
Shoeb Siddique
fonte
Onde o Google recomenda o Glid?
Derzu
1
Veja isso, onde a equipe do desenvolvedor Android usou o Glide em seu aplicativo de amostra. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique
1
'Glide é bem parecido com Picasso, mas é muito mais rápido que Picasso' e 'Glide consome menos memória que Picasso'. Desculpe, não estou satisfeito com essas idéias. Por favor, prefira este link: medium.com/@multidots/glide-vs-picasso-930eed42b81d . Aliás, não posso testar o Glide 4.0 agora por não poder atualizar a versão 3.0.1 (conexão lenta à Internet); mas testei o Glide 3.5.2 em mostrar gif, ele funciona, mas não perfeitamente, como eu esperava em imagens grandes (está piscando), e esse também é um problema comum. Por favor, CMIW.
Nguyen Tan Dat
7

Use o ImageViewEx , uma biblioteca que torna o uso de um gif tão fácil quanto o uso de um ImageView.

NightSkyCode
fonte
Isso foi preterido
Martin Marconcini
Eu olhei através deste código de bibliotecas, deve ser bom por 2 ou mais anos.
NightSkyCode
1
Sim, acho que é relativamente bom, apenas apontando que o autor decidiu preteri-lo. (e, portanto, não mantê-lo), indicando que devemos usar algo como o Picasso, o que é estranho, porque o Picasso é um downloader de imagens e não o ajudará quando for exibir um gif animado mais do que qualquer um dos muitos downloads / cache ferramentas lá fora.
Martin Marconcini 5/05
6

Tente isso, abaixo o código exibe o arquivo gif na barra de progresso

loading_activity.xml (na pasta 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 (na pasta extraível)

aqui eu coloquei black_gif.gif (na pasta drawable), você pode colocar seu próprio gif aqui

<?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 (na pasta 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);

    }

}
nirav kalola
fonte
Vejo você girar o gif. Por quê?
AlikElzin-Kilaka
Como você pode colocar gif na pasta drawable?
Apurva
6

Ninguém mencionou a biblioteca Ion ou Glide . eles funcionam muito bem.

É mais fácil de manusear em comparação com um WebView.

bapho
fonte
5

Tive sucesso com a solução proposta neste artigo , uma classe chamada GifMovieView, que renderiza uma Viewque pode ser exibida ou adicionada a uma determinadaViewGroup . Confira os outros métodos apresentados nas partes 2 e 3 do artigo especificado.

A única desvantagem desse método é que o antialiasing no filme não é tão bom (deve ser um efeito colateral do uso da Movieclasse Android "obscura" ). É melhor definir o plano de fundo para uma cor sólida no seu GIF animado.

Dr1Ku
fonte
4

Algumas reflexões sobre o exemplo BitmapDecode ... Basicamente, ele usa a classe Movie antiga, mas bastante característica, de android.graphics. Nas versões recentes da API, você precisa desativar a aceleração de hardware, conforme descrito aqui . Caso contrário, foi um erro para mim.

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

Aqui está o exemplo BitmapDecode abreviado apenas com a parte GIF. Você precisa criar seu próprio Widget (Visualizar) e desenhá-lo sozinho. Não é tão poderoso quanto um 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 outros métodos, um com o ImageView e outro com o WebView podem ser encontrados neste tutorial . O método ImageView usa o android-gifview licenciado pela Apache no Google Code.

lubosz
fonte
1
@luboz você pode me dizer qual método é bom para o desempenho do Android ... eu quero usar gif animado para a barra de carregamento da tela inicial. então você pode sugerir qual método é melhor. Também quero saber que, usando o método de exibição de imagem, é possível usar a propriedade de tipo de escala?
Swap-IOS-Android
4

@PointerNull deu uma boa solução, mas não é perfeita. Ele não funciona em alguns dispositivos com arquivos grandes e mostra animação GIF com bugs com frames delta na versão anterior ao ICS. Encontrei solução sem esses bugs. É uma biblioteca com decodificação nativa para drawable: android-gif-drawable da koral .

Sergei Vasilenko
fonte
2

Coloque-o em um WebView, ele deve poder exibi-lo corretamente, pois o navegador padrão suporta arquivos gif. (Froyo +, se não me engano)

keybee
fonte
Isso não é verdade. Nem todos os navegadores são compatíveis com GIF.
RichieHH
4
Espero que não precisemos de todos os navegadores ... O navegador de ações o suporta desde o Android 2.2, por isso não me reduza o voto, por favor. Um WebView exibirá definitivamente o GIF!
keybee
2

Existem duas opções para carregar gifs animados em nossos aplicativos Android

1) Usando Glide para carregar o gif em um 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) Usando um html para carregar o gif em um WebView

Crie o html com o endereço para o arquivo .gif:

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

armazene esse arquivo no diretório de ativos:

insira a descrição da imagem aqui

Carregue este html no WebView do seu aplicativo:

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

Heres é um exemplo completo dessas duas opções .

insira a descrição da imagem aqui

Jorgesys
fonte
2

Apenas para API Android (Android Pie) 28 e +

use AnimatedImageDrawable como

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

Código XML, adicione um 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 é um filho do Drawable e criado por ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawableo que exigiu ainda a instância de ImageDecoder.Sourcecriada por ImageDecoder.createSource.

ImageDecoder.createSourcesó pode usar origem como nome, ByteBuffer, File, resourceId, URI, ContentResolver para criar um objeto de origem e usá-lo para criar AnimatedImageDrawablecomo Drawable(chamada polimórfica)

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: Você também pode criar Bitmapusando o ImageDecoder # decodeBitmap .

Resultado:

AnimatedDrawable também suporta redimensionamento, moldura e manipulação de cores

Pavneet_Singh
fonte
1

Eu acho que a melhor biblioteca para lidar com arquivos gif é esta: por koral

Usei e tenho sucesso e esta biblioteca é dedicada ao GIF'S; mas onde, como picasso e glide, são estruturas de imagem de uso geral ; então eu acho que os desenvolvedores desta biblioteca se concentraram inteiramente em arquivos gif

DJphy
fonte
1

Só queria acrescentar que a classe Movie agora está obsoleta.

Esta classe foi descontinuada no nível de API P.

Recomenda-se usar este

AnimatedImageDrawable

Drawable para desenhar imagens animadas (como GIF).

Sushobh Nadiger
fonte
1

Crie um pacote chamado "Utils" na pasta src e crie uma classe chamada "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");
        }
    }
}

Agora defina GifImageView no arquivo 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);
    }
}

Agora arquivo de peça da interface do usuário: 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>

Código de recurso: exemplo do Android

Tienanhvn
fonte
como redimensionar a imagem, pls
The Dead Guy
0

Primeiro, o navegador Android deve suportar GIFs animados. Se não, então é um bug! Dê uma olhada nos rastreadores de problemas.

Se você estiver exibindo esses GIFs animados fora de um navegador, pode ser uma história diferente. Para fazer o que você está pedindo, é necessária uma biblioteca externa que suporte a decodificação de GIFs animados.

A primeira porta de escala seria olhar para a API Java2D ou JAI (Java Advanced Imaging), embora eu ficaria muito surpreso se o Android Dalvik suportasse essas bibliotecas no seu aplicativo.

Eurig Jones
fonte
alguns dispositivos não mostram gifs animados, mesmo em um navegador da web. Como exemplo, eu sei que o Galaxy Mini com Android 2.3.6 não os mostra.
desenvolvedor android
0

Semelhante ao que @Leonti disse, mas com um pouco mais de profundidade:

O que fiz para resolver o mesmo problema foi abrir o GIMP, ocultar todas as camadas, exceto uma, exportar como sua própria imagem, ocultar a camada e exibir a próxima, etc., até que eu tivesse arquivos de recursos individuais para cada uma. . Então eu poderia usá-los como quadros no arquivo XML AnimationDrawable.

Jon O
fonte
1
Você pode usar o gifsicle para extrair os quadros se não tiver muito tempo. Também python ou bash são muito úteis ao gerar arquivos xml.
lubosz
0

Eu resolvi isso dividindo gif em quadros e usando a animação padrão do Android

Raluca Lucaci
fonte
0

Algo que fiz para mostrar gifs em aplicativos. Estendi o ImageView para que as pessoas possam usar seus atributos livremente. Ele pode mostrar gifs do URL ou do diretório de ativos. A biblioteca também facilita a herança de classes estendidas e a extensão para oferecer suporte a diferentes métodos para inicializar o gif.

https://github.com/Gavras/GIFView

Há um pequeno guia na página do github.

Também foi publicado no Android Arsenal:

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

Use exemplo:

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

Na atividade:

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

        }
});

Configurando o gif programaticamente:

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

Maneira mais fácil - pode ser considerado o código abaixo

Podemos tirar proveito do Imageview setImageResource, consulte o código abaixo para o mesmo.

O código abaixo pode ser usado para mostrar a imagem como gif, caso você tenha a imagem dividida múltipla de gif. Basta dividir o gif em png individual a partir de uma ferramenta on-line e colocar a imagem no drawable como na ordem abaixo

image_1.png, image_2.png etc.

Tenha o manipulador para alterar a imagem dinamicamente.

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);
// 
                    }
                });
              }
Lakshmanan
fonte
0

A maneira mais fácil de exibir GIF animado diretamente do URL para o layout do aplicativo é usar a classe WebView.

Etapa 1: no seu layout XML

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

Etapa 2: em sua atividade

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

Etapa 3: No seu Manifest.XML, faça a permissão da Internet

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

Etapa 4: caso você queira tornar o plano de fundo do GIF transparente e ajustá-lo ao layout

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

Ovais Chaudhry
fonte
Obrigado pela solução alternativa, mas considerável desenvolvedor pode não querer ter non-native tornar devido algumas implicações como um impacto de memória, uso de CPU e bateria de vida útil
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());

      }
    }
  }
}
Ashok Domadiya
fonte