Android: circle drawing and touch event error
I am having an issue right now with drawing circles and handling touch events. Basically I am listening for touch events, which selects a circle and lets a user drag around to control the location/radius of the circle. I also have a menu option to "add a new circle" which changes the drag event to add a new circle to view. This keeps throwing a force close though when I test it. I do not know how to see what is causing the force close (sorry I am a newb who happens to be good at hacking things apart and making them work). Could someone please take a look at this, or point me in the direction of debugging this correctly?
I think it might have something to do with the new circle b开发者_运维知识库eing created inside the view that is currently in focus? If that makes any sense.
Here is my code... initial values are coming from a previous activity (this is not where the problem lies though, the problem is in my TouchEventListener).
/*this is the working example of playing audio
* and adjusting the volume, although playback
* is a bit choppy and the different sounds loose
* sync after a bit
*/
package com.adam.PlaySound;
import java.util.ArrayList;
import java.util.Collections;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AbsoluteLayout;
import android.widget.TextView;
@SuppressWarnings("deprecation")
public class EditInterface extends Activity {
/** Called when the activity is first created. */
/*do our web stuff*/
ConnectToUrl makeConnection = new ConnectToUrl();
TextView text;
AbsoluteLayout circlesView;
int numPlayers;
ArrayList<Float> regionX = new ArrayList<Float>();
ArrayList<Float> regionY = new ArrayList<Float>();
ArrayList<Float> regionR = new ArrayList<Float>();
ArrayList<String> soundFiles = new ArrayList<String>();
ArrayList<LoopRegion> region = new ArrayList<LoopRegion>();
ArrayList<LoopRegion> border = new ArrayList<LoopRegion>();
MediaPlayer mediaPlayer = new MediaPlayer();
String key;
int index;
int actionState = 0;
//We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit);
text = (TextView) findViewById(R.id.text);
text.setText("");
circlesView = (AbsoluteLayout) findViewById(R.id.absoluteLayout1);
circlesView.setOnTouchListener(Motion);
Bundle extras = getIntent().getExtras();
if(extras != null) {
numPlayers = extras.getInt("numPlayers");
}
for (int i = 0; i < numPlayers; i++){
//get regionX values
key = "regionX" + i;
regionX.add(extras.getFloat(key));
//get regionY values
key = "regionY" + i;
regionY.add(extras.getFloat(key));
//get regionR values
key = "regionR" + i;
regionR.add(extras.getFloat(key));
//get soundFiles values
key = "soundFiles" + i;
soundFiles.add(extras.getString(key));
//add our circles
region.add(new LoopRegion(this,regionX.get(i),regionY.get(i),regionR.get(i), true, Color.WHITE));
border.add(new LoopRegion(this,regionX.get(i),regionY.get(i),regionR.get(i), false, Color.RED));
circlesView.addView(region.get(i));
circlesView.addView(border.get(i));
}
}
OnTouchListener Motion
= new AbsoluteLayout.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent ev) {
float x1 = ev.getX(0);
float y1 = ev.getY(0);
float x2 = ev.getX(1);
float y2 = ev.getY(1);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (actionState == 0){
/***select our circle***/
mode = DRAG;
//for testing//text.setText("action down");
//calculate distance to detect which circle we will look at
ArrayList<Float> distance = new ArrayList<Float>();
for (int i = 0; i < numPlayers; i++){
if (distance(regionX.get(i), regionY.get(i), x1, y1) > (regionR.get(i) + 5)){
distance.add((float) 10000);
}
else {
distance.add(distance(regionX.get(i), regionY.get(i), x1, y1));
}
}
Object object = Collections.min(distance);
index = distance.indexOf(object);
//for testing//text.setText("index: " + index);
//set up sound
String path = "http://soundclusters.adamlaskowitz.com/uploads/" + soundFiles.get(index);
mediaPlayer = MediaPlayer.create(EditInterface.this, Uri.parse(path));
mediaPlayer.start();
region.get(index).setColor(true, Color.RED);
region.get(index).invalidate();
border.get(index).setColor(false, Color.WHITE);
border.get(index).invalidate();
}
else if (actionState == 1){
region.add(new LoopRegion(EditInterface.this, x1, y1, 50 , true, Color.WHITE));
border.add(new LoopRegion(EditInterface.this, x1, y1, 50, false, Color.RED));
circlesView.addView(region.get(numPlayers));
circlesView.addView(border.get(numPlayers));
circlesView.clearFocus();
/////region.get(index).invalidate();
/////border.get(index).invalidate();
index = numPlayers; //since they are zero-indexed the previous
//amount of Players will equal the index of the new larger array
numPlayers = region.size();
text.setText("length:" + numPlayers + ", state:" + actionState);
//text.setText("index:" + index + ", numPlayers:" + numPlayers + ", length:" + region.size());
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
/***initiate zoom***/
mode = ZOOM;
//for testing//text.setText("action 2 down");
break;
case MotionEvent.ACTION_UP:
/***finish our current edit and deselect circle***/
mode = NONE;
//for testing//text.setText("action up");
//stop and release current sound for region
mediaPlayer.stop();
mediaPlayer.release();
region.get(index).setColor(true, Color.WHITE);
region.get(index).invalidate();
border.get(index).setColor(false, Color.RED);
border.get(index).invalidate();
actionState = 0;
text.setText("index:" + index + ", state:" + actionState);
break;
case MotionEvent.ACTION_POINTER_UP:
/***set mode Drag***/
mode = DRAG;
//for testing//text.setText("action 2 up");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG){
/***Drag the circle based on radius***/
//for testing//text.setText("action move");
region.get(index).setCoordinate(x1, y1, regionR.get(index));
region.get(index).invalidate();
border.get(index).setCoordinate(x1, y1, regionR.get(index));
region.get(index).invalidate();
regionX.set(index, x1);
regionY.set(index, y1);
}
else if (mode == ZOOM) {
/***Zoom and move the circle***/
//for testing//text.setText("action 2 move");
regionR.set(index, distance(x1,y1,x2,y2));
float centerX = midpoint(x1,x2);
float centerY = midpoint(y1,y2);
float radius = regionR.get(index)/2;
region.get(index).setCoordinate(centerX, centerY, radius);
region.get(index).invalidate();
border.get(index).setCoordinate(centerX, centerY, radius);
region.get(index).invalidate();
regionX.set(index, centerX);
regionY.set(index, centerY);
regionR.set(index, radius);
}
break;
}
return true;
}
};
//make our menu---------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.edit_menu, menu);
return true;
}
public float regionXNew[] = new float[numPlayers];
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.play:
//return to the GraphicInterface----------------------------------------
Intent mIntent = new Intent(EditInterface.this, GraphicInterface.class);
String num = Integer.toString(numPlayers);
String xVal = "";
String yVal = "";
String rVal = "";
String files = "";
for (int i = 0; i < numPlayers; i++){
//format values to send to web*/
if (i == (numPlayers - 1)){
xVal = xVal.concat(regionX.get(i) + "");
yVal = yVal.concat(regionY.get(i) + "");
rVal = rVal.concat(regionR.get(i) + "");
files = files.concat(soundFiles.get(i) + "");
}
else {
xVal = xVal.concat(regionX.get(i) + "=");
yVal = yVal.concat(regionY.get(i) + "=");
rVal = rVal.concat(regionR.get(i) + "=");
files = files.concat(soundFiles.get(i) + "=");
}
}
makeConnection.sendToWeb(num, xVal, yVal, rVal, files);
if (getParent() == null) {
setResult(RESULT_OK, mIntent);
} else {
getParent().setResult(RESULT_OK, mIntent);
}
finish();
//return to the GraphicInterface---------------------------------------
return true;
case R.id.help:
return true;
case R.id.add:
actionState = 1;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
//make our menu---------------------------------------------------------
public float distance(float x1, float y1, float x2, float y2){
float dist;
float a = x1 - x2;
float b = y1 - y2;
dist = (float) (Math.pow(a, 2) + Math.pow(b, 2));
dist = (float) Math.sqrt(dist);
return dist;
}
public float midpoint(float axis1, float axis2){
float midpoint;
midpoint = (axis1 + axis2)/2;
return midpoint;
}
}
Thank you for those who respond.
The first thing you need to learn when developing android apps is to read the logcat
: http://developer.android.com/guide/developing/tools/adb.html#logcat
Please, connect your device to the PC and run adb logcat *:W > log.txt
Read the output and look for any exception thrown. Then, paste here the code so we have a better idea of what's going on.
PS: If you're testing on the emulator from Eclipse, the android debug perspective will open one window with the logcat for you. Use it to copy the relevant text. It will be the full logcat, so it will have a lot more non-relavant output than the command line above.
精彩评论