首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LiveWallpaper与SurfaceHolder.lockCanvas(Rect脏)

LiveWallpaper与SurfaceHolder.lockCanvas(Rect脏)
EN

Stack Overflow用户
提问于 2011-03-04 07:10:36
回答 1查看 3.4K关注 0票数 6

我想问一次或两次在这里讨论的问题,但我发现的任何信息都不能帮助我克服几天前我面临的问题。

我想用画布为安卓做一张活壁纸--它在图形上不够复杂,不需要OpenGL。为了简单起见,假设它由坚实的背景和两个较小的矩形组成。绘图由三个独立的阶段(单线程)组成:

  1. backgroundDraw()请求整个画布锁,并在此基础上绘制实色
  2. draw1()请求部分(Rect r1)锁,只绘制锁定的rectangle
  3. draw2()请求部分(Rect r2)锁,并仅在锁定的矩形

上绘图。

我在多个Android版本(模拟器和设备)上测试了它: 2.1、2.2、2.3.3。它似乎只在后一种情况下正常工作(这里是:http://home.elka.pw.edu.pl/~pgawron/include/Android/android_233.jpg)。在以前的安卓版本中,SurfaceHolder.lockCanvas(Rect脏)调整大小(!)脏作为参数传递给整个屏幕的大小,然后使用它在整个屏幕上进行结果绘图(此处:http://home.elka.pw.edu.pl/~pgawron/include/Android/android_22.jpg)。事实上,我可以看到每个矩形是如何被错误地绘制(全屏):整个屏幕改变它的颜色非常快。

不幸的是,谷歌没有为我找到任何正确的例子,lockCanvas(重脏)用法。下面我附上了我的完整的,也是唯一用于测试的类。只要设置屏幕截图,就可以访问完全eclipse项目。

如果有人能最终帮助我并纠正我的代码(如果问题在我的代码中),我将非常感激。我真的浪费了太多时间在这上面。

BR

佩里

代码语言:javascript
复制
package sec.polishcode.test;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.SystemClock;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.SurfaceHolder;

public class TestLiveWallpaper extends WallpaperService{

@Override
public Engine onCreateEngine() {
    return new MyEngine();
}

class MyEngine extends Engine implements SurfaceHolder.Callback {

    private final String LOGTAG = MyEngine.class.getSimpleName();
    private Paint backgroundPaint = new Paint();
    private Paint mPaint1 = new Paint();
    private Paint mPaint2 = new Paint();
    private long lastVisibilityOnChange;

    private final Rect r1 = new Rect(20, 20, 60, 280);
    private final Rect r2 = new Rect(70, 20, 110, 280);

    public MyEngine() {

        getSurfaceHolder().addCallback(this);

        backgroundPaint.setColor(Color.YELLOW);
        mPaint1.setColor(Color.LTGRAY);
        mPaint2.setColor(Color.MAGENTA);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
            int arg3) {
        drawSurface();
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        Log.i(LOGTAG, "surfaceCreated");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        Log.i(LOGTAG, "surfaceDestroyed");
    }

    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
        super.onCreate(surfaceHolder);

        setTouchEventsEnabled(true);
    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        if (!visible)
            return;

        lastVisibilityOnChange = SystemClock.elapsedRealtime();
        drawSurface();
    }

    @Override
    public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
            float yStep, int xPixels, int yPixels) {

        if (SystemClock.elapsedRealtime() - lastVisibilityOnChange > 30)
            return;

        Log.i(LOGTAG, "onOffsetsChanged filtered");
        drawSurface();
    }

    private void drawSurface() {
        backgroundDraw();
        draw1();
        draw2();
    }

    private void backgroundDraw() {
        final SurfaceHolder holder = getSurfaceHolder();

        Canvas c = null;
        try {
            c = holder.lockCanvas();
            if (c != null) {
                c.drawRect(holder.getSurfaceFrame(), backgroundPaint);
            }
        } finally {
            if (c != null)
                holder.unlockCanvasAndPost(c);
        }
    }

    private void draw1() {
        final SurfaceHolder holder = getSurfaceHolder();

        Canvas c = null;
        try {
            c = holder.lockCanvas(r1);
            if (c != null) {
                c.drawRect(r1, mPaint1);
            }
        } finally {
            if (c != null)
                holder.unlockCanvasAndPost(c);
        }
    }

    private void draw2() {
        final SurfaceHolder holder = getSurfaceHolder();

        Canvas c = null;
        try {
            c = holder.lockCanvas(r2);
            if (c != null) {
                c.drawRect(r2, mPaint2);
            }
        } finally {
            if (c != null)
                holder.unlockCanvasAndPost(c);
        }
    }
}
}
EN

回答 1

Stack Overflow用户

发布于 2011-08-14 03:47:22

lockCanvas(Rect脏的)非常简单。请记住,在默认情况下,Android表面是双缓冲的。这意味着您不仅需要重新绘制当前表面的脏区域,还需要重新绘制前一个表面的脏区域,以使其正常工作。这就是为什么lockCanvas()将调整您传递的矩形的大小:它告诉真正的脏区域是什么。脏区域可能也会改变,因为曲面被丢弃和重新创建,等等。使用lockCanvas(Rect)的正确方法是传递脏矩形,然后检查它的新值并尊重它们。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5190789

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档