Hareketli GIF Görüntüle


261

Uygulamamda animasyonlu GIF resimleri görüntülemek istiyorum. Zor şekilde öğrendiğim gibi, Android animasyonlu GIF'i yerel olarak desteklemiyor.

Ancak AnimationDrawable kullanarak animasyonları görüntüleyebilir :

Geliştir> Kılavuzlar> Resimler ve Grafikler> Çizilebilir Tablolara Genel Bakış

Örnek, uygulama kaynaklarında kare olarak kaydedilen animasyonu kullanır, ancak ihtiyacım olan şey animasyonlu gif'i doğrudan görüntülemek.

Planım animasyonlu GIF'i karelere bölmek ve her kareyi AnimationDrawable'a çizilebilir olarak eklemek.

Herkes animasyonlu GIF kareleri ayıklamak ve bunların her biri Drawable dönüştürmek biliyor mu ?


3
Android içinde mi yoksa harici bir araçla bir giften kareleri çıkarmak mı?
Osmund

kesinlikle bir hata, daha fazla bilgi için IssueTracker'a bakın .
fbtb

Animasyonlu GIF'leri görüntüleyebilecek bir uygulama arayarak buraya gelenler için: quickPic
rubo77


GIF'i görüntülemek için fresk kullanın github.com/facebook/fresco Bunun basit bir çözüm olduğunu düşünüyorum.
16:49

Yanıtlar:


191

Android aslında android.graphics.Movie sınıfını kullanarak animasyonlu GIF'lerin kodunu çözebilir ve görüntüleyebilir.

Bu çok fazla belgelenmemiştir, ancak SDK Referansındadır . Ayrıca, BitmapDecode örneğindeki ApiDemos'taki Örneklerde bazı animasyonlu bayraklarla birlikte kullanılır.


9
Bu ne kadar kararlı? Uygulamamda uyguladım, Ice Cream Sandwich cihazımda hiç çalışmıyor, 2.3 emülatörde çalışıyor, ancak bazı GIF çerçeveleri buggy (yanlış renkler). Bir bilgisayarda elbette iyi çalışıyor. Ne oluyor?
Benoit Duffez

12
@Bicou HC sonrası cihazlarda setLayerType(LAYER_TYPE_SOFTWARE)Görünümünüzde bulunmalısınız . Ancak yine de sadece bazı gifler ve bazı cihazlar için çalışır.
Michał K

9
@ MichałK Teşekkürler! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);çalıştı!
Chloe

1
@lubosz: LAYER_TYPE_SOFTWARE ayarlamak için yeterli olmalıdır.
Pointer Null

2
Film sınıfı bilerek belgelenmemiştir - zayıf ve desteklenmez. Uygun Gif animasyonlarına ihtiyacınız varsa, onu kendiniz uygulamanız daha iyi olur. NDK kullanarak uygulamam için yaptım.
Pointer Null

60

GÜNCELLEME:

Kayma kullanın:

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

kullanımı:

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

belgelere bakın


1
Bana şimdi iyi görünüyor, açıkçası cevap tüm kütüphaneyi içeremez, bu yüzden çağrı örneği yeterli görünüyor.
gaborous

@gaborous Açıkçası kod, işaretleme sırasında dahil edilmedi.
Ocak

1
Zaten NDK kullanıyorsanız bu kütüphaneyi kullanmanızı önermiyorum. Bu lib'i derecelendirmeye ekledikten sonra, bir Unity modülü çalışmayı durdurdu.
RominaV

Bu bulduğum en iyi kütüphane. Sıkıştığım bir şey, gif görüntüsünü yakınlaştırmak için tutam uygulamak. Kimse biliyor mu?
engerek

28

ayrıca (main / asset / htmls / name.gif) [bu html ile boyuta ayarlayın]

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

Xml'inizde böyle beyan edin (main / res / layout / name.xml): [örneğin boyutu siz tanımlarsınız]

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

Etkinliğinizde sonraki kodu onCreate'ın içine koyun

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

dinamik olarak yüklemek istiyorsanız, web görünümünü verilerle yüklemeniz gerekir:

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

öneri: daha fazla bilgi için statik görüntülerle daha iyi yük gifidir https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

Hepsi bu, umarım yardım edersin.


2
Sdcard'dan GIF yüklemek istersem?
Jaydev

