timertask on Draw()Android的内部

发布于 2025-01-17 21:20:27 字数 3553 浏览 4 评论 0原文

我正在使用 Android Studio 开发一个 Android 应用程序。我有一个从另一个活动呈现的自定义视图。在自定义视图的 onDraw() 函数内部,我安排了一个新的计时器任务来重绘 UI 的一部分。最初,当我这样做时,我收到了 SIGSEGV 错误,但我可以通过添加以下内容来解决该问题: setLayerType(LAYER_TYPE_SOFTWARE, null)

但是,添加此内容后,我在计时器不会出现在画布上。

这里是一些用于更好理解的代码:

List<Person> people = new ArrayList<>(); 

public CustomView() {
   super(context);
   patch = BitmapFactory.decodeResource(this.getResources(), R.drawable.person);
   patch = Bitmap.createScaledBitmap(patch, 60, 60, true);
}

protected void onDraw() {
   if (drawPatch) {     // draw patch is a static boolean var that gets set to true 
                        // from the activity using this view

      timer.schedule(new TimerTask() {
         @Override
         public void run() {
            if (currentTime == timeBetweenSpawns) {
               people.add(new Person(x, y)); // x, y represents the location of the
                                             // person on the canvas
               currentTime = 0;
            } else {
               currentTime++;
            }
         }

         for (Person person : people) {
             person.movePerson(); // moves the person on the canvas
         }

         for (Person person : people) {
             canvas.drawBitmap(person.getBitmap(), person.getX(), person.getY(), null);
         }
      }, 0, 1000);
   } 
}

我想要做什么:

CustomView 代表游戏的地图。我想绘制游戏中地图上移动的人,并重复重新绘制人,使他们看起来移动流畅。问题是,当我这样做时,我不想重绘整个 CustomView,因为 CustomView 中唯一改变的是人的位置(对于上下文来说, onDraw() 中还绘制了很多其他内容) CustomView 中的函数,为了简洁起见我省略了它)。我上面尝试的计时器逻辑就是尝试执行此操作,但它不起作用。

是否有更好的方法来仅重绘人员列表中的 Person 对象,而不必使整个视图无效并重绘?

额外上下文

protected void onDraw(Canvas canvas) {
        for (Grass grassLocation : grassLocations) {
            canvas.drawBitmap(grassLocation.getBitMap(),
                    grassLocation.getX(),
                    grassLocation.getY(),
                    null);
        }

        for (Path pathLocation : pathLocations) {
            canvas.drawBitmap(pathLocation.getBitMap(),
                    pathLocation.getX(),
                    pathLocation.getY(),
                    null);
        }

        canvas.drawBitmap(monumentLocation.getBitMap(),
                monumentLocation.getX(),
                monumentLocation.getY(),
                null);

        for (Indicator indicatorLocation : indicatorLocations) {
            canvas.drawBitmap(indicatorLocation.getBitMap(),
                    indicatorLocation.getX(),
                    indicatorLocation.getY(),
                    null);
        }

        for (Turret turretLocation : turretLocations) {
            canvas.drawBitmap(turretLocation.getBitMap(),
                    turretLocation.getX(),
                    turretLocation.getY(),
                    null);
        }

        if (combatStarted) {
            if (currentTime == timeBetweenSpawns) {
                addPerson(); // add a new person
                currentTime = 0;
            } else {
                currentTime++;
            }

            // Move all enemies, check if person has reached monument
            for (Person person : people) {
             person.movePerson(); // moves the person on the canvas
            }

            for (Person person : people) {
             canvas.drawBitmap(person.getBitmap(), person.getX(), 
             person.getY(), null);
            }

            invalidate();
        }
}

I have an Android application that I am working on with Android Studio. I have a custom view that gets rendered from another activity. Inside of the custom view's onDraw() function, I schedule a new timer task to redraw a part of the UI. Initially, when I did this I was getting a SIGSEGV error, but I was able to fix that by adding this: setLayerType(LAYER_TYPE_SOFTWARE, null)

However, after adding this, the Bitmap I drew inside of the Timer doesn't appear on the Canvas.

Here is some of the code for better understanding:

List<Person> people = new ArrayList<>(); 

public CustomView() {
   super(context);
   patch = BitmapFactory.decodeResource(this.getResources(), R.drawable.person);
   patch = Bitmap.createScaledBitmap(patch, 60, 60, true);
}

protected void onDraw() {
   if (drawPatch) {     // draw patch is a static boolean var that gets set to true 
                        // from the activity using this view

      timer.schedule(new TimerTask() {
         @Override
         public void run() {
            if (currentTime == timeBetweenSpawns) {
               people.add(new Person(x, y)); // x, y represents the location of the
                                             // person on the canvas
               currentTime = 0;
            } else {
               currentTime++;
            }
         }

         for (Person person : people) {
             person.movePerson(); // moves the person on the canvas
         }

         for (Person person : people) {
             canvas.drawBitmap(person.getBitmap(), person.getX(), person.getY(), null);
         }
      }, 0, 1000);
   } 
}

What I am trying to do:

CustomView represents a map for a game. I want to draw people moving on the map in the game and repetitively redraw the people to make it seem like they are moving smoothly. The issue is, I don't want to redraw the entire CustomView when I do this since the only thing changing in the CustomView is the location of the people (also for context there is a lot of other stuff being drawn in the onDraw() function in CustomView, I just omitted it for brevity). The timer logic I attempted above was an attempt to do this, but it didn't work.

Is there a better way to only redraw the Person objects in the people list without having to invalidate and redraw the entire view?

Extra Context

protected void onDraw(Canvas canvas) {
        for (Grass grassLocation : grassLocations) {
            canvas.drawBitmap(grassLocation.getBitMap(),
                    grassLocation.getX(),
                    grassLocation.getY(),
                    null);
        }

        for (Path pathLocation : pathLocations) {
            canvas.drawBitmap(pathLocation.getBitMap(),
                    pathLocation.getX(),
                    pathLocation.getY(),
                    null);
        }

        canvas.drawBitmap(monumentLocation.getBitMap(),
                monumentLocation.getX(),
                monumentLocation.getY(),
                null);

        for (Indicator indicatorLocation : indicatorLocations) {
            canvas.drawBitmap(indicatorLocation.getBitMap(),
                    indicatorLocation.getX(),
                    indicatorLocation.getY(),
                    null);
        }

        for (Turret turretLocation : turretLocations) {
            canvas.drawBitmap(turretLocation.getBitMap(),
                    turretLocation.getX(),
                    turretLocation.getY(),
                    null);
        }

        if (combatStarted) {
            if (currentTime == timeBetweenSpawns) {
                addPerson(); // add a new person
                currentTime = 0;
            } else {
                currentTime++;
            }

            // Move all enemies, check if person has reached monument
            for (Person person : people) {
             person.movePerson(); // moves the person on the canvas
            }

            for (Person person : people) {
             canvas.drawBitmap(person.getBitmap(), person.getX(), 
             person.getY(), null);
            }

            invalidate();
        }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文