我使用SurfaceView
和Canvas
开发了带有GIF的壁纸。当GIF必须更新和更改时。但问题是,当更新屏幕的时间变为黑色时。
此处来自WallpaperEngine
class WallpaperEngine extends Engine implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "WallpaperEngine";
private AnimationThread animationThread;
private SurfaceHolder mSurfaceHolder;
private Scene scene;
private Movie movie1;
private Movie movie2;
private Movie movie3;
private Movie movie4;
private Movie movie5;
private Bitmap bitmap1;
private Bitmap bitmap2;
private Bitmap bitmap3;
private Bitmap bitmap4;
private BitmapFactory.Options opts, bitmapOptions;
private SharedPreferences prefs;
private float dx = 0.0f;
private int mWidth, mHeight;
WallpaperManager myWallpaperManager;
View view;
WindowManager.LayoutParams lp;
@SuppressLint("NewApi")
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
Log.d(TAG, "onCreate");
mSurfaceHolder = surfaceHolder;
opts = new BitmapFactory.Options();
opts.inSampleSize = 2;
bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 1;
myWallpaperManager = WallpaperManager.getInstance(getApplicationContext());
prefs = PreferenceManager.getDefaultSharedPreferences(Wallpaper.this);
prefs.registerOnSharedPreferenceChangeListener(this);
checkCurrentTime();
movie1 = Movie.decodeStream(getResources().openRawResource(R.raw.fountain));
movie2 = Movie.decodeStream(getResources().openRawResource(R.raw.idle_cycle));
movie3 = Movie.decodeStream(getResources().openRawResource(R.raw.tree_move));
movie4 = Movie.decodeStream(getResources().openRawResource(R.raw.wash_full));
movie5 = Movie.decodeStream(getResources().openRawResource(R.raw.prayer_full));
DisplayMetrics displayMetrics = new DisplayMetrics();
Display display = ((WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
// create the scene
scene = new Scene(sky, ground, town, middle, movie1, movie2, movie3, null, null, mHeight);
// start animation thread; thread starts paused
// will run onVisibilityChanged
animationThread = new AnimationThread(mSurfaceHolder, scene);
animationThread.start();
}
当需要更改GIF动画时,我调用updateWallpapers()
方法:
private void updateWallpapers(int skyId, int townId, int middleId, Movie movie2, Movie movie4, Movie movie5) {
sky = BitmapFactory.decodeResource(getResources(), skyId);
ground = BitmapFactory.decodeResource(getResources(), R.drawable.ground_plainblack, opts);
town = BitmapFactory.decodeResource(getResources(), townId);
middle = BitmapFactory.decodeResource(getResources(), middleId);
if (movie2 != null) {
scene = new Scene(sky, ground, town, middle, movie1, movie2, movie3, null, null, mHeight);
} else if (movie4 != null) {
scene = new Scene(sky, ground, town, middle, movie1, null, movie3, movie4, null, mHeight);
} else if (movie5 != null) {
scene = new Scene(sky, ground, town, middle, movie1, null, movie3, null, movie5, mHeight);
}
animationThread.stopThread();
joinThread(animationThread);
animationThread = null;
animationThread = new AnimationThread(mSurfaceHolder, scene);
animationThread.start();
animationThread.resumeThread();
}
AnimationThread
上课,我认为这是问题,但我无法解决它:
public class AnimationThread extends Thread {
private static final String TAG = "AnimationThread";
private Object pauseLock = new Object();
private boolean running = true;
private boolean paused = true;
private int fps = 30;
private int timeFrame = 1000 / fps; // drawing time frame in miliseconds 1000 ms / fps
final private SurfaceHolder surfaceHolder;
private Scene scene;
public AnimationThread(SurfaceHolder surfaceHolder, Scene scene) {
this.surfaceHolder = surfaceHolder;
this.scene = scene;
}
@Override
public void run() {
while (running) {
waitOnPause();
if (!running) {
return;
}
long beforeDrawTime = System.currentTimeMillis();
Canvas canvas = null;
try {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
/** Clean Canvas before draw.
When I erase this line screen not changing and it draws GIFs above each other, layer by layer.
But now when I update GIFs screen just turns black and freezes on this state.
HERE'S THE PROBLEM!!! */
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
}
/** Workaround for: SurfaceTextureClient: dequeueBuffer failed (No such device) */
if (canvas == null) {
continue;
}
synchronized (surfaceHolder) {
scene.draw(canvas);
}
} catch (IllegalArgumentException e) {
Log.e(TAG, "Error during surfaceHolder.lockCanvas()", e);
stopThread();
} finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Error during unlockCanvasAndPost()", e);
stopThread();
}
}
}
long afterDrawTime = System.currentTimeMillis() - beforeDrawTime;
try {
if (timeFrame > afterDrawTime) {
Thread.sleep(timeFrame - afterDrawTime);
}
} catch (InterruptedException ex) {
Log.e(TAG, "Exception during Thread.sleep().", ex);
}
}
}
public void stopThread() {
synchronized (pauseLock) {
paused = false;
running = false;
pauseLock.notifyAll();
}
Log.d(TAG, "Stopped thread (" + this.getId() + ")");
}
public void pauseThread() {
synchronized (pauseLock) {
paused = true;
}
Log.d(TAG, "Paused thread (" + this.getId() + ")");
}
public void resumeThread() {
synchronized (pauseLock) {
paused = false;
pauseLock.notifyAll();
}
Log.d(TAG, "Resumed thread (" + this.getId() + ")");
}
private void waitOnPause() {
synchronized (pauseLock) {
while (paused) {
try {
pauseLock.wait();
} catch (InterruptedException e) {
}
}
}
}
}
Scene
上课:
public class Scene {
private Bitmap background = null;
private Bitmap ground = null;
private Bitmap town = null;
private Bitmap middle = null;
private Movie movie1 = null;
private Movie movie2 = null;
private Movie movie3 = null;
private Movie movie4 = null;
private Movie movie5 = null;
private Rect rectangleFrame = null;
private int height;
private int width;
private float dx;
private int centerX;
private int centerY;
public Scene(Bitmap backgroundImg, Bitmap groundImg, Bitmap townImg, Bitmap middleImg,
Movie movie1, Movie movie2, Movie movie3 Movie movie4,
Movie movie5, int screenHeight) {
background = backgroundImg;
town = townImg;
middle = middleImg;
ground = groundImg;
height = screenHeight;
this.movie1 = movie1;
this.movie2 = movie2;
this.movie3 = movie3;
this.movie3 = movie4;
this.movie4 = movie5;
}
public synchronized void updateSize(int width, int height, float dx) {
this.dx = dx;
centerY = height / 2;
this.height = height;
this.width = width;
}
public synchronized void draw(Canvas canvas) {
canvas.save();
canvas.translate(dx, 0);
rectangleFrame = new Rect(0, 0, (int) (this.width * 2.5), this.height);
centerX = rectangleFrame.centerX() / 2;
canvas.drawBitmap(background, null, rectangleFrame, null);
canvas.drawBitmap(town, null, rectangleFrame, null);
canvas.drawBitmap(middle, null, rectangleFrame, null);
canvas.drawBitmap(ground, null, rectangleFrame, null);
movie1.draw(canvas, centerX - (movie3.width() / 2),
(rectangleFrame.centerY() + (rectangleFrame.centerY() / 1.65f)) - this.movie1.height());
if (movie2 != null) {
movie2.draw(canvas, centerX,
(rectangleFrame.centerY() + (rectangleFrame.centerY() / 1.6f)) - movie2.height());
}
if (movie4 != null) {
movie4.draw(canvas, centerX - (movie3.width() / 2 - this.movie1.width() + 30),
(rectangleFrame.centerY() + (rectangleFrame.centerY() / 1.6f)) - movie4.height());
}
if (movie5 != null) {
movie5.draw(canvas, centerX,
(rectangleFrame.centerY() + (rectangleFrame.centerY() / 1.6f)) - movie5.height());
}
movie3.draw(canvas, centerX + this.movie1.width(),
(rectangleFrame.centerY() + (rectangleFrame.centerY() / 1.6f)) - movie3.height());
canvas.restore();
this.movie1.setTime((int) (System.currentTimeMillis() % this.movie1.duration()));
if (movie2 != null) {
movie2.setTime((int) (System.currentTimeMillis() % movie2.duration()));
}
if (movie4 != null) {
movie4.setTime((int) (System.currentTimeMillis() % movie4.duration()));
}
if (movie5 != null) {
movie5.setTime((int) (System.currentTimeMillis() % movie5.duration()));
}
movie3.setTime((int) (System.currentTimeMillis() % movie3.duration()));
}
任何帮助将不胜感激!谢谢!
答案 0 :(得分:0)
在我的代码上花了很多时间后,我终于找到了解决方案!我刚删除了这一行canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
并在updateSize()
实施后添加了AnimationThread
方法,如下所示:
animationThread.stopThread();
joinThread(animationThread);
animationThread = null;
animationThread = new AnimationThread(mSurfaceHolder, scene);
animationThread.start();
animationThread.resumeThread();
/**----------------Here!!!---------------*/
scene.updateSize(mWidth, mHeight, dx);
现在它运作正常!