1

你好,节日快乐!经过大量搜索,我最终定义了一个自定义类来在 android 上播放动画 gif。在某些手机中它可以完美运行,但在某些手机(和一些模拟器配置文件)中却没有。问题是蓝色“闪烁”(视频示例)。我尝试启用/禁用硬件加速渲染,但没有效果。任何想法?

/**
 * Main proportion of this class is to play .gif files with the minimum CPU and
 * memory demands. Is way more memory efficient than DrawableAnimation class,
 * the only drawback is that you have to specify targetSdkVersion="3" in
 * Manifest.xml cause of backward incompatibilities.
 * 
 * @author Nilos Psathas
 * 
 */
public class GifMovieView extends View
{
    private Movie movie;
    private long movieStart;

    /**
     * should we keep the last frame when the animation ends? or we will shown
     * the first frame again?
     */
    private boolean keepLastFrame;
    private boolean stopInformed;
    private float sx;
    private float sy;
    private int elapsed;

    private GifAnimListener listener;

    public GifMovieView(Context context, int resId)
    {
        super(context);
        InputStream s = null;

        byte[] bytes = null;

        s = context.getResources().openRawResource(resId);
        try
        {
            bytes = new byte[s.available()];
            s.read(bytes);
        }
        catch (IOException ex)
        {
            Log.d("anim", "cant load a gif! " + ex);
        }

        movie = Movie.decodeByteArray(bytes, 0, bytes.length);

        stopInformed = keepLastFrame = false;
        movieStart = -1;
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        canvas.drawColor(Color.TRANSPARENT);
        canvas.scale(sx, sy);
        super.onDraw(canvas);

        if (movieStart == -1)
        {
            return;
        }

        long now = SystemClock.uptimeMillis();

        if (movieStart == 0)
        {
            movieStart = now;
            listener.onAnimStart();
        }

        elapsed = (int) (now - movieStart);

        if (!isRunning())
        {
            if (keepLastFrame)
            {
                movie.setTime(movie.duration());
            }
            else
            {
                movie.setTime(0);
            }

            if (!stopInformed)
            {
                stopInformed = true;
                listener.onAnimEnd();
            }
        }
        else
        {
            int relTime = (int) ((elapsed) % movie.duration());
            movie.setTime(relTime);
        }

        movie.draw(canvas, 0, 0);
        this.invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        sx = ((float) getWidth()) / ((float) movie.width());
        sy = ((float) getHeight()) / ((float) movie.height());
    }

    public void start()
    {
        stopInformed = false;
        movieStart = 0;
        setVisibility(VISIBLE);
        invalidate();
    }

    public void forceStop()
    {
        setVisibility(GONE);
        movieStart = -1;
        listener.onForceStop();
    }

    public void stop()
    {
        movieStart = SystemClock.uptimeMillis() - movie.duration();
        invalidate();
    }

    public boolean isRunning()
    {
        return movieStart != -1 && elapsed < movie.duration();
    }

    public void setKeepLastFrame(boolean keepLast)
    {
        keepLastFrame = keepLast;
    }

    public void setListener(GifAnimListener listener)
    {
        this.listener = listener;
    }

    /**
     * Simple interface for animation events
     * 
     * @author Nilos Psathas
     * 
     */
    public interface GifAnimListener
    {
        public void onAnimStart();

        public void onAnimEnd();

        public void onForceStop();
    }
}
4

0 回答 0