sdcard'dan yüklemek istiyorsanız: resminizin uri'si için "file: ///android_asset/htmls/name.html" dosyasını değiştirin
Alex Zaraos

Bu yöntemi kullanarak gif dosyasının adını dinamik olarak nasıl değiştirebilirim? Uygulamamda göstermem gereken her gif ile gitmek için bir html dosyası yapmak istemiyorum
scrayne

Bir GIF için Web görünümü?!? Performans, bellek tüketimi ve pil hakkında düşündünüz mü?
Duna

@Duna 5 yıl önce, şu anda örneğin kayma kullanabilirsiniz
Alex Zaraos

22

Sorunu , telefona kaydetmeden önce gif animasyonlarını çerçevelere bölerek çözdüm , bu yüzden Android'de bununla uğraşmak zorunda kalmam.

Sonra her kareyi telefona indiriyorum, ondan Drawable oluşturuyorum ve sonra AnimationDrawable oluşturuyorum - sorumdan örneğe çok benzer


2
Animasyonları işlemenin belgelenmiş yolu budur.
RichieHH

16

Burada güzel ve basit bir çalışma örneği ile çok kolay bir yol buldum

animasyonlu widget'ı görüntüle

Çalışmaya başlamadan önce kodda yapmak için bazı chages var

AŞAĞIDAKİ

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

sadece değiştir

setContentView(new MYGIFView());

içinde

setContentView(new MYGIFView(this));

VE

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

Kendi gif animasyon dosyanızı sağlayın

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

İLK HATTI DEĞİŞTİRİN

public MYGIFView(Context context) {

sınıfın ismine göre ...

Bu küçük değişiklikleri yaptıktan sonra benim için çalışmalı ...

umarım bu yardım


2
Bunu hangi android sürümünde denediniz? Android 2.2 ve 2.3 sürümünü denedim ama Movie nesnesi null döndürür. Neyin yanlış olabileceği hakkında bir fikrin var mı?
Ashwini Shahapurkar

16
Lütfen bu cevabı temizleyin, bu yüzden rastgele.
taxeeta

2
cevabın sorunu nedir? Ben sadece bir bağlantı ve çalışması için bazı gerekli düzeltme sağladı
Apperside

10

Android'de animasyonlu GIF göstermenin yolları:

  • Film sınıfı. Yukarıda belirtildiği gibi, oldukça adamcağız.
  • WebView. Kullanımı çok basit ve genellikle işe yarıyor. Ancak bazen yanlış davranmaya başlar ve her zaman sahip olmadığınız bazı belirsiz cihazlarda bulunur. Ayrıca, herhangi bir liste görünümünde birden fazla örneği kullanamazsınız, çünkü belleğinizde bir şeyler yapar. Yine de, bunu birincil bir yaklaşım olarak düşünebilirsiniz.
  • Gif'leri bitmap'lerde çözmek ve bunları Çekilebilir veya ImageView olarak göstermek için özel kod. İki kütüphaneden bahsedeceğim:

https://github.com/koral--/android-gif-drawable - kod çözücü C dilinde uygulandığından çok etkilidir.

https://code.google.com/p/giffiledecoder - kod çözücü Java'da uygulandığından, çalışmak daha kolaydır. Büyük dosyalar için bile hala oldukça verimlidir.

GifDecoder sınıfına dayanan birçok kütüphane de bulacaksınız. Bu aynı zamanda Java tabanlı bir kod çözücüdür, ancak tüm dosyayı belleğe yükleyerek çalışır, bu nedenle yalnızca küçük dosyalar için geçerlidir.


10

Android'de animasyonlu gif çalışmak için gerçekten zor zamanlar geçirdim. Sadece şu iki çalışmam vardı:

  1. WebView
  2. İyon

WebView iyi ve gerçekten kolay çalışıyor, ancak sorun görünüm yüklerini yavaşlatıyor ve uygulama bir saniyeliğine yanıt vermiyor. Bunu beğenmedim. Bu yüzden farklı yaklaşımlar denedim (ÇALIŞMADI):

  1. ImageViewEx kullanımdan kaldırıldı!
  2. picasso animasyonlu gif yüklemedi
  3. android-gif-drawable harika görünüyor, ancak projemde bazı kablolu NDK sorunlarına neden oldu. Yerel NDK kütüphanemin çalışmasının durmasına neden oldu ve düzeltemedim

Ben ileri geri bazı vardı Ion; Sonunda, çalışıyorum ve gerçekten hızlı :-)

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

