问题
So essentially I am working on an app that creates a circle withing a SurfaceView. I want for a new circle to be generated inside the SurfaceView whenever pressing the "create" button. Each new circle would have a random speed, color, starting position along with a unique sequence number. It's easy enough to create a circle with a random color and starting position, but I was having some trouble getting the circle to draw only when I click on the create button. Whenever I try to create a circle within the create button listener it crashes. Any help with this would be appreciated. Thank you.
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;
}
}
}
Here is the 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>
回答1:
class DrawingView extends 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;
}
}
call it on button click event setContentView(new DrawingView(this));
来源:https://stackoverflow.com/questions/31443911/creating-circle-in-surfaceview-on-button-click-android