Відобразити анімований GIF


261

Я хочу відобразити анімовані GIF-зображення у моїх заявках. Як я з'ясував, важкий спосіб Android не підтримує анімований GIF на самому світі.

Однак він може відображати анімацію за допомогою AnimationDrawable :

Розробка> Посібники> Зображення та графіка> Огляд рисунків

У прикладі використовується анімація, збережена як кадри в ресурсах програми, але мені потрібно безпосередньо відображати анімовані gif.

Мій план полягає в тому, щоб розбити анімований GIF на кадри та додати кожен кадр як малюнок до AnimationDravable.

Хтось знає, як витягти кадри з анімованих GIF і перетворити кожен з них у Dravable ?


2
Ви маєте на увазі під android або витягування кадрів з gif із зовнішнім інструментом?
Осмунд

це, безумовно, помилка, див. IssueTracker для отримання додаткової інформації.
fbtb

Просто для всіх, хто прийшов сюди, шукаючи додаток, який може відображати анімовані GIF-файли: quickPic
rubo77


Використовуйте фреску для відображення GIF github.com/facebook/fresco Я думаю, що це просте рішення.
kaitian521

Відповіді:


191

Android насправді може декодувати та відображати анімовані GIF, використовуючи клас android.graphics.Movie.

Це не надто задокументовано, але є у SDK Reference . Більше того, він використовується в зразках в ApiDemos в прикладі BitmapDecode з деяким анімованим прапором.


9
Наскільки це стабільно? Я реалізував це у своєму додатку, на моєму морозиво-сендвіч-пристрої він взагалі не працює, на емуляторі 2.3 він працює, але деякі рамки GIF є баггі (неправильні кольори). На комп’ютері це, звичайно, добре працює. Що дає?
Бенуа Даффез

12
@Bicou На пост-HC пристроях, які ви повинні мати setLayerType(LAYER_TYPE_SOFTWARE)у своєму представленні. Але це все ще працює лише для деяких gif-файлів і для деяких пристроїв.
Michał K

9
@ MichałK Дякую! Paint p = new Paint(); p.setAntiAlias(true); setLayerType(LAYER_TYPE_SOFTWARE, p);працювали!
Хлоя

1
@lubosz: LAYER_TYPE_SOFTWARE має вистачити для встановлення.
Покажчик Null

2
Клас кіно за призначенням недокументований - він слабкий і не підтримується. Якщо вам потрібні належні Gif-анімації, краще реалізуйте її самостійно. Я зробив це для свого додатка за допомогою NDK.
Вказівник Null

60

ОНОВЛЕННЯ:

Використовуйте ковзання:

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

використання:

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

див. документи


1
Мені здається нормально, очевидно, що відповідь не може включати всю бібліотеку, тому прикладу виклику здається достатньою.
габоровий

@gaborous Очевидно, що код не був включений під час позначення.
січня

1
Я не рекомендую використовувати цю бібліотеку, якщо ви вже використовуєте NDK. Після додавання цієї лібу до gradle модуль Unity перестав працювати.
RominaV

Це найкраща бібліотека, яку я знайшов. Одне, до чого я застряг - це реалізація прищіпки для збільшення зображення зображення. Хтось знає?
гадюка

28

також поставте (main / properties / htmls / name.gif) [за допомогою цього html відрегулюйте розмір]

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

заявіть у своєму Xml наприклад, наприклад, цей (main / res / layout / name.xml): [Ви визначаєте розмір, наприклад]

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

у вашій діяльності введіть наступний код всередині onCreate

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

якщо ви хочете динамічно завантажувати, вам потрібно завантажити веб-перегляд з даними:

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

пропозиція: краще завантажуйте gif зі статичними зображеннями для отримання додаткової інформації перевірити https://developer.android.com/reference/android/graphics/dravable/AnimationDravable.html

Це все, я сподіваюся, ви допоможете.


2
Якщо я хочу завантажити GIF з sdcard?
Jaydev

якщо ви хочете завантажити з sdcard: замініть "файл: ///android_asset/htmls/name.html" на урі вашого зображення
Alex Zaraos

Використовуючи цей метод, як я можу динамічно змінити ім'я файлу gif? Я не хочу робити HTML-файл для кожного gif, який мені потрібно відобразити у своєму додатку
scrayne

Веб-перегляд GIF?!? Ви думали про продуктивність, споживання пам’яті та акумулятор?
Дуна

@Duna, що було 5 років тому, зараз ми можемо використовувати
сліз,

22

Я вирішив проблему, розділивши анімаційні файли на кадри, перш ніж зберегти її на телефон, тому мені не доведеться з цим мати справу в Android.