Android-gif-drawable ile aynı NDK ile ilgili sorunları yaşadım.
RominaV

Merhaba @RominaV, Yük gifinde İyonda ilerleme çubuğu kullandınız mı, çünkü yük gifinde ilerleme göstermem gerekiyor.
patel135

9

Kayma 4.6

1. Yükleme gif

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

2. Dosya nesnesini almak için

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

Google tarafından önerilen Android için Resim Yükleyici Kütüphanesi.

  • Glide Picasso'ya oldukça benzer, ancak bu Picasso'dan çok daha hızlıdır.
  • Glide, Picasso'dan daha az bellek tüketiyor.

Glide'nin sahip olduğu şey ama Picasso'nun sahip olmadığı şey

GIF Animation'u basit bir ImageView'e yükleme yeteneği, Glide'ın en ilginç özelliği olabilir. Ve evet, bunu Picasso ile yapamazsın. Bazı önemli bağlantılarresim açıklamasını buraya girin

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

Google Glid'i nereden öneriyor?
Derzu

1
Geliştirici Android ekibinin Glide'ı örnek uygulamalarında kullandığı yere bakın. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique

1
'Glide Picasso'ya oldukça benziyor, ancak bu Picasso'dan çok daha hızlı' ve 'Glide Picasso'dan daha az bellek tüketiyor.' Üzgünüz, bu fikirlerden memnun değilim, lütfen şu bağlantıyı tercih edin: medium.com/@multidots/glide-vs-picasso-930eed42b81d . Btw, şimdi 3.0.1 (yavaş Internet bağlantısı) sürümüne yükseltme mümkün olmadığı için Glide 4.0 test edemiyorum; ama Glide 3.5.2'yi gif gösterme konusunda test ettim, çalışıyor ama büyük img'de beklediğim gibi mükemmel değil (titriyor) ve bu da yaygın bir konudur. Lütfen CMIW.
Nguyen Tan Dat

7

Bir gif kullanmayı bir kadar kolay hale getiren bir kütüphane olan ImageViewEx'i kullanın ImageView.


Bu onaylanmadı
Martin Marconcini

Bu kütüphaneler kodunu inceledim, 2 veya daha fazla yıl boyunca iyi olmalı.
NightSkyCode

1
Evet, bence nispeten iyi, sadece yazarın onu reddetmeye karar verdiğine işaret ediyor. Picasso gibi bir şey kullanmamız gerektiğine işaret ederek (garip olan Picasso gibi), Picasso bir resim indiricisidir ve birçok indirme / önbellekten herhangi birinden daha fazla animasyonlu bir gif görüntüleme söz konusu olduğunda size yardımcı olmaz. orada araçlar.
Martin Marconcini

6

Bunu deneyin, ilerleme çubuğunda feryat kodu görüntüleme gif dosyası

loading_activity.xml (Düzen klasöründe)

<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 (çekilebilir klasörde)

buraya black_gif.gif (çekilebilir klasöre) koydum, kendi gif'inizi buraya koyabilirsiniz

<?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 (res klasöründe)

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

    }

}

Gif'i döndürdüğünü görüyorum. Neden?
AlikElzin-kilaka

GIF'i çekilebilir klasöre nasıl koyabilirsiniz?
Apurva

6

Kimse Ion veya Glide kütüphanesinden bahsetmedi . çok iyi çalışıyorlar.

WebView ile karşılaştırıldığında kullanımı daha kolaydır.


5

Bu makalede önerilen çözüm ile başarılı oldum, denilen bir sınıf daha sonra görüntülenebilir veya belirli bir eklenebilir GifMovieViewhale getirir . Belirtilen makalenin 2. ve 3. bölümlerinde sunulan diğer yöntemleri inceleyin.ViewViewGroup

Bu yöntemin tek dezavantajı, filmdeki kenar yumuşatmanın o kadar iyi olmamasıdır ("gölgeli" Android MovieSınıfını kullanmanın bir yan etkisi olmalıdır ). Ardından, animasyonlu GIF'inizde arka planı düz bir renge ayarlamak daha iyi olur.


4

BitmapDecode örneğiyle ilgili bazı düşünceler ... Temel olarak android.graphics'ten eski, ama oldukça özelliksiz Movie sınıfını kullanıyor. Son API sürümlerinde, burada açıklandığı gibi donanım hızlandırmayı kapatmanız gerekir . Aksi takdirde benim için segfaulting oldu.

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

