Tampilkan GIF Animasi

261

Saya ingin menampilkan gambar GIF animasi dalam aplikasi saya. Seperti yang saya ketahui, sulitnya Android tidak mendukung animasi GIF secara asli.

Namun itu dapat menampilkan animasi menggunakan AnimationDrawable :

Kembangkan> Panduan> Gambar & Grafik> Gambaran Umum Drawables

Contoh ini menggunakan animasi yang disimpan sebagai bingkai dalam sumber daya aplikasi tetapi yang saya butuhkan adalah menampilkan animasi gif secara langsung.

Rencana saya adalah memecah animasi GIF ke bingkai dan menambahkan setiap bingkai sebagai dapat ditarik ke AnimationDrawable.

Adakah yang tahu cara mengekstrak bingkai dari animasi GIF dan mengonversinya masing-masing menjadi Drawable ?

Leonti
sumber
3
Apakah yang Anda maksud dalam Android, atau mengekstraksi bingkai dari gif dengan alat eksternal?
Osmund
itu pasti bug, lihat IssueTracker untuk informasi lebih lanjut.
fbtb
Hanya untuk semua orang yang datang ke sini dengan mencari aplikasi yang dapat menampilkan GIF animasi: quickPic
rubo77
Gunakan fresco untuk menampilkan GIF github.com/facebook/fresco Saya pikir ini adalah solusi sederhana.
kaitian521

Jawaban:

191

Android sebenarnya bisa mendekode dan menampilkan animasi GIF, menggunakan kelas android.graphics.Movie.

Ini tidak terlalu banyak didokumentasikan, tetapi dalam Referensi SDK . Selain itu, digunakan dalam Sampel di ApiDemos dalam contoh BitmapDecode dengan beberapa bendera animasi.

Pointer Null
sumber
9
Seberapa stabil ini? Saya telah mengimplementasikannya di aplikasi saya, pada perangkat Ice Cream Sandwich saya tidak berfungsi sama sekali, pada emulator 2.3 berfungsi, tetapi beberapa frame GIF bersifat buggy (warna salah). Di komputer tentu saja berfungsi dengan baik. Apa yang menyebabkannya?
Benoit Duffez
12
@Bicou Pada perangkat post-HC Anda harus melihat setLayerType(LAYER_TYPE_SOFTWARE)Anda. Tetapi masih hanya berfungsi untuk beberapa gif dan untuk beberapa perangkat.
Michał K
9
@ MichałK Terima kasih! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);bekerja!
Chloe
1
@ lubosz: LAYER_TYPE_SOFTWARE harus cukup untuk diatur.
Pointer Null
2
Kelas film sengaja tidak didokumentasi - lemah dan tidak didukung. Jika Anda membutuhkan animasi Gif yang tepat, Anda lebih baik menerapkannya sendiri. Saya melakukannya untuk aplikasi saya menggunakan NDK.
Pointer Null
60

MEMPERBARUI:

Gunakan glide:

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

pemakaian:

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

lihat dokumen

itzhar
sumber
1
Tampak oke bagi saya sekarang, jelas jawabannya tidak dapat menyertakan seluruh perpustakaan, jadi contoh panggilan sepertinya cukup.
Gaborous
@ rumit Jelas kode tidak termasuk pada saat penandaan.
Jan
1
Saya tidak merekomendasikan menggunakan perpustakaan ini jika Anda sudah menggunakan NDK. Setelah menambahkan lib ini ke gradle, modul Unity berhenti bekerja.
RominaV
Ini adalah perpustakaan terbaik yang saya temukan. Satu hal yang membuat saya terjebak adalah menerapkan pinch untuk memperbesar gambar gif. Adakah yang tahu
viper
28

juga put (main / assets / htmls / name.gif) [dengan html ini sesuaikan dengan ukuran]

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

mendeklarasikan dalam Xml Anda misalnya seperti ini (main / res / layout / name.xml): [Anda menentukan ukuran, misalnya]

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

di Aktivitas Anda, letakkan kode berikutnya di dalam onCreate

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

jika Anda ingin memuat secara dinamis, Anda harus memuat tampilan web dengan data:

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

saran: lebih baik memuat gif dengan gambar statis untuk memeriksa informasi lebih lanjut https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Itu saja, saya harap Anda membantu.