Потім я завантажую кожен кадр на телефон, створюю з нього Dravable і потім створюю AnimationDravable - дуже схожий на приклад із мого запитання


2
Який документально підтверджений спосіб обробки анімації.
RichieHH

16

Я знайшов дуже простий спосіб, з приємним і простим робочим прикладом тут

відобразити анімований віджет

Перш ніж почати працювати, в коді потрібно зробити декілька знаків

У НАСТУПНОМУ

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

просто замініть

setContentView(new MYGIFView());

в

setContentView(new MYGIFView(this));

І В

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

Надайте свій власний файл анімації gif

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

ЗАМІНА ПЕРШОЇ ЛІНІЇ В

public MYGIFView(Context context) {

відповідно до назви класу ...

після цього невеликих змін воно повинно працювати як для мене ...

сподіваюся, що ця допомога


2
На якій версії Android ви це спробували? Я спробував на Android версії 2.2 і 2.3, але він повертає об'єкт Movie null. Будь-яке уявлення про те, що може бути не так?
Ашвіні Шахапукаркар

16
Очистіть цю відповідь, так, випадково.
taxeeta

2
в чому проблема з відповіддю? Я щойно надав посилання та якийсь необхідний виправлення, щоб він працював
Apperside

10

Способи показу анімаційного GIF на Android:

  • Кіноклас. Як було сказано вище, це досить баггі.
  • WebView. Він дуже простий у використанні і зазвичай працює. Але іноді він починає погано поводитися, і це завжди на деяких незрозумілих пристроях, яких у вас немає. Крім того, ви не можете використовувати декілька примірників у будь-якому вигляді переглядів списків, оскільки це впливає на вашу пам'ять. Тим не менш, ви можете розглянути це як основний підхід.
  • Спеціальний код для декодування gif-файлів у растрові карти та показ їх як Dravable або ImageView. Я згадаю дві бібліотеки:

https://github.com/koral--/android-gif-dravable - декодер реалізований на C, тому це дуже ефективно.

https://code.google.com/p/giffiledecoder - декодер реалізований на Java, тому з ним легше працювати. Ще досить ефективно, навіть із великими файлами.

Ви також знайдете багато бібліотек на основі класу GifDecoder. Це також декодер на основі Java, але він працює, завантажуючи весь файл у пам'ять, тому застосовно лише до невеликих файлів.


10

Мені було дуже важко анімувати gif, працюючи в Android. У мене були лише два працюючих:

  1. WebView
  2. Іон

WebView працює нормально і дуже просто, але проблема полягає в тому, що він переглядає завантаження повільніше, і додаток не відповідатиме ні секунди. Мені це не сподобалось. Тому я спробував різні підходи (НЕ РОБОТИ):

  1. ImageViewEx застаріло!
  2. Пікассо не завантажив анімований gif
  3. android-gif-dravable виглядає чудово, але це спричинило деякі проблеми з NDK в моєму проекті. Це призвело до припинення роботи моєї місцевої бібліотеки NDK, і я не зміг її виправити

У мене було дещо назад і назад Ion; Нарешті, у мене це працює, і це дуже швидко :-)

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

У мене були ті ж проблеми, що стосуються NDK, з андроїд-gif-Dravable.
RominaV

Привіт @RominaV, Ви використовували смужку прогресу в Іоні при завантаженні gif, тому що мені потрібно показати прогрес при завантаженні gif.
patel135

9

Ковзання 4.6

1. Завантажити gif

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

2. Отримати об’єкт файлу

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

Бібліотека завантажувачів зображень для Android, рекомендована Google.

  • Glide досить схожий на Picasso, але це набагато швидше, ніж Picasso.
  • Glide споживає менше пам'яті, ніж Пікассо.

Що у цього Гліда є, але Пікассо не робить

Можливість завантаження анімації GIF на простий ImageView може бути найцікавішою особливістю Glide. І так, ви не можете цього зробити з Пікассо. Деякі важливі посилання-введіть тут опис зображення

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

Де Google рекомендує Glid?
Дерзу

1
Дивіться це, де команда розробників Android використовувала Glide у своєму прикладному додатку. developer.android.com/samples/XYZTouristAttractions/Application/…
Shoeb Siddique

