Android: как заставить пользовательский вид перерисовать частично? - PullRequest
14 голосов
/ 01 июня 2010

У меня есть пользовательский вид, который заполняет весь мой экран. (Фортепианная клавиатура) Когда пользователь касается клавиши, он вызывает invalidate(), и вся клавиатура перерисовывается, чтобы показать новое состояние с нажатой клавишей.

В настоящее время вид очень прост, но я планирую добавить немного более приятную графику. Поскольку вся клавиатура отображается динамически, это сделает перерисовку всей клавиатуры более дорогой.

Итак, я подумал, давайте рассмотрим частичную перерисовку. Теперь я звоню invalidate(Rect dirty) с правильным грязным регионом. Я установил свой метод onDraw(Canvas canvas), чтобы рисовать ключи только в грязной области, если я действительно хочу частичную перерисовку. Это приводит к тому, что эти клавиши рисуются, но остальная часть клавиатуры полностью черная / не рисуется вообще.

Я ошибаюсь, ожидая, что вызов invalidate(Rect dirty) будет "кэшировать" текущий canvas и только "разрешит" рисование в грязной области?

Есть ли способ, которым я могу достичь того, чего я хочу? (Способ «кэшировать» холст и перерисовывать только грязную область? »

Ответы [ 2 ]

19 голосов
/ 01 июня 2010

Текущий хороший обходной путь - вручную кэшировать весь холст в растровое изображение:

 private void onDraw(Canvas canvas)
 {
     if (!initialDrawingIsPerformed)
     {
          this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
            Config.ARGB_8888); //Change to lower bitmap config if possible.
          Canvas cacheCanvas = new Canvas(this.cachedBitmap);
          doInitialDrawing(cacheCanvas);
          canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
          initialDrawingIsPerformed = true;
     }
     else
     {
          canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint());
          doPartialRedraws(canvas);
     }
 }

Конечно, вам нужно хранить информацию о том, что нужно перерисовать, и желательно не использовать новый Paint каждый раз, но это детали.

Также обратите внимание: растровые изображения довольно сильно влияют на использование памяти вашим приложением. У меня были сбои, когда я кэшировал View, который использовался с помощью скроллера и который был примерно в 5 раз больше высоты устройства, поскольку он использовал> 10 МБ памяти!

5 голосов
/ 06 мая 2011

В дополнение к ответу Петерда вы можете сохранить свои операции в изображении вместо растрового изображения.

  • Растровое изображение будет сохранять все пиксели, как он сказал, что это может занять много память.
  • Изображение сохранит вызовы, такие как drawRect, drawLine и т. д.

Это зависит от того, что действительно тяжело в вашем приложении: много операций рисования, несколько операций рисования, но управляемых тяжелыми вычислениями, много пустого / неиспользуемого пространства (предпочтительнее изображение) и т. Д. *

...