Alex Zaraos
sumber
2
Jika saya ingin memuat GIF dari sdcard?
Jaydev
jika Anda ingin memuat dari sdcard: ganti "file: ///android_asset/htmls/name.html" untuk uri gambar Anda
Alex Zaraos
Dengan menggunakan metode ini, bagaimana saya bisa mengubah nama file gif secara dinamis? Saya tidak ingin membuat file html untuk pergi dengan setiap gif yang saya butuhkan untuk ditampilkan di aplikasi saya
scrayne
Tampilan web untuk GIF?!? Apakah Anda memikirkan kinerja, konsumsi memori, dan baterai?
Duna
@Duna itu 5 tahun yang lalu, saat ini kita bisa menggunakan glide misalnya
Alex Zaraos
22

Saya memecahkan masalah dengan memecah animasi gif menjadi bingkai sebelum menyimpannya ke ponsel, jadi saya tidak harus menghadapinya di Android.

Lalu saya mengunduh setiap frame ke ponsel, membuat Drawable darinya dan kemudian membuat AnimationDrawable - sangat mirip dengan contoh dari pertanyaan saya

Leonti
sumber
2
Yang merupakan cara penanganan animasi yang didokumentasikan.
RichieHH
16

Saya menemukan cara yang sangat mudah, dengan contoh kerja yang bagus dan sederhana di sini

tampilkan widget animasi

Sebelum menjalankannya ada beberapa chages yang harus dilakukan dalam kode

BERIKUT INI

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

ganti saja

setContentView(new MYGIFView());

di

setContentView(new MYGIFView(this));

DAN MASUK

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

Berikan file animasi gif Anda sendiri

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

GANTI BARIS PERTAMA DI

public MYGIFView(Context context) {

sesuai dengan nama kelas ...

setelah melakukan perubahan kecil ini seharusnya berfungsi seperti untuk saya ...

semoga ini membantu

Apperside
sumber
2
Di versi android mana Anda mencoba ini? Saya mencoba versi android 2.2 dan 2.3 tetapi mengembalikan objek Movie nol. Adakah yang tahu apa yang salah?
Ashwini Shahapurkar
16
Tolong bersihkan jawaban ini, ini begitu, acak.
taxeeta
2
apa masalah dengan jawabannya? Saya baru saja memberikan tautan dan beberapa perbaikan yang diperlukan untuk membuatnya berfungsi
Apperside
10

Cara untuk menampilkan GIF animasi di Android:

  • Kelas film. Seperti disebutkan di atas, itu cukup buggy.
  • WebView. Ini sangat mudah digunakan dan biasanya berfungsi. Tapi kadang-kadang itu mulai bertingkah buruk, dan itu selalu ada di beberapa perangkat tidak jelas yang tidak Anda miliki. Selain itu, Anda tidak dapat menggunakan banyak instance dalam segala jenis tampilan daftar, karena hal itu berpengaruh pada memori Anda. Namun, Anda mungkin menganggapnya sebagai pendekatan utama.
  • Kode khusus untuk mendekode gif menjadi bitmap dan menunjukkannya sebagai Drawable atau ImageView. Saya akan menyebutkan dua perpustakaan:

https://github.com/koral--/android-gif-drawable - decoder diimplementasikan dalam C, jadi sangat efisien.

https://code.google.com/p/giffiledecoder - decoder diimplementasikan di Java, jadi lebih mudah digunakan. Masih cukup efisien, bahkan dengan file besar.

Anda juga akan menemukan banyak perpustakaan berdasarkan kelas GifDecoder. Itu juga decoder berbasis Java, tetapi bekerja dengan memuat seluruh file ke dalam memori, jadi itu hanya berlaku untuk file kecil.

Nick Frolov
sumber
10

Saya sangat kesulitan memiliki animasi gif yang bekerja di Android. Saya hanya mengikuti dua pekerjaan:

  1. WebView
  2. Ion

WebView berfungsi dengan baik dan sangat mudah, tetapi masalahnya membuat tampilan lebih lambat dan aplikasi tidak responsif untuk satu detik atau lebih. Saya tidak suka itu. Jadi saya telah mencoba berbagai pendekatan (TIDAK BEKERJA):

  1. ImageViewEx sudah usang!
  2. picasso tidak memuat gif animasi
  3. android-gif-drawable terlihat hebat, tetapi itu menyebabkan beberapa masalah NDK berkabel di proyek saya. Itu menyebabkan perpustakaan NDK lokal saya berhenti bekerja, dan saya tidak dapat memperbaikinya

Saya memiliki beberapa bolak-balik dengan Ion; Akhirnya, saya membuatnya bekerja, dan itu sangat cepat :-)