1
"Glide досить схожий на Picasso, але це набагато швидше, ніж Picasso", і "Glide споживає менше пам'яті, ніж Picasso." Вибачте, я не задоволений цими ідеями . Віддайте перевагу за цим посиланням: medium.com/@multidots/glide-vs-picasso-930eed42b81d . До речі, зараз я не можу перевірити Glide 4.0 через те, що не в змозі оновити збірку до 3.0.1 (повільне підключення до Інтернету); але я тестував Glide 3.5.2 на показ gif, він працює, але не ідеально, як я очікував на великих img (це мерехтіння), і це також поширена проблема. Будь ласка, CMIW.
Nguyen Tan Dat

7

Використовуйте ImageViewEx , бібліотеку, яка робить використання gif так само просто, як і використання ImageView.


Це застаріло
Мартін Маркончіні

Я переглянув цей код бібліотек, він повинен бути хорошим протягом 2 або більше років.
NightSkyCode

1
Так, я думаю, що це відносно добре, лише зазначивши, що автор вирішив знехтувати це. (і, отже, не підтримувати), вказуючи на те, що ми повинні використовувати щось на кшталт Пікассо, що дивно, адже Пікассо є завантажувачем зображень і не допоможе вам, коли справа доводиться відображати анімований gif більше, ніж будь-який із багатьох завантажень / кеш-пам'яток інструменти там.
Мартін Маркончіні

6

Спробуйте це, внизу коду відображайте файл Gif на панелі прогресу

loading_activity.xml (у папці "Макет")

<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 (у папці, що витягується)

тут я поміщаю black_gif.gif (у папку, що витягується), ви можете розмістити тут свій gif

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

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. Чому?
АлікЕльзін-кілака

Як ви можете помістити gif в папку, що витягується?
Апурва


5

Я мав успіх із рішенням, запропонованим у цій статті , класом під назвою GifMovieView, який надає a, Viewякий потім може бути відображений або доданий до певногоViewGroup . Ознайомтесь з іншими методами, представленими у частинах 2 та 3 зазначеної статті.

Єдиним недоліком цього методу є те, що антиалізінг на фільм не настільки хороший (повинен бути побічним ефектом від використання "тінистого" Movieкласу Android ). Тоді вам краще налаштувати фон у суцільний колір у анімаційному GIF.


4

Деякі думки на прикладі BitmapDecode ... В основному він використовує стародавній, але досить безглуздий клас фільму від android.graphics. В останніх версіях API потрібно вимкнути апаратне прискорення, як описано тут . Інакше для мене це було грубо.

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

Ось приклад BitmapDecode, скорочений лише частиною GIF. Ви повинні зробити власний віджет (Перегляд) і намалювати його самостійно. Не настільки потужний, як 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();
            }
        }
    }
}

Ще два способи, один із ImageView, інший із WebView, можна знайти в цьому прекрасному підручнику . Метод ImageView використовує ліцензований Apache android-gifview з коду Google.


1
@luboz, будь ласка, скажіть, який метод хороший для роботи Android ... я хочу використовувати анімований gif для панелі завантаження екрана заставки. тож чи можете ви підказати, який метод краще. також я хочу знати, що за допомогою методу перегляду зображень можна використовувати властивість типу масштабу?
Swap-IOS-Android

4

@PointerNull дав хороше рішення, але це не ідеально. Він не працює на деяких пристроях з великими файлами і показує глюкозну анімацію Gif з дельта-кадрами за попередньою версією ICS. Я знайшов рішення без цих помилок. Це бібліотека з власним розшифруванням до малюваного: аралі-gif-Dravable для коралів .


2

Помістіть його у WebView, він повинен мати можливість правильно відображати його, оскільки браузер за замовчуванням підтримує файли gif. (Froyo +, якщо я не помиляюся)


Це не правда. Не всі браузери підтримують GIF.
RichieHH

4
Сподіваємось, нам не потрібні всі браузери ... Веб-браузер підтримує це з Android 2.2, тому не зволікайте мені, будь ласка. WebView обов'язково відобразить GIF!
keybee

2

Існує два варіанти завантаження анімаційних gif-файлів у наші програми для Android

1) Використання Glide для завантаження gif в 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) Використання html для завантаження gif в a WebView

Створіть html з адресою у файл .gif:

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

збережіть цей файл у каталозі активів:

введіть тут опис зображення

Завантажте цей HTML у WebView вашої програми:

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

Єрес є повним прикладом цих двох варіантів .

введіть тут опис зображення


2

Для лише Android API (Android Pie) 28 і +

використовувати AnimatedImageDrawable як

// 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-код, додайте 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 є дитиною Dravable та створений ImageDecoder.decodeDrawable

ImageDecoder.decodeDrawableщо додатково вимагало екземпляра ImageDecoder.Sourceствореного ImageDecoder.createSource.

