Android - как анимировать движущуюся фигуру с помощью пользовательского SurfaceView? - PullRequest
3 голосов
/ 17 января 2012

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

Основная деятельность:

package ybz.test;

import ybz.fireworks.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;

public class TestActivity extends Activity implements OnClickListener {

    private static final String TAG = "CL_FireworksActivity";
    MySurfaceView mySurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            findViewById(R.id.btnStart).setOnClickListener(this);
            findViewById(R.id.btnStop).setOnClickListener(this);

            mySurfaceView = (MySurfaceView) (findViewById(R.id.surfaceView1));
        } catch (Exception e) {
            Log.d(TAG, "Failed to create; " + e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btnStart:
            try {
                mySurfaceView.startThread();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        case R.id.btnStop:
            mySurfaceView.stopThread();
            break;
        }
    }
}

Пользовательский SurfaceView:

package ybz.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements
        SurfaceHolder.Callback {
    private DrawThread drawThread;
    private Paint paint = new Paint();
    private Point location;

    public MySurfaceView(Context context) {
        super(context);
        initialize();
    }

    public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public MySurfaceView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

    private void initialize() {
        getHolder().addCallback(this);
        setFocusable(true);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(1);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.SQUARE);
        paint.setStyle(Style.FILL);
        location = new Point(0, 200);
    }

    public void startThread() {
        drawThread = new DrawThread(getHolder(), this);
        drawThread.setRunning(true);
        drawThread.start();
    }

    public void stopThread() {
        drawThread.setRunning(false);
        drawThread.stop();
    }

    public void update() {
        location.x = location.x + 10;
        if(location.x > getWidth()) {
            location.x = 0;
        }
    }

    public void onDraw(Canvas canvas) {
        canvas.drawCircle(location.x, location.y, 15, paint);
    }

    class DrawThread extends Thread {
        private SurfaceHolder surfaceHolder;
        MySurfaceView mySurfaceView;
        private boolean run = false;

        public DrawThread(SurfaceHolder surfaceHolder,
                MySurfaceView mySurfaceView) {
            this.surfaceHolder = surfaceHolder;
            this.mySurfaceView = mySurfaceView;
            run = false;
        }

        public void setRunning(boolean run) {
            this.run = run;
        }

        @Override
        public void run() {
            Canvas canvas = null;
            while (run) {
                try {
                    canvas = surfaceHolder.lockCanvas(null);
                    synchronized (surfaceHolder) {
                        mySurfaceView.onDraw(canvas);
                        mySurfaceView.update();
                    }
                } finally {
                    if (canvas != null) {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }

}

Компоновка:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ybz.test.MySurfaceView
        android:id="@+id/surfaceView1"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center" >

        <Button
            android:id="@+id/btnStart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="@string/lbl_start" />

        <Button
            android:id="@+id/btnStop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="@string/lbl_stop" />

    </LinearLayout>

</LinearLayout>

Ответы [ 2 ]

3 голосов
/ 17 января 2012

Видимо, вид Surface не очищается после каждого рисования, поэтому мне нужно сделать это явно.Цитата из Руководства Android-разработчика :

Примечание. На каждом проходе, когда вы извлекаете Canvas из SurfaceHolder, предыдущее состояние Canvas будет сохраняться.Чтобы правильно анимировать вашу графику, вы должны перекрасить всю поверхность.Например, вы можете очистить предыдущее состояние холста, заполнив цвет с помощью drawColor () или установив фоновое изображение с помощью drawBitmap ().В противном случае вы увидите следы ранее выполненных чертежей.

Обновлен метод onDraw ():

public void onDraw(Canvas canvas) {
    canvas.drawColor(Color.BLACK);
    canvas.drawCircle(location.x, location.y, 15, paint);
}
0 голосов
/ 16 мая 2017

Вам необходимо перекрасить холст в цвет фона в начале метода onDraw () производного класса SurfaceView.

Вот мои три видеоурока, которые помогут вам полностью понять Android Graphics & Animation.В нем объясняется, как разрабатывать анимацию, используя как обычный вид, так и вид поверхности.

https://youtu.be/kRqsoApOr9U

https://youtu.be/Ji84HJ85FIQ

https://youtu.be/U8igPoyrUf8

...