Вопрос

Я новичок в Android.

Я рисую растровые изображения, линии и фигуры на холсте внутри метода OnDraw (холст холста) моего представления.Мне нужна помощь, как реализовать плавную прокрутку в ответ на перетаскивание пользователем.Я искал, но не нашел никаких руководств, которые могли бы помочь мне в этом.

В ссылке на Canvas говорится, что если Canvas создан из растрового изображения (скажем, называемого bmpBuffer), то все, что нарисовано на Canvas, также рисуется в bmpBuffer.Можно ли использовать bmpBuffer для реализации прокрутки...возможно, скопировать его обратно на холст, сдвинутый на несколько пикселей за раз?Но если я использую Canvas.drawBitmap для отрисовки bmpBuffer обратно в Canvas, сдвинутого на несколько пикселей, не будет ли bmpBuffer поврежден?Поэтому, возможно, мне следует скопировать bmpBuffer в bmpBuffer2, а затем нарисовать bmpBuffer2 обратно на холст.

Более простой подход — нарисовать линии, формы и т. д.прямо в растровое изображение буфера, затем нарисуйте этот буфер (со сдвигом) на холсте, но, насколько я вижу, различные методы:drawLine(), drawShape() и т. д. недоступны для рисования в растровом изображении...только на холст.

Могу ли я получить 2 холста?Один из них будет создан из растрового изображения буфера и использован просто для построения линий, фигур и т. д.а затем растровое изображение буфера будет нарисовано на другом холсте для отображения в представлении?

Буду рад любому совету!

Ответы на подобные вопросы здесь (и на других сайтах) относятся к «блитингу».Я понимаю эту концепцию, но не могу найти ничего о «blit» или «bitblt» в документации Android.Являются ли Canvas.drawBitmap и Bitmap.Copy эквивалентами Android?

Это было полезно?

Решение

У меня тоже была эта пробема,

Рисунок я делал так:

Canvas BigCanvas = new Canvas();
Bitmap BigBitmap = new Bitmap(width,height);

int ScrollPosX , ScrollPosY  // (calculate these with the onScrollEvent handler)

void onCreate()
{
   BigCanvas.SetBitmap(BigBitmap);
}

onDraw(Canvas TargetCanvas)
{
   // do drawing stuff
   // ie.  BigCanvas.Draw.... line/bitmap/anything

   //draw to the screen with the scrolloffset

   //drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
   TargetCanvas.DrawBitmap(BigBitmap(new Rect(ScrollPosX,ScrollPosY,ScrollPosX + BigBitmap.getWidth(),ScrollPosY + BigBitmap.getHeight(),new Rect(0,0,ScreenWidth,ScreenHeight),null);
}

для плавной прокрутки вам нужно будет создать какой-то метод, который занимает несколько точек после прокрутки (т.е. первую точку прокрутки и 10-ю), вычесть их и прокрутить на это число в каждом цикле, что постепенно замедляет его ( ScrollAmount - повороты - Трение).

Надеюсь, это даст больше понимания.

Другие советы

Кажется, я нашел ответ.Я поместил большую часть кода рисования (который ранее находился в onDraw()) в новый метод doDrawing().Этот метод начинается с создания нового растрового изображения, большего размера, чем экран (достаточно большого, чтобы вместить весь рисунок).Затем он создает второй холст, на котором можно выполнить подробный рисунок:

    BufferBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
    Canvas BufferCanvas = new Canvas(BufferBitmap);

Остальная часть метода doDrawing() занята детальным рисованием в BufferCanvas.

Весь метод onDraw() теперь выглядит следующим образом:

    @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(BufferBitmap, (float) -posX, (float) -posY, null);
}

Переменные позиции posX и posY инициализируются значением 0 в методе onCreate() приложения.Приложение реализует OnGestureListener и использует аргументы distanceX и distanceY, возвращаемые в уведомлении OnScroll, для увеличения posX и posY.

Кажется, это все, что нужно для реализации плавной прокрутки.Или я что-то упускаю!?

Продолжение ответа Виктору...

На самом деле ситуация сложнее.Поскольку процесс doDrawing довольно медленный (на моем старом медленном телефоне HTC Hero он занимает 2-3 секунды), я счел желательным вывести всплывающее сообщение, чтобы сообщить пользователю, что это происходит, и указать причину.Очевидный способ сделать это — создать новый метод, содержащий всего две строки:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");`
    doDrawing();
}

и вызывать этот метод из других мест моей программы вместо doDrawing().

Однако я обнаружил, что Тостер либо вообще не появлялся, либо вспыхивал так кратковременно, что его невозможно было прочитать.Мой обходной путь заключался в использовании обработчика проверки времени, чтобы заставить программу спать на 200 миллисекунд между отображением Toast и вызовом doDrawing().Хотя это немного задерживает начало перерисовки, я считаю, что это цена, которую стоит заплатить с точки зрения удобства использования программы, поскольку пользователь знает, что происходит.reDrawBuffer() теперь гласит:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");
    mTimeCheckHandler.sleep(200);    
}`

и код обработчика (который вложен в мой класс View):

private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();

class timeCheckHandler extends Handler {
@Override
    public void handleMessage(Message msg) {
        doDrawing();
    }
    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}`

Нет необходимости перезапускать действие!(Согласно ответу prepbgg от 27 10 января на его «ответ» от 17 10 января). Вместо того, чтобы перерабатывать растровое изображение и нести накладные расходы на перезагрузку активности, вы можете избежать загрузки приложения, поместив атрибут «android: configChanges», показанный ниже: в элементе «активность» файла AndroidManifest.xml для приложения.Это сообщает системе, что приложение обработает изменения ориентации и что ему не нужно перезапускать приложение.

<activity android:name=".ANote"
    android:label="@string/app_name"
    android:configChanges="orientation|screenLayout">
    <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Этот метод можно использовать для получения уведомления при изменении ориентации:

public void onConfigurationChanged(Configuration  newConfig) {
    super.onConfigurationChanged(newConfig);
    prt("onConfigurationChanged: "+newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
      prt("  PORTRAIT");
    } else {
      prt("  LANDSCAPE");
    }
} // end of onConfigurationChanged

препбгг:Я не думаю, что код будет работать, потому что Canvas.drawBitmap не рисует растровое изображение, а рисует его на холсте.

Поправьте меня, если я ошибаюсь!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top