Ion.with(imgView)
  .error(R.drawable.default_image)
  .animateGif(AnimateGifMode.ANIMATE)
  .load("file:///android_asset/animated.gif");
Roozbeh Zabihollahi
sumber
Saya memiliki masalah terkait NDK yang sama dengan android-gif-drawable.
RominaV
Halo @RominaV, Sudahkah Anda menggunakan progress bar di Ion saat memuat gif, karena saya harus menunjukkan kemajuan saat memuat gif.
patel135
9

Meluncur 4.6

1. Untuk Memuat gif

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

2. Untuk mendapatkan objek 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);
                    }
                });
Gowsik KC
sumber
8

Glide

Perpustakaan Pemuat Gambar untuk Android, direkomendasikan oleh Google.

  • Glide sangat mirip dengan Picasso tetapi ini jauh lebih cepat daripada Picasso.
  • Glide mengkonsumsi lebih sedikit memori daripada Picasso.

Apa yang dimiliki Glide tetapi Picasso tidak

Kemampuan memuat Animasi GIF ke ImageView sederhana mungkin merupakan fitur paling menarik dari Glide. Dan ya, Anda tidak dapat melakukannya dengan Picasso. Beberapa tautan penting -masukkan deskripsi gambar di sini

  1. https://github.com/bumptech/glide
  2. http://inthecheesefactory.com/blog/get-to-know-glide-recomended-by-google/en
Shoeb Siddique
sumber
Di mana Google merekomendasikan Glid?
Derzu
1
Lihat ini, di mana tim Pengembang Android menggunakan Glide di aplikasi sampel mereka. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique
1
'Glide sangat mirip dengan Picasso tetapi ini jauh lebih cepat daripada Picasso' dan 'Glide mengkonsumsi lebih sedikit memori daripada Picasso.' Maaf saya tidak puas dengan ide-ide ini, lebih suka tautan ini: medium.com/@multidots/glide-vs-picasso-930eed42b81d . Btw, saya tidak dapat menguji Glide 4.0 sekarang karena tidak dapat memutakhirkan build ke 3.0.1 (koneksi internet lambat); tapi saya memang menguji Glide 3.5.2 untuk menunjukkan gif, itu bekerja tetapi tidak sempurna seperti yang saya harapkan pada img besar (ini berkedip-kedip), dan ini adalah masalah umum juga. Silakan CMIW.
Nguyen Tan Dat
7

Gunakan ImageViewEx , perpustakaan yang membuat penggunaan gif semudah menggunakan ImageView.

NightSkyCode
sumber
Ini sudah ditinggalkan
Martin Marconcini
Saya telah melihat-lihat kode perpustakaan ini, itu harus baik untuk 2 tahun atau lebih.
NightSkyCode
1
Ya, saya pikir itu relatif baik-baik saja, hanya menunjukkan bahwa penulis telah memutuskan untuk tidak menggunakannya. (dan karena itu tidak memeliharanya), menunjukkan bahwa kita harus menggunakan sesuatu seperti Picasso, yang aneh, karena Picasso adalah pengunduh gambar dan tidak akan membantu Anda ketika datang untuk menampilkan gif animasi lagi daripada banyak unduhan / cache alat di luar sana.
Martin Marconcini
6

Coba ini, di bawah ini kode menampilkan file gif di progressbar