ImageDecoder.createSourceможе приймати джерело лише як ім'я, ByteBuffer, File, resourceId, URI, ContentResolver для створення вихідного об'єкта і використовує його для створення AnimatedImageDrawableяк Drawable(поліморфний виклик)

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)

Примітка. Ви також можете створити Bitmapза допомогою ImageDecoder # decodeBitmap .

Вихід:

AnimatedDravable також підтримує маніпулювання розміром, рамкою та кольором


1

Я думаю, що краща бібліотека для обробки файлів gif це ця: за допомогою коралів

Використовую це, і я успішний, і ця бібліотека присвячена GIF'S; але де пікассо та ковзання є рамками зображення загального призначення ; тому я думаю, що розробники цієї бібліотеки повністю зосередилися на файлах gif



1

Просто хотів додати, що клас фільму зараз застарілий.

Цей клас застарілий у рівні API API.

Рекомендується використовувати це

AnimatedImageDrawable

Малюнок для малювання анімаційних зображень (наприклад, GIF).


1

Створіть пакет під назвою "Utils" у папці src та створіть клас під назвою "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");
        }
    }
}

Тепер визначте GifImageView у файлі 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);
    }
}

Тепер файл частини інтерфейсу: 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>

Resourece код: приклад Android


як змінити розмір зображення, pls
Мертвий хлопець

0

Насамперед браузер Android повинен підтримувати анімовані GIF. Якщо ні, то це помилка! Погляньте на проблеми з відстеженням проблем.

Якщо ви показуєте ці анімовані GIF-файли поза веб-переглядачем, це може бути інша історія. Щоб зробити те, що ви просите, знадобиться зовнішня бібліотека, яка підтримує розшифровку анімованих GIF-файлів.

Першим портом дзвінка було б подивитися API Java2D або JAI (Java Advanced Imaging), хоча я був би дуже здивований, якщо Android Dalvik підтримає ці бібліотеки у вашому додатку.


деякі пристрої не показують анімовані gif-файли навіть у веб-переглядачі. як приклад, я знаю, що галактика mini з Android 2.3.6 не показує їх.
андроїд розробник

0

Схоже на те, що сказав @Leonti, але з трохи більшою глибиною:

Що я зробив, щоб вирішити ту саму проблему, це відкрити GIMP, приховати всі шари, крім одного, експортувати його як власне зображення, а потім приховати цей шар і приховати наступний і т. Д., Поки у мене не з'явилися окремі файли ресурсів для кожного . Тоді я міг би використовувати їх як кадри у XML-файлі AnimationDravable.


1
Ви можете використовувати gifsicle для витягування кадрів, якщо у вас не так багато часу. Також python або bash дуже зручні при генерації XML-файлів.
lubosz


0

Щось я зробив для показу gif-програм у додатках. Я розширив ImageView, щоб люди могли вільно використовувати його атрибути. Він може показувати gif з URL-адреси або з каталогу активів. Бібліотека також полегшує розширення класів для успадкування від неї та розширення для підтримки різних методів ініціалізації gif.

https://github.com/Gavras/GIFView

На сторінці github є невеликий довідник.

Він також був опублікований на Android Arsenal:

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

Приклад використання:

Від 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" />

У діяльності:

    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 програмно:

mGifView.setGifResource("asset:gif1");

0

Найпростіший спосіб - можна розглянути наведений нижче код

Ми можемо скористатися Imageview setImageResource, наведений нижче код для того ж.

Наведений нижче код може бути використаний для показу зображення як gif incase, якщо у вас є декілька розділених зображень gif. Просто розділіть GIF на індивідуальний png від онлайн-інструменту і поставте зображення в малюнок, як у наведеному нижче порядку

image_1.png, image_2.png тощо

Запропонуйте оброблювачу динамічно змінювати зображення.

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

Найпростішим способом відображення анімованого GIF безпосередньо з URL-адреси до макета додатка є використання класу WebView.

Крок 1. У вашому макеті XML

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

Крок 2: У вашій діяльності

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

Крок 3. У Manifest.XML зробіть дозвіл на Інтернет

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

Крок 4: Якщо ви хочете зробити ваш GIF фон прозорим і зробити GIF підходящим до вашого макета

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


Дякую за обхід, але значний розробник може не захотіти мати ненормативну візуалізацію через деякі наслідки, як вплив на пам'ять, використання процесора та час роботи акумулятора
ruX

-1

Ви можете використовувати бібліотеку GifAnimationDrawable, яку ви знайдете за цим посиланням - https://github.com/Hipmob/gifanimateddrawable , і які перетворять будь-який gif в AnimationDrawable. Насолоджуйтесь :)


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

      }
    }
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.