İşte sadece GIF kısmı ile kısaltılmış BitmapDecode örneği. Kendi Widget'ınızı (Görünüm) yapmanız ve kendiniz çizmeniz gerekir. Bir ImageView kadar güçlü değil.

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();
            }
        }
    }
}

Biri ImageView ile diğeri WebView ile olmak üzere 2 yöntem daha bu ince eğitimde bulunabilir . ImageView yöntemi , Google Code'dan Apache lisanslı android gifview kullanır .


1
@luboz bana android performansı için hangi yöntemin iyi olduğunu söyleyebilir misiniz ... açılış ekranı yükleme çubuğu için animasyonlu gif kullanmak istiyorum. lütfen hangi yöntemin daha iyi olduğunu önerebilir misiniz? Ayrıca görüntü görünümü yöntemi kullanarak ölçek türü özelliği kullanmak mümkün olduğunu bilmek istiyorum?
Swap-IOS-Android

4

@PointerNull iyi bir çözüm verdi, ama mükemmel değil. Büyük dosyaları olan bazı cihazlarda çalışmaz ve ICS öncesi sürümünde delta çerçeveli buggy Gif animasyonu gösterir. Bu hatalar olmadan çözüm buldum. Bu çekilebilir yerel kod çözme ile kütüphane: koral android-gif-drawable .


2

Bir WebView içine koyun, varsayılan tarayıcı gif dosyalarını desteklediğinden, doğru bir şekilde görüntüleyebilmelidir. (Froyo +, yanılmıyorsam)


Bu doğru değil. Tüm tarayıcılar GIF'i desteklemez.
RichieHH

4
Umarım tüm tarayıcılara ihtiyacımız yoktur ... Stok tarayıcı android 2.2'den beri destekliyor, bu yüzden lütfen beni aşağı indirmeyin. Bir WebView kesinlikle GIF'i gösterecektir!
keybee

2

Android uygulamalarımıza animasyonlu gif yüklemek için iki seçenek vardır

1) gif bir yüklemek için Glide kullanarak 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) Gif'i bir yüklemek için bir html kullanma WebView

.Tif dosyasının adresini içeren html dosyasını oluşturun:

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

bu dosyayı varlık dizininde sakla:

resim açıklamasını buraya girin

Bu html'yi uygulamanızın WebView öğesine yükleyin:

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

Heres bu iki seçeneğin tam bir örneğidir .

resim açıklamasını buraya girin


2

Yalnızca android API (Android Pie) 28 ve + için

AnimatedImageDrawable'ı şu şekilde kullanın:

// ImageView from layout
val ima : ImageView = findViewById(R.id.img_gif)
// create AnimatedDrawable 
val decodedAnimation = ImageDecoder.decodeDrawable(
        // create ImageDecoder.Source object
        ImageDecoder.createSource(resources, R.drawable.tenor))
// set the drawble as image source of ImageView
ima.setImageDrawable(decodedAnimation)
// play the animation
(decodedAnimation as? AnimatedImageDrawable)?.start()

XML kodu, bir ImageView ekleyin

<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 Drawable'ın bir çocuğu ve ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawablebu da ImageDecoder.Sourcetarafından oluşturulan örneği gerektiriyordu ImageDecoder.createSource.

ImageDecoder.createSourceSadece bir isim olarak kaynak alabilir, ByteBuffer Dosya, RESOURCEID, URI ContentResolver Kaynak nesneyi yaratmak için kullanır oluşturmak için AnimatedImageDrawableolduğu gibi Drawable(polimorfik çağrı)

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)

Not: ImageDecoder # decodeBitmapBitmap kullanarak da oluşturabilirsiniz .

Çıktı:

AnimatedDrawable ayrıca yeniden boyutlandırma, çerçeve ve renk manipülasyonunu destekler


1

Gif dosyaları işlemek için daha iyi kütüphane bu olduğunu düşünüyorum : koral tarafından

Kullanılan ve ben başarılı ve bu kütüphane GIF'S adamıştır; ancak burada picasso ve kayma olan genel amaçlı görüntü çerçevesi; bu kütüphanenin geliştiricilerinin tamamen gif dosyalarına odaklandığını düşünüyorum



1

Sadece Movie sınıfının artık kullanımdan kaldırıldığını eklemek istedim .