loading_activity.xml (dalam folder 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 (dalam folder yang dapat digambar)

di sini saya meletakkan black_gif.gif (dalam folder yang dapat digambar), Anda dapat meletakkan gif Anda sendiri di sini

<?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 (dalam folder 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
sumber
Saya melihat Anda memutar gif. Mengapa?
AlikElzin-kilaka
Bagaimana Anda bisa meletakkan gif di folder yang dapat digambar?
Apurva
6

Tidak ada yang menyebutkan perpustakaan Ion atau Glide . mereka bekerja dengan sangat baik.

Lebih mudah ditangani dibandingkan dengan WebView.

bapho
sumber
5

Saya telah berhasil dengan solusi yang diusulkan dalam artikel ini , sebuah kelas yang disebut GifMovieView, yang menjadikan Viewyang kemudian dapat ditampilkan atau ditambahkan ke spesifikViewGroup . Lihat metode lain yang disajikan dalam bagian 2 dan 3 dari artikel yang ditentukan.

Satu-satunya kelemahan dari metode ini adalah bahwa antialiasing pada film tidak sebagus itu (harusnya merupakan efek samping dari penggunaan MovieKelas Android "teduh" ). Anda kemudian lebih baik mengatur latar belakang ke warna solid dalam GIF animasi Anda.

Dr1Ku
sumber
4

Beberapa pemikiran tentang contoh BitmapDecode ... Pada dasarnya ia menggunakan kelas Movie yang kuno, tetapi tidak memiliki fitur dari android.graphics. Pada versi API terbaru Anda perlu mematikan akselerasi perangkat keras, seperti dijelaskan di sini . Sebaliknya bagi saya itu segfaulting.

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

Berikut adalah contoh BitmapDecode yang dipersingkat dengan hanya bagian GIF. Anda harus membuat Widget Anda sendiri (Tampilan) dan menggambarnya sendiri. Tidak sekuat 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 metode lain, satu dengan ImageView yang lain dengan WebView dapat ditemukan di tutorial ini . Metode ImageView menggunakan android-gifview berlisensi Apache dari Google Code.

lubosz
sumber
1
@ luboz bisa tolong beri tahu saya metode mana yang baik untuk kinerja android ... saya ingin menggunakan animasi gif untuk bilah pemuatan layar splash. jadi bisakah Anda menyarankan metode mana yang lebih baik. juga saya ingin tahu bahwa dengan menggunakan metode tampilan gambar apakah mungkin untuk menggunakan properti jenis skala?
Swap-IOS-Android
4

@PointerNull memberikan solusi yang baik, tetapi tidak sempurna. Itu tidak bekerja pada beberapa perangkat dengan file besar dan menunjukkan animasi Gif kereta dengan bingkai delta pada versi pra ICS. Saya menemukan solusi tanpa bug ini. Ini adalah perpustakaan dengan decoding asli ke drawable: koral's android-gif-drawable .

Sergei Vasilenko
sumber
2

Masukkan ke dalam WebView, itu harus dapat menampilkannya dengan benar, karena browser default mendukung file gif. (Froyo +, jika saya tidak salah)

keybee
sumber
Ini tidak benar. Tidak semua browser mendukung GIF.
RichieHH
4
Semoga kita tidak memerlukan semua browser ... Browser stok mendukungnya sejak android 2.2, jadi jangan downvote saya, tolong. WebView pasti akan menampilkan GIF!
keybee
2

Ada dua opsi untuk memuat animasi gif ke dalam aplikasi Android kami

1) Menggunakan Glide untuk memuat gif ke dalam 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) Menggunakan html untuk memuat gif ke dalam a WebView

Buat html dengan alamat ke file .gif:

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

simpan file ini ke direktori aset:

masukkan deskripsi gambar di sini

Muat html ini ke dalam WebView aplikasi Anda:

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

Berikut ini adalah contoh lengkap dari dua opsi ini .

masukkan deskripsi gambar di sini

Jorgesys
sumber
2

Hanya API Android (Pie Android) 28 dan +

gunakan AnimatedImageDrawable sebagai

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

Kode XML, tambahkan 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 adalah anak Drawable dan dibuat oleh ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawableyang selanjutnya membutuhkan instance dari yang ImageDecoder.Sourcedibuat oleh ImageDecoder.createSource.

ImageDecoder.createSourcehanya dapat mengambil sumber sebagai nama, ByteBuffer, File, resourceId, URI, ContentResolver untuk membuat objek sumber dan menggunakannya untuk membuat AnimatedImageDrawablesebagai Drawable(panggilan polimorfik)

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)

Catatan: Anda juga dapat membuat Bitmapmenggunakan ImageDecoder # decodeBitmap .

Keluaran:

AnimatedDrawable juga mendukung pengubahan ukuran, bingkai dan warna

Pavneet_Singh
sumber
1

Saya pikir perpustakaan yang lebih baik untuk menangani file gif adalah yang satu ini: oleh koral

Sudah menggunakannya dan saya berhasil dan perpustakaan ini didedikasikan untuk GIF; tetapi di mana sebagai picasso dan meluncur adalah kerangka gambar tujuan umum ; jadi saya pikir para pengembang perpustakaan ini sepenuhnya berkonsentrasi pada file gif

DJphy
sumber
1

