Android:SurfaceView闪烁

时间:2015-10-01 20:40:07

标签: android bitmap android-canvas surfaceview

我在绘制到If (input == 0){ Syso "You Tied" } Else { If (input == -1){ Syso "You Lose" } If (input == 1){ Syso "You Win" } If (input == 2){ Syso "You Lose" } If (input == -2){ Syso "You Win" } } 时遇到问题,当移动SurfaceView上的位图图像时,它们会闪烁(或撕裂)。我在以前的代码迭代中没有遇到这个问题。但是现在我终于通过为每个位图使用单独的SurfaceView来正确缩放位图,这个问题就开始发生了。这些是我的自定义Canvas类的重要部分:

SurfaceView

这是我的自定义public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback { public DrawingSurface(Context context, AttributeSet attributeSet, int defStyle) { super(context, attributeSet, defStyle); initialize(context); } private void initialize(Context context) { mContext = context; getHolder().addCallback(this); setFocusable(true); } @Override public void surfaceCreated(SurfaceHolder holder) { mHost = (EditorActivity) mContext; Log.d("DrawingSurface", "SURFACE CREATED"); mDrawingThread = new DrawingThread(this, REFRESH_RATE); mDrawingThread.setRunning(true); mDrawingThread.start(); onConfigurationChanged(getResources().getConfiguration()); } public Bitmap createBitmap() { Bitmap bitmap = Bitmap.createBitmap(mBitmap); Canvas canvas = new Canvas(bitmap); Sticker[] stickers = mStickers.toArray(new Sticker[mStickers.size()]); for (Sticker sticker : stickers) { canvas.drawBitmap(sticker.getBitmap(), new Matrix(), mPaint); } return bitmap; } public void drawSurface(Canvas canvas) { Bitmap bitmap = createBitmap(); mMatrix.setScale(1.0f / mScaleFactor, 1.0f / mScaleFactor); canvas.drawBitmap(bitmap, mMatrix, mPaint); } private void setScaleFactor() { mScaleFactor = ((float) mBitmap.getWidth()) / getWidth(); } public void addSticker(int drawableId) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; Sticker sticker = new Sticker( BitmapFactory.decodeResource(getResources(), drawableId, options), new PointF(mBitmap.getWidth(), mBitmap.getHeight()), mScaleFactor); mActiveSticker = sticker; mStickers.add(sticker); } }

Thread

标签类用于保存每个单独的public class DrawingThread extends Thread { private volatile boolean mRunning = false; private long mRefreshRate; private DrawingSurface mSurface; public DrawingThread (DrawingSurface surface, long time) { super(); mSurface = surface; mRefreshRate = time; } public void setRunning (boolean run) { mRunning = run; Log.d("DrawingThread", "Running: " + mRunning); } @Override public void run() { while (mRunning) { try { sleep(mRefreshRate); onSurfaceUpdate(); } catch (InterruptedException exception) { exception.printStackTrace(); } } } public void onSurfaceChanged(Configuration config, Point fit, float ratio) { float width, height; if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { width = fit.y * ratio; height = fit.y; } else if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { width = fit.x; height = fit.x / ratio; } else { width = fit.x; height = fit.x / ratio; } mSurface.getHolder().setFixedSize((int) width, (int) height); } private void onSurfaceUpdate() { Canvas canvas = null; try { canvas = mSurface.getHolder().lockCanvas(); synchronized (mSurface.getHolder()) { if (canvas != null) { mSurface.drawSurface(canvas); } } } finally { if (canvas != null) { mSurface.getHolder().unlockCanvasAndPost(canvas); } } } } Canvas

Bitmap

我在StackOverflow以及其他网站上找到了关于同一主题的各种讨论。所有这些都得出结论,闪烁是由于public class Sticker { private static final float START_SCALE = 0.5f; private static final float MIN_SCALE = 0.3f; private static final float MAX_SCALE = 7f; private float mScale = 1f; private float mScaleFactor; private Canvas mCanvas = new Canvas(); private Bitmap mSticker; private Bitmap mSurface; private PointF mCenter = new PointF(); private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Matrix mMatrix = new Matrix(); public Sticker(Bitmap sticker, PointF size, float scaleFactor) { mSticker = sticker; mSurface = Bitmap.createBitmap((int) size.x, (int) size.y, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mSurface); mCanvas.drawColor(0, PorterDuff.Mode.CLEAR); setScaleFactor(scaleFactor); postSticker(); } private void postSticker() { mMatrix.postScale(START_SCALE, START_SCALE); setCenter(); setTranslate(mCenter.x, mCenter.y); } public boolean collider(PointF point) { int x = (int) (point.x * mScaleFactor); int y = (int) (point.y * mScaleFactor); int color = mSurface.getPixel(x, y); if(color != Color.TRANSPARENT) { return true; } else { return false; } } public Bitmap getBitmap() { return mSurface; } public void flipSticker() { Matrix matrix = new Matrix(); matrix.preScale(-1, 1); mSticker = Bitmap.createBitmap(mSticker, 0, 0, mSticker.getWidth(), mSticker.getHeight(), matrix, false); } public void setScaleFactor(float scaleFactor) { mScaleFactor = scaleFactor; } public void setTranslate(float deltaX, float deltaY) { mMatrix.postTranslate(deltaX * mScaleFactor, deltaY * mScaleFactor); draw(); } public void setScale(float deltaScale, PointF midpoint) { mScale *= deltaScale; if(MIN_SCALE < mScale && mScale < MAX_SCALE) { mMatrix.postScale(deltaScale, deltaScale, midpoint.x * mScaleFactor, midpoint.y * mScaleFactor); } draw(); } public void setRotate(float deltaRotate, PointF midpoint) { mMatrix.postRotate(deltaRotate, midpoint.x * mScaleFactor, midpoint.y * mScaleFactor); draw(); } private void setCenter() { float width = (mSurface.getWidth() / 2) - ((mSticker.getWidth() / 2) * START_SCALE); float height = (mSurface.getHeight() / 2) - ((mSticker.getHeight() / 2) * START_SCALE); mCenter.set(width, height); } private void draw() { mCanvas.drawColor(0, PorterDuff.Mode.CLEAR); mCanvas.drawBitmap(mSticker, mMatrix, mPaint); } } 如何处理缓冲,使用两个表面进行交换。解决方案包括使用单独的位图首先绘制所有图像,然后将该位图绘制到SurfaceView。正如您所看到的,我已经使用SurfaceView方法完成了此操作,但闪烁仍然存在。

1 个答案:

答案 0 :(得分:0)

我认为闪烁是由于CanvascreateBitmap()中使用之前未完成对位图的绘制。我将方法getBitmap()更改为返回mSticker而不是更大的mSurface(用于检测用户触摸的位置),因此绘制的位图不是那么大。我添加了方法getMatrix()以从mMatrix返回Sticker,并将其用于canvas.drawBitmap()中的createBitmap()方法。这停止了​​闪烁,即使我用于贴纸的png文件相当大(大多数是1024 x 1024)。