Bu sınıf API P düzeyinde kullanımdan kaldırıldı.

Bunu kullanmanız önerilir

AnimatedImageDrawable

Animasyonlu görüntüler çizmek için çizilebilir (GIF gibi).


1

Src klasörü altında “Utils” adlı bir paket oluşturun ve “GifImageView” adlı bir sınıf oluşturun

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");
        }
    }
}

Şimdi MainActivity Dosyasında GifImageView'u tanımlayın: 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);
    }
}

Şimdi UI Parça Dosyası: 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>

Kaynak kodu: Android örneği


görüntüyü yeniden boyutlandırma, pls
The Dead Guy

0

Her şeyden önce Android tarayıcı Animasyonlu GIF'leri desteklemelidir. Eğer değilse, bu bir hata! Sorun izleyicilere bir göz atın.

Bu animasyonlu GIF'leri bir tarayıcı dışında görüntülüyorsanız, farklı bir hikaye olabilir. İstediğinizi yapmak için Animasyonlu GIF'lerin kod çözülmesini destekleyen harici kitaplık gerekir.

İlk arama portu Java2D veya JAI (Java Advanced Imaging) API'sine bakmak olacaktır, ancak Android Dalvik'in Uygulamanızdaki bu kütüphaneleri desteklemesi çok şaşırır.


bazı cihazlar bir web tarayıcısında bile hareketli gifler göstermez. örnek olarak, android 2.3.6 ile galaxy mini onlara göstermediğini biliyorum.
android geliştirici

0

@Leonti'nin söylediklerine benzer, ancak biraz daha derinlikle:

Aynı sorunu çözmek için yaptığım şey, GIMP'yi açmak, biri hariç tüm katmanları gizlemek, kendi görüntüsü olarak dışa aktarmak ve daha sonra bu katmanı gizlemek ve bir sonrakini göstermek, vb. . Sonra onları AnimationDrawable XML dosyasında çerçeveler olarak kullanabilirim.


1
Çok fazla zamanınız yoksa çerçeveleri çıkarmak için gifsicle kullanabilirsiniz . Ayrıca xml dosyaları oluştururken python veya bash çok kullanışlıdır.
lubosz

0

Bunu gif'i çerçevelere bölerek çözdüm ve standart android animasyon kullanıyorum


0

Uygulamalarda gif göstermek için yaptığım bir şey. ImageView'i genişleterek insanların özniteliklerini özgürce kullanabilmelerini sağladım. URL'den veya varlıklar dizininden gif'leri gösterebilir. Kütüphane ayrıca sınıfları genişletmek ve gif'i başlatmak için farklı yöntemleri desteklemek üzere genişletmek için de kolaylaştırır.

https://github.com/Gavras/GIFView

Github sayfasında küçük bir rehber var.

Ayrıca Android Arsenal'de yayınlandı:

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

Örnek kullanın:

XML'den:

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

Faaliyette:

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

        }
});

GIF'i programlı olarak ayarlama:

mGifView.setGifResource("asset:gif1");

0

En kolay yol - Aşağıdaki kod düşünülebilir

Imageview setImageResource'tan yararlanabiliriz, bunun için aşağıdaki kodlara bakın.

Aşağıdaki kod, gif'in birden fazla bölünmüş görüntüsüne sahipseniz, gif olayı gibi görüntüyü göstermek için kullanılabilir. GIF'i çevrimiçi bir araçtan tek tek png'ye ayırın ve resmi aşağıdaki sırada olduğu gibi çekmeceye koyun

image_1.png, image_2.png vb.

İşleyiciye görüntüyü dinamik olarak değiştirmesini sağlayın.

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

Animasyonlu GIF'i doğrudan URL'den uygulama düzeninize görüntülemenin kolay yolu WebView sınıfını kullanmaktır.

1. Adım: Düzen XML'nizde

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

2. Adım: Faaliyetinizde

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

3. Adım: Manifest.XML'nizde İnternet izni alın

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

Adım 4: GIF arka planınızı şeffaf hale getirmek ve GIF'i Düzeninize sığdırmak istiyorsanız

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


Geçici çözüm için teşekkürler, ancak önemli geliştirici, bellek etkisi, CPU kullanımı ve pil ömrü gibi bazı etkiler nedeniyle yerel olmayan oluşturma
istemeyebilir


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

      }
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.