Android: проблема при многократном рисовании одного и того же растрового изображения на холсте - PullRequest
1 голос
/ 11 марта 2011

Итак, у меня есть растровое изображение, которое я загрузил из файла ресурсов (изображение в формате PNG):

Bitmap map = BitmapFactory.decodeResource(getResources(), R.drawable.wave);

Если я отрисовываю это растровое изображение только один раз, используя canvas.drawBitmap(...);, то проблем нет.Однако, если я рисую одно и то же растровое изображение несколько раз, изображение продолжает мигать взад и вперед, а не как раньше.

Я подозревал, что не могу использовать одно и то же растровое изображение более одного раза, поэтому я попытался загрузитьизображение в новое растровое изображение каждый раз, когда я хочу нарисовать ту же картинку, но это не помогает, поведение все еще сохраняется.

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

// The ocean.
private ArrayList<Wave> waves;

            // Draw the waves and update their positions.
    for (int i = 0; i < this.waves.size(); i++)
    {
        Wave wave = this.waves.get(i);

        // Go through each of the sub-waves of this current wave.
        for (int j = 0; j < wave.getSubWaveEdges().size(); j++)
        {
            // Get the sub wave.
            final float subWaveEdge = wave.getSubWaveEdges().get(j);

            canvas.drawBitmap( wave.getSubWave(j), subWaveEdge, 40, brush);

            wave.setSubWaveEdge(j, subWaveEdge + (float) 0.5);
        }

        // Update this current wave.
        wave.update();

        // If the wave has passed the left edge of the screen then add a new sub-wave.
        if (wave.getFarthestEdge() >= 0)
            wave.addSubWaveEdges(wave.getFarthestEdge() - this.getWidth());
    }

Если левый край растрового изображения находится внутри экрана, я создаю новое растровое изображение из того же файла изображения и рисую.Вот класс Wave:

    private class Wave
{
    private Bitmap wave;
    private float farthestEdge;
    private ArrayList<Float> subWaveEdges;
    private ArrayList<Bitmap> subWaves;

    public Wave(Bitmap wave)
    {   
        this.wave = wave;

        this.farthestEdge = 0;

        this.subWaveEdges = new ArrayList<Float>();

        this.subWaves = new ArrayList<Bitmap>();
    }

    public Bitmap getWave ()
    { return this.wave; }

    public void setWave (Bitmap wave)
    { this.wave = wave; }

    public float getFarthestEdge ()
    { return this.farthestEdge; }

    public void setFarthestEdge (final float furthestEdge)
    { this.farthestEdge = furthestEdge; }

    public ArrayList<Float> getSubWaveEdges ()
    { return subWaveEdges; }

    public void setSubWaveEdge (final int index, final float value)
    {
        this.subWaveEdges.remove(index);

        this.subWaveEdges.add(value);
    }

    public void addSubWaveEdges (final float edge)
    {
        this.subWaveEdges.add(edge);

        Bitmap newSubWave = BitmapFactory.decodeResource(getResources(), R.drawable.wave);

        newSubWave = Bitmap.createScaledBitmap(newSubWave, MasterView.this.getWidth(), newSubWave.getHeight(), true);

        this.subWaves.add(newSubWave);
    }

    public Bitmap getSubWave(final int index)
    { return this.subWaves.get(index); }

    public void update ()
    {

        // Check to see if there is any sub-wave going outside of the screen.
        // If there is then remove that wave.
        for (int index = 0; index < this.subWaveEdges.size(); index++)
            if (this.subWaveEdges.get(index) > MasterView.this.getWidth())
            {
                this.subWaveEdges.remove(index);

                this.subWaves.remove(index);
            }

        // Set the farthest edge to the other side of the screen.
        this.farthestEdge = MasterView.this.getWidth();

        // Get the farthest edge of the wave.
        for (int index = 0; index < this.subWaveEdges.size(); index++)
            if (this.subWaveEdges.get(index) < this.farthestEdge)
                this.farthestEdge = this.subWaveEdges.get(index);
    }
}

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

Кто-нибудь сталкивался с этой проблемой и знает, как ее исправить?

Спасибо,

Ответы [ 3 ]

1 голос
/ 13 марта 2011

Виктор Ланнер, Спасибо за помощь, но я не думаю, что это проблема.Я понимаю, что мои коды трудно читать, так как это всего лишь небольшая часть большой программы.

Однако я обнаружил проблему: это не упоминается в моем исходном вопросе, но для того, чтобы смоделировать дваволны, движущиеся друг за другом, я должен нарисовать следующую волну, как только первая волна выходит на экран.Однако каждая волна длиннее ширины экрана.Поэтому я должен нарисовать следующую волну «снаружи» экрана, если вы понимаете, о чем я.Это означает, что следующая волна рисуется из отрицательной x-координаты снаружи экрана:

    // If the wave has passed the left edge of the screen then add a new sub-wave.
    if (wave.getFarthestEdge() >= 0)
        wave.addSubWaveEdges(wave.getFarthestEdge() - this.getWidth());

И я обнаружил, что это не так.Это то, что вызывает мигание взад и вперед.

Чтобы исправить это, вместо рисования следующей волны снаружи экрана, я использую этот метод:

     canvas.drawBitmap (Bitmap bitmap, Rect source, Rect destination, Paint paint)

Этот метод позволяетВы указываете прямоугольную область на растровом изображении, которое будет отображаться на экране, и прямоугольную область на экране, где будет рисоваться эта часть растрового изображения.Я использую этот метод, чтобы нарисовать следующую волну.Когда следующая волна переместится на экран, я соответствующим образом изменю «источник» и «место назначения», чтобы нарисовать части растрового изображения.

1 голос
/ 20 мая 2011

Я просто хотел сказать, что у меня была проблема, когда изображения на моем холсте мигали взад-вперед или мигали между черным и моим первым кадром, пока я не сделал движение, почти как если бы холст быстро переключался между текущее и последнее изображение.

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

Я справился с этим, сделав что-то вроде этого:

if (needToRedraw == true) {
      canvas = mSurfaceHolder.lockCanvas(null);
      ... logic to eventually draw on that canvas ...
   }
0 голосов
/ 11 марта 2011

До canvas.drawBitmap(...) звонка; попробуйте использовать canvas.drawColor(Color.BLACK), чтобы очистить Canvas от предыдущих рисунков.

Пример кода:

// Stuff.
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(wave.getSubWave(j), subWaveEdge, 40, brush);
// Stuff.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...