Hanya ingin menambahkan bahwa kelas Film sekarang sudah usang.

Kelas ini sudah tidak digunakan lagi di level API P.

Disarankan untuk menggunakan ini

AnimatedImageDrawable

Dapat digambar untuk menggambar gambar animasi (seperti GIF).

Sushobh Nadiger
sumber
1

Buat paket bernama "Utils" di bawah folder src dan buat kelas bernama "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");
        }
    }
}

Sekarang tentukan GifImageView di MainActivity File: 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);
    }
}

Sekarang File Bagian UI: 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>

Kode sumber: contoh Android

Tienanhvn
sumber
cara mengubah ukuran gambar, pls
The Dead Guy
0

Pertama-tama peramban Android harus mendukung GIF Animasi. Jika tidak maka itu bug! Lihatlah pelacak masalah.

Jika Anda menampilkan GIF animasi ini di luar peramban, mungkin ini cerita yang berbeda. Untuk melakukan apa yang Anda minta akan membutuhkan perpustakaan eksternal yang mendukung decoding GIF Animasi.

Port of call pertama adalah melihat Java2D atau JAI (Java Advanced Imaging) API, meskipun saya akan sangat terkejut jika Android Dalvik akan mendukung perpustakaan-perpustakaan di App Anda.

Eurig Jones
sumber
beberapa perangkat tidak menampilkan gif animasi, bahkan di browser web. sebagai contoh, saya tahu bahwa galaxy mini dengan android 2.3.6 tidak menunjukkannya.
pengembang android
0

Mirip dengan apa yang dikatakan @Leonti, tetapi dengan sedikit lebih dalam:

Apa yang saya lakukan untuk mengatasi masalah yang sama adalah membuka GIMP, menyembunyikan semua layer kecuali satu, mengekspornya sebagai gambar sendiri, dan kemudian menyembunyikan layer itu dan menyembunyikan yang berikutnya, dll., Sampai saya memiliki file sumber daya individual untuk masing-masing . Lalu saya bisa menggunakannya sebagai bingkai dalam file XML AnimationDrawable.

Jon O
sumber
1
Anda bisa menggunakan gifsicle untuk mengekstrak bingkai jika Anda tidak punya banyak waktu. Juga python atau bash sangat berguna saat membuat file xml.
lubosz
0

Saya memecahkan masalah ini dengan memisahkan gif dalam bingkai dan menggunakan animasi android standar

Raluca Lucaci
sumber
0

Sesuatu yang saya lakukan untuk menampilkan gif di aplikasi. Saya memperluas ImageView sehingga orang dapat menggunakan atributnya secara bebas. Itu dapat menampilkan gif dari url atau dari direktori aset. Perpustakaan juga memudahkan untuk memperluas kelas untuk mewarisi darinya dan memperluasnya untuk mendukung metode yang berbeda untuk menginisialisasi gif.

https://github.com/Gavras/GIFView

Ada sedikit panduan di halaman github.

Itu juga diterbitkan di Android Arsenal:

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

Gunakan contoh:

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

Dalam kegiatan:

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

        }
});

Mengatur gif secara terprogram:

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

Cara termudah - Dapat mempertimbangkan kode di bawah ini

Kita dapat memanfaatkan Imageview setImageResource, merujuk kode di bawah ini untuk hal yang sama.

Kode di bawah ini dapat digunakan untuk menampilkan gambar seperti gif incase jika Anda memiliki beberapa gambar split gif. Hanya membagi gif menjadi png individu dari alat online dan menempatkan gambar dalam gambar seperti urutan di bawah ini

image_1.png, image_2.png, dll.

Minta pawang untuk mengubah gambar secara dinamis.

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
sumber
0

Cara mudah untuk menampilkan GIF animasi langsung dari URL ke tata letak aplikasi Anda adalah dengan menggunakan kelas WebView.

Langkah 1: Di layout XML Anda

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

Langkah 2: Dalam Aktivitas Anda

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

Langkah 3: Di Manifest.XML Anda, buat izin Internet

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

Langkah 4: Jika Anda ingin membuat latar belakang GIF Anda transparan dan membuat GIF cocok dengan Tata Letak Anda

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

Ovais Chaudhry
sumber
Terima kasih atas solusinya tetapi pengembang yang cukup besar mungkin tidak ingin memiliki render non-asli karena beberapa implikasi sebagai dampak memori, penggunaan CPU dan masa pakai baterai
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
sumber