在Android中,点击按钮创建SurfaceView上的圆形

3
因此,我正在开发一款应用程序,它可以在SurfaceView中创建一个圆。我希望每当按下“创建”按钮时,在SurfaceView内生成一个新的圆。每个新的圆都将具有随机速度、颜色和起始位置,以及唯一的序列号。创建一个具有随机颜色和起始位置的圆很容易,但是我在尝试在创建按钮监听器中创建圆时遇到了一些问题,导致应用程序崩溃。如果您能提供帮助,我们将不胜感激。谢谢。
package com.dwolford.project8;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import java.util.ArrayList;
import java.util.Random;

public class Main extends Activity implements Runnable {
private Button create;
private Button destroy;
private Button quit;
private SurfaceView surface;
private SurfaceHolder holder;
private boolean locker=true;
private Thread thread;
private int canvasWidth = 0;
private int canvasHeight = 0;
private int xCoordinate = 0;
private int yCoordinate = 0;
public static Canvas canvas;
public boolean createBall = false;
ArrayList<Balls> ballList = new ArrayList<Balls>();


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    surface = (SurfaceView) findViewById(R.id.surfaceView);
    holder = surface.getHolder();

    create = (Button)findViewById(R.id.create);
    create.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Balls ball = new Balls();
            ballList.add(ball);
            //create ball with random color, speed, beginning, direction, and incremented sequence number
        }
    });


    destroy = (Button)findViewById(R.id.destroy);
    destroy.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            ballList.remove(0);
        }
    });

    quit = (Button)findViewById(R.id.quit);
    quit.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });


    thread = new Thread(this);
    thread.start();
}

@Override
public void run() {
    while(locker){
        //checks if the lockCanvas() method will be success,and if not, will check this statement again
        if(!holder.getSurface().isValid()){
            continue;
        }
        /** Start editing pixels in this surface.*/
        canvas = holder.lockCanvas();

        //ALL PAINT-JOB MAKE IN draw(canvas); method.
        draw(canvas);

        // End of painting to canvas. system will paint with this canvas,to the surface.
        holder.unlockCanvasAndPost(canvas);
    }
}


private void draw(Canvas nCanvas) {
    Paint paint = new Paint();

    canvas = nCanvas;

    canvasWidth = canvas.getWidth();//Get width of canvas for ball positioning
    canvasHeight = canvas.getHeight();//Get height of canvas for ball positioning

    canvas.drawColor(Color.WHITE);
    for(int i = 0; i < ballList.size(); i++)
    {
        paint.setColor((ballList.get(i).getColor()));
        canvas.drawCircle((ballList.get(i).getXPosition()),(ballList.get(i).getYPosition()), 30, paint);
    }
}


@Override
protected void onPause() {
    super.onPause();
    pause();
}

private void pause() {

    locker = false;
    while(true){
        try {
            thread.join();
        } catch (InterruptedException e) {e.printStackTrace();
        }
        break;
    }
    thread = null;
}

@Override
protected void onResume() {
    super.onResume();
    resume();
}

private void resume() {
    //RESTART THREAD AND OPEN LOCKER FOR run();
    locker = true;
}


public class Balls
{
    int currentSequenceNum = 0;
    int color;

    public Balls(){
        calculatePosition();
        setColor();
        currentSequenceNum = currentSequenceNum +1;//Increment sequence number
    }


    /**
     * Calculates the random starting x and y coordinates of the ball within the canvas
     */
    private void calculatePosition() {
        Random xRand = new Random();
        Random yRand = new Random();

        xCoordinate = xRand.nextInt((canvasWidth)+1);
        yCoordinate = yRand.nextInt((canvasHeight)+1);
    }

    /**
     * Sets the color of this circle
     */
    public void setColor()
    {
        Random rand = new Random();
        Paint paint = new Paint();

        color = Color.argb(255, rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
        paint.setColor(color);
        //canvas.drawCircle(xCoordinate, yCoordinate, 30, paint);
    }

    public int getColor()
    {
        return color;
    }


    /**
     * Gets the starting x position of this ball
     * @return
     */
    public int getXPosition()
    {
        return xCoordinate;
    }


    public int getYPosition()
    {
        return yCoordinate;
    }

}
}

这里是 XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"          android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".Main">

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Create"
    android:id="@+id/create"
    android:layout_alignParentTop="true"
    android:layout_toLeftOf="@+id/quit"
    android:layout_toStartOf="@+id/quit" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="DESTROY"
    android:id="@+id/destroy"
    android:layout_alignTop="@+id/create"
    android:layout_toRightOf="@+id/quit"
    android:layout_toEndOf="@+id/quit" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="QUIT"
    android:id="@+id/quit"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" />

<SurfaceView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/surfaceView"
    android:layout_below="@+id/create"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_above="@+id/quit"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />
</RelativeLayout>

请将崩溃信息复制粘贴到您的问题中,以便我们查看它是如何失败的。 - fadden
它不再崩溃了,但我稍微修改了一下代码。正如您所看到的,我创建了一个单独的内部类来处理圆形设计方面的问题。我的问题现在是,圆圈会出现,但只会在消失前的一瞬间出现。我需要它与我创建的其他圆圈一起保留,直到我选择销毁它。 - Deus Ex Machina
根据您当前的代码,您在循环中绘制所有圆形,然后调用 canvas.drawColor(),它会将整个画布清除为指定的颜色。因此,我不会期望您看到除了白色表面以外的任何东西。不确定为什么您只能短暂地看到一些东西。 - fadden
我在我的draw()方法中进行了一些轻微的编辑,现在它每次只绘制一个圆圈,但每次绘制新的圆圈时都会擦除之前的。有什么建议可以防止之前的圆圈被擦除,直到我想要擦除它? - Deus Ex Machina
每一帧,您需要清除表面并重新绘制所有内容。如果您正在绘制大量静态内容,则可能希望在屏幕外呈现并复制结果。(例如,请参见http://stackoverflow.com/questions/30832960/) - fadden
1个回答

4

类 DrawingView 继承自 SurfaceView {

private final SurfaceHolder surfaceHolder;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

public DrawingView(Context context) {
    super(context);
    surfaceHolder = getHolder();
    paint.setColor(Color.RED);
    paint.setStyle(Style.FILL);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN) {
        if (surfaceHolder.getSurface().isValid()) {
            Canvas canvas = surfaceHolder.lockCanvas();
            canvas.drawColor(Color.BLACK);
            canvas.drawCircle(event.getX(), event.getY(), 50, paint);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
    return false;
}

在按钮单击事件上调用它

setContentView(new DrawingView(this));


嗯...由于我的类目前扩展了Activity,我该如何在不破坏代码的情况下实现这个功能呢? - Deus Ex Machina
你需要创建一个扩展SurfaceView的单独类。这段代码非常准确。 - Zack Matthews
当我尝试在我的onCreate方法中调用它时,logcat会给我这个异常:java.io.IOException: 无法创建目录/dev/block/mmcblk0p29。 - Deus Ex Machina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接