【问题标题】:Android Java. Strange behaviour with invalidate(Rect)安卓Java。 invalidate(Rect) 的奇怪行为
【发布时间】:2012-06-02 16:32:43
【问题描述】:

我得到了 invalidate(Rect) 的奇怪效果。

我在画布上使用 onDraw 方法。在最简单的情况下,我有一个背景和一个精灵。

在第一次通过 onDraw 时,我绘制背景并使用 invalidate(Rect)(一个覆盖整个运动场的矩形),在同一次通过中,我绘制了一个 sprite 并且(因为所有通道的代码都是相同的) 我对精灵所在的 Rect 做了一个 invalidate(Rect)。

第一次传球后,比赛场地是正确的。整个背景就位,精灵叠加。

在下一次和后续通过 onDraw 时,我绘制精灵所在背景的“脏”位,并在其上执行 invalidate(Rect) 以及精灵及其新的“脏”矩形,然后sprite 的另一个 invalidate(Rect)。

在这遍和所有后续遍之后,我只看到了精灵。就好像画布被清除了一样。

不允许一次做多个invalidate(Rect)吗?这是问题吗?我遇到了一些异步问题吗?

这里是 onDraw() 代码。如果我在 onDraw() 结束时执行全屏 invalidate() 代替,它可以正常工作,但速度很慢。 它还缩放所有图像。所有图像和屏幕位置均基于 640x480 的运动场, 并缩放到当前 android 设备的大小。在我尝试优化屏幕之前,一切正常 使用 invalidate(Rect) 绘图。

    @Override
    protected void onDraw(Canvas canvas) 
{
    int ii;

    // Draw the background scene
    // Restore all the bits of the backcloth that got 
    // trampled on by any sprites or the cursor 
    // On the first pass the whole playfield dirty rectangle is in place in mask
    paint.reset();
    mask.collapse();
    ArrayList <Rect> usedSet = mask.getUsedRectSet();
    for (ii = 0; ii < usedSet.size(); ii++)
    {
        Rect src = rescaleRect(usedSet.get(ii));
        Rect dst = displaceRect(src);
        canvas.drawBitmap(backcloth, src, dst, paint);
        invalidate(dst);
    }
    // Leave used Rect set clear for next set of sprites
    mask.ClearUsedRectSet();

    //
    // draw Sprites
    //   screen scaling and
    //   displacement is done here.
    //
    ArrayList <Sprite> slist = jadedata.getCurrentSprites();
    //Sort sprites into ascending order of priority
    //      This is a sinking sort. On first pass, the highest
    //      priority sprite arrives at the bottom. On second,
    //      the next highest arrives at second bottom, etc.
    //      Sprites of the same priority remain in their
    //      original sequence with respect to each other.
    for (ii = 0; ii< slist.size()-1; ii++)
    {
        int sw=0;
        for (int jj = 0; jj < (slist.size()-ii-1); jj++)
        {
            Sprite spare1 = slist.get(jj);
            Sprite spare2 = slist.get(jj+1);
            if (spare1.getPriority() > spare2.getPriority())
            {
                slist.set(jj+1, spare1);
                slist.set(jj, spare2);
                sw=1;
            }
        }
        if (sw==0) break;  // exit if slist is already in sequence
    }

    for (ii = 0; ii< slist.size(); ii++) 
    {
        Point p = new Point();
        Point e = new Point();
        Rect o = new Rect();
        Sprite sprite = (Sprite)slist.get(ii);
        // Zero-priority sprites do not get drawn
        if (sprite.getPriority() == 0) continue;
        p = sprite.getPosition();
        e = sprite.getExtent();
        // make a rect for usedRects
        Rect r = new Rect(0, 0, e.x-1, e.y-1);
        Rect src = new Rect(r);
        // move it to the model playfield position
        r.offset(p.x-e.x/2, p.y-e.y/2);
        // make an overlap rect so we can apply it to the source image
        o = overlapRect(r, 0, 0, iWidth, iHeight);
        // trim r for the used rectangles
        r = trimRect(r, 0, 0, iWidth, iHeight);
        // add it to used Rectangles
        mask.addNewRect(r);
        // draw the sprite image
        Rect d = rescaleRect(usedSet.get(ii));
        Rect dst = displaceRect(d);
        Bitmap spriteim = sprite.getCurrentImage();
        src.top += o.top;
        src.left += o.left;
        src.bottom -= o.bottom;
        src.right -= o.right;
        canvas.drawBitmap(spriteim, src, dst, paint);
        invalidate(dst);
    }

【问题讨论】:

    标签: java android


    【解决方案1】:

    不知道你在做什么,因为你没有提供代码,所以我只是给出一个一般性的提示:

    对于第一遍之后的遍,只在脏矩形上使用invalidate,并在onDraw方法中,绘制所有需要绘制的东西,但只在脏矩形内。

    【讨论】:

    • 感谢您的回复。我想我正在按照你的建议做。 ' 矩形 src = rescaleRect(usedSet.get(ii));矩形 dst = displaceRect(src); canvas.drawBitmap(backcloth, src, dst, paint);无效(dst); ' 用于背景和 'canvas.drawBitmap(spriteim, src, dst, paint);无效(dst);'对于精灵
    • 现在可以了吗?如果是,请勾选答案。如果不是,请提供您的代码的 sn-p,以便我们查看问题所在。
    • 我是这个网站的初学者,所以我必须研究 mini-markdown 的工作原理。整理好后我会添加代码!
    • 对于代码,要么放4个空格(“”),要么标记代码行并按code-sample按钮,或者直接按CTRL+K。
    • 我认为你粘贴了太多代码。你应该坚持这个问题并尝试用最少的代码制作一个小项目来演示它,因为这里的很多代码要么无关紧要,要么无法理解(因为有许多函数和变量没有记录或显示) .
    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 2013-12-11
    • 2023-04-06
    • 2018-08-15
    • 2017-09-27
    相关资源
    最近更新 更多