需要帮助尝试在 TextView 中制作 gif 动画

Need help in attempt to animate gif inside TextView

我希望能够将动画 gif 加载到文本之间的 Textview 中,这就是我想出的:

我用Html.fromHtml

由于一个 gif 可以出现多次,所以我将所有加载的不同 gif 制作成一个数组,这样我就可以将引用传回(尽管在这个测试器中没有使用)

这是我目前得到的:

public class MainActivity extends Activity implements ImageGetter {
    private TextView mTv;
    private Map<String, LevelListDrawable> gifs;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gifs = new HashMap<>();
        String imgs="<p><img alt=\"\" src=\"http://lonelytraveller.comoj.com/qff/tjatja.gif\" style=\"height:50px; width:100px\" />Test Article, Test Article, Test Article, Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,v</p>";
        Spanned spanned = Html.fromHtml(imgs, this, null);
        mTv = (TextView) findViewById(R.id.tv);
        mTv.setText(spanned);

    }

    @Override
    public Drawable getDrawable(String source) {
        if(gifs.get(source.split("\Q/\E")[source.split("\Q/\E").length-1]) != null){
            return gifs.get(source.split("\Q/\E")[source.split("\Q/\E").length-1]);
        }else {
            LevelListDrawable d = new LevelListDrawable();
            Drawable empty = ContextCompat.getDrawable(this, R.drawable.save);
            d.addLevel(0, 0, empty);
            d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());

            new LoadImage().execute(source, d);

            return d;
        }
    }

    class LoadImage extends AsyncTask<Object, Void, byte[]> {

        private LevelListDrawable mDrawable;
        private String key;
        @Override
        protected byte[] doInBackground(Object... params) {
            String source = (String) params[0];
            key = source.split("\Q/\E")[source.split("\Q/\E").length-1];
            mDrawable = (LevelListDrawable) params[1];
            try {
                InputStream is = new URL(source).openStream();
                return IOUtils.toByteArray(is);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(byte[] bytes) {
            if(bytes != null) {
                GifDecoder decoder = new GifDecoder();
                decoder.read(bytes);
                ArrayList<Long> alist = new ArrayList<>();
                for (int i = 0; i < decoder.getFrameCount(); i++) {
                    decoder.advance();
                    Bitmap bitmap = decoder.getNextFrame();
                    BitmapDrawable d = new BitmapDrawable(getResources(), bitmap);
                    int i2 = i+1;
                    mDrawable.addLevel(i2, i2, d);
                    mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
                    alist.add((long) decoder.getNextDelay());
                }
                gifs.put(key, mDrawable);
                animateGif(decoder.getFrameCount(), mDrawable, alist);
            }
        }
    }
    public void animateGif(int length, LevelListDrawable d, ArrayList<Long> delays){
        for(int i = 1; i<(length+1); i++){
            d.setLevel(i);

            CharSequence t = mTv.getText();
            mTv.setText(t);

            long sleep = delays.get(i-1);
            try {
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(i == length) i=1;
        }
    }
}

我使用这个 GifDecoder:https://gist.github.com/devunwired/4479231

使用我在上面发布的代码,如果我在 animateGif 函数中放置一个日志,我只能得到空的可绘制对象(级别 0)我可以看到他确实进行了无限循环,但它只是不起作用它停留在空的可绘制图像;

如果我将 onPostExecute 函数的内容更改为:

    if(bytes != null) {
        GifDecoder decoder = new GifDecoder();
        decoder.read(bytes);
        decoder.advance();
        Bitmap bitmap = decoder.getNextFrame();
        BitmapDrawable d = new BitmapDrawable(getResources(), bitmap);
        mDrawable.addLevel(1, 1, d);
        mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
        mDrawable.setLevel(1);

        CharSequence t = mTv.getText();
        mTv.setText(t);
    }

它确实将空图像更改为 gif 文件的第一帧。 我只是不明白为什么这行不通,有人可以帮助我吗?

感谢 android-dev irc..

的 jawatio 的帮助,我解决了这个问题

通过将此依赖项添加到 build.gradle 文件:

编译'pl.droidsonroids.gif:android-gif-drawable:1.2.6'

来自:https://github.com/koral--/android-gif-drawable

然后做这样的事情:

public class test extends Activity implements Drawable.Callback {

 public TextView tv;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        tv = (TextView) findViewById(R.id.testtext);
        new LoadImage().execute("http://lonelytraveller.comoj.com/qff/tjatja.gif");

    }

    @Override
    public void invalidateDrawable(Drawable who) {
        tv.invalidate();
    }

    @Override
    public void scheduleDrawable(Drawable who, Runnable what, long when) {
        tv.postDelayed(what, when);
    }

    @Override
    public void unscheduleDrawable(Drawable who, Runnable what) {
        tv.removeCallbacks(what);
    }


    class LoadImage extends AsyncTask<Object, Void, byte[]> {

        private String key;
        @Override
        protected byte[] doInBackground(Object... params) {
            String source = (String) params[0];
            //key = source.split("\Q/\E")[source.split("\Q/\E").length-1];
            try {
                InputStream is = new URL(source).openStream();
                return IOUtils.toByteArray(is);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(byte[] b) {
            SpannableStringBuilder ssb = new SpannableStringBuilder("test");
            GifDrawable gd = null;
            try {
                gd = new GifDrawable(b);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (gd != null) {
                gd.setBounds(0, 0, gd.getIntrinsicWidth(), gd.getIntrinsicHeight());

                gd.setCallback(test.this);

                ssb.setSpan(new ImageSpan(gd), 1, 2, 0);
                tv.setText(ssb);
            }
        }
    }
}