こんにちは、楽しい休日を!多くの検索の後、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();
}
}