Андроид:Как отобразить большой анимированный GIF-файл по URL-адресу?

StackOverflow https://stackoverflow.com/questions/809878

  •  03-07-2019
  •  | 
  •  

Вопрос

Предположим, у меня есть URL-адрес большого анимированного GIF-файла, и я хочу создать действие, подобное YouTube, которое отображает анимацию в потоковом режиме.Как мне

  1. поток в изображении?
  2. заставить его отображать настоящую анимацию?

Я знаю ImageView это не ответ, поскольку показывает только первый кадр.

Бонусом будет доступ к состоянию его буферизации, чтобы я мог также синхронизировать потоковый звук — это часть YTMND приложение для просмотра.Хотя я мог бы создать сервис, который перекодирует общедоступные файлы gif в более удобный формат, мне бы хотелось, чтобы приложение функционировало без дополнительных зависимостей.

Это было полезно?

Решение

Общий набросок решения заключается в использовании пользовательского интерфейса. View который рисует спрашивает Movie привлечь себя к Canvas периодически.

Первым шагом является создание Movie пример.Есть фабрика под названием decodeStream который может сделать фильм, учитывая InputStream но недостаточно использовать поток из UrlConnection.Если вы попробуете это, вы получите IOException когда загрузчик фильма пытается позвонить reset на потоке.Хак, каким бы неудачным он ни был, заключается в использовании отдельного BufferedInputStream с ручной установкой mark чтобы сказать ему сохранить достаточно данных, чтобы reset не подведет.К счастью, URLConnection может сказать нам, какой объем данных следует ожидать.Я считаю, что этот хак неудачен, поскольку он фактически требует буферизации всего изображения в памяти (что не является проблемой для настольных приложений, но является серьезной проблемой на мобильном устройстве с ограниченной памятью).

Вот фрагмент Movie код установки:

URL url = new URL(gifSource);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bis.mark(conn.getContentLength());
Movie movie = Movie.decodeStream(bis);
bis.close();

Далее вам нужно создать представление, которое будет отображать это Movie.Подкласс View с обычаем onDraw сделает свое дело (при условии, что у него есть доступ к Movie вы создали с помощью предыдущего кода).

@Override protected void onDraw(Canvas canvas) {
    if(movie != null) {
        long now = android.os.SystemClock.uptimeMillis();
        int dur = Math.max(movie.duration(), 1); // is it really animated?
        int pos = (int)(now % dur);
        movie.setTime(pos);
        movie.draw(canvas, x, y);
    }
}

Представление не будет перерисовываться без посторонней помощи и слепо вызывать invalidate() в конце onDraw это просто трата энергии.В другом потоке (вероятно, том, который вы использовали для загрузки данных изображения) вы можете отправлять сообщения в основной поток с просьбой сделать представление недействительным с постоянной (но не безумной) скоростью.

Handler handler = new Handler();
new Thread() {
    @Override public void run() {
        // ... setup the movie (using the code from above)
        // ... create and display the custom view, passing the movie

        while(!Thread.currentThread().isInterrupted()) {
            handler.post(new Runnable() {
                public void run(){
                    view.invalidate();
                }
            });
            try {
                Thread.sleep(50); // yields 20 fps
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}.start();

Действительно хорошее решение имело бы всевозможные индикаторы выполнения и проверку ошибок, но суть здесь.

Другие советы

Ты пробовал BitmapDecode?

В демонстрациях API есть пример. здесь.

Скольжение доказать самый простой и эффективный способ добиться этого с помощью всего одной строки кода: -

Glide.with(getApplicationContext())
            .load(Uri.parse("https://media1.giphy.com/media/5ziaphcUWGKPu/200.gif"))
            .asGif().placeholder(R.drawable.ic_launcher).crossFade()
            .into(imageView);

Результат здесь: -

enter image description here

Гифка взята отсюда http://giphy.com/search/big-gif/3

Добавьте банку отсюда: - https://github.com/bumptech/glide/releases

Может быть АнимацияDrawable может работать на тебя?РЕДАКТИРОВАТЬ:Нет, если вы хотите загружать с URL-адреса, о котором рассказывается в этом посте.Извини

http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

В зависимости от сложности GIF, т.е.если это простой индикатор загрузки/прогресса, вы можете разбить GIF на части, сохранить каждое изображение отдельно и использовать AnimationDrawable в Android Framework.

Для простых индикаторов выполнения это может быть менее подвержено ошибкам и, возможно, даже более производительно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top