我正在开发一个简单的应用程序,在触摸屏幕上产生气泡。气泡在屏幕上移动并在到达屏幕边界或用户触摸时弹出。我已成功将气泡编码到达屏幕边界时弹出,但无法找出检测用户是否触摸它的方法。
我想检测用户是否触摸了屏幕上的任何气泡。
注意: - 使用自定义视图创建气泡。此外,我只包括一些重要的功能,但如果你愿意,可以包括整个代码。这是代码
public class BubbleActivity extends Activity {
// These variables are for testing purposes, do not modify
private final static int RANDOM = 0;
private final static int SINGLE = 1;
private final static int STILL = 2;
private static int speedMode = RANDOM;
private static final int MENU_STILL = Menu.FIRST;
private static final int MENU_SINGLE_SPEED = Menu.FIRST + 1;
private static final int MENU_RANDOM_SPEED = Menu.FIRST + 2;
private static final String TAG = "Lab-Graphics";
// Main view
private RelativeLayout mFrame;
// Bubble image
private Bitmap mBitmap;
// Display dimensions
private int mDisplayWidth, mDisplayHeight;
// Sound variables
// AudioManager
private AudioManager mAudioManager;
// SoundPool
private SoundPool mSoundPool;
// ID for the bubble popping sound
private int mSoundID;
// Audio volume
private float mStreamVolume;
// Gesture Detector
private GestureDetector mGestureDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set up user interface
mFrame = (RelativeLayout) findViewById(R.id.frame);
// Load basic bubble Bitmap
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b64);
}
@Override
protected void onResume() {
super.onResume();
// Manage bubble popping sound
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// Get the size of the display so this view knows where borders are
mDisplayWidth = mFrame.getWidth();
mDisplayHeight = mFrame.getHeight();
}
}
// Set up GestureDetector
private void setupGestureDetector() {
mGestureDetector = new GestureDetector(this,
new GestureDetector.SimpleOnGestureListener() {
// Detecting if user touched bubble here
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
// Trying to get bubble position but can't just get x=0, y=0 tried
// many things
Log.d(TAG,""+((ViewGroup)mFrame).getChildCount());
for(int i=0; i<((ViewGroup)mFrame).getChildCount(); ++i) {
View nextChild = ((ViewGroup)mFrame).getChildAt(i);
Rect rect = new Rect();
nextChild.getLocalVisibleRect(rect);
int[] location = new int[2];
nextChild.getLocationOnScreen(location);
Log.d(TAG, "X = " + location[0] + " Y = " + location[1]);
}
if(event.getAction() == MotionEvent.ACTION_DOWN){
BubbleView bubbleView = new BubbleView(getApplicationContext(), event.getX(),event.getY());
bubbleView.start();
mFrame.addView(bubbleView);
}
return true;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO - delegate the touch to the gestureDetector
return mGestureDetector.onTouchEvent(event);
}
@Override
protected void onPause() {
// TODO - Release all SoundPool resources
super.onPause();
}
// BubbleView is a View that displays a bubble.
// This class handles animating, drawing, popping amongst other actions.
// A new BubbleView is created for each bubble on the display
private class BubbleView extends View {
private static final int BITMAP_SIZE = 64;
private static final int REFRESH_RATE = 40;
private final Paint mPainter = new Paint();
private ScheduledFuture<?> mMoverFuture;
private int mScaledBitmapWidth;
private Bitmap mScaledBitmap;
// location, speed and direction of the bubble
private float mXPos, mYPos, mDx, mDy;
private long mRotate, mDRotate;
public BubbleView(Context context, float x, float y) {
super(context);
log("Creating Bubble at: x:" + x + " y:" + y);
// Create a new random number generator to
// randomize size, rotation, speed and direction
Random r = new Random();
// Creates the bubble bitmap for this BubbleView
createScaledBitmap(r);
// Adjust position to center the bubble under user's finger
mXPos = x - mScaledBitmapWidth / 2;
mYPos = y - mScaledBitmapWidth / 2;
// Set the BubbleView's speed and direction
setSpeedAndDirection(r);
// Set the BubbleView's rotation
setRotation(r);
mPainter.setAntiAlias(true);
}
// Start moving the BubbleView & updating the display
private void start() {
// Creates a WorkerThread
ScheduledExecutorService executor = Executors
.newScheduledThreadPool(1);
// Execute the run() in Worker Thread every REFRESH_RATE
// milliseconds
// Save reference to this job in mMoverFuture
mMoverFuture = executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// TODO - implement movement logic.
// Each time this method is run the BubbleView should
// move one step. If the BubbleView exits the display,
// stop the BubbleView's Worker Thread.
// Otherwise, request that the BubbleView be redrawn.
if(!isOutOfView()){
moveWhileOnScreen();
}
else{
stop(true);
}
}
}, 0, REFRESH_RATE, TimeUnit.MILLISECONDS);
}
private synchronized boolean intersects(float x, float y) {
// TODO - Return true if the BubbleView intersects position (x,y)
return false;
}
// Cancel the Bubble's movement
// Remove Bubble from mFrame
// Play pop sound if the BubbleView was popped
private void stop(final boolean popped) {
if (null != mMoverFuture && mMoverFuture.cancel(true)) {
// This work will be performed on the UI Thread
mFrame.post(new Runnable() {
@Override
public void run() {
// TODO - Remove the BubbleView from mFrame
if (popped) {
log("Pop!");
// TODO - If the bubble was popped by user,
// play the popping sound
mFrame.removeView(BubbleView.this);
//mMoverFuture.cancel(true);
mSoundPool.play(mSoundID, 1, 1, 1, 0, 1);
}
log("Bubble removed from view!");
}
});
}
}
// Change the Bubble's speed and direction
private synchronized void deflect(float velocityX, float velocityY) {
log("velocity X:" + velocityX + " velocity Y:" + velocityY);
//TODO - set mDx and mDy to be the new velocities divided by the REFRESH_RATE
mDx = velocityX/REFRESH_RATE;
mDy = velocityY/REFRESH_RATE;
}
// Draw the Bubble at its current location
@Override
protected synchronized void onDraw(Canvas canvas) {
// TODO - save the canvas
canvas.save();
// TODO - increase the rotation of the original image by mDRotate
mRotate = mRotate + mDRotate;
// TODO Rotate the canvas by current rotation
canvas.rotate(mRotate, mXPos + mScaledBitmapWidth/2, mYPos + mScaledBitmapWidth/2);
// TODO - draw the bitmap at it's new location
canvas.drawBitmap(mScaledBitmap, mXPos, mYPos,mPainter);
// TODO - restore the canvas
canvas.restore();
}
private synchronized boolean moveWhileOnScreen() {
// TODO - Move the BubbleView
// Returns true if the BubbleView has exited the screen
mXPos = mDx+mXPos;
mYPos = mDy+mYPos;
postInvalidate();
return false;
}
private boolean isOutOfView() {
// TODO - Return true if the BubbleView has exited the screen
if(mXPos + mScaledBitmapWidth/2 >= mDisplayWidth - mScaledBitmapWidth/2 || mXPos <0
||mYPos + mScaledBitmapWidth/2 >= mDisplayHeight - mScaledBitmapWidth/2 || mYPos <0){
return true;
}
return false;
}
}
更新: -
为了澄清一点,我想获得屏幕上所有气泡的位置,然后将它们与event.getX()和event.getY()进行比较,以检测我是否点击任何气泡。我必须检查onSingleTapConfirmed()
中的气泡点击。我能够正确地获得气泡总数但无法检测到它们在屏幕上的位置。
for(int i=0; i<((ViewGroup)mFrame).getChildCount(); ++i) {
View nextChild = ((ViewGroup)mFrame).getChildAt(i);
Rect rect = new Rect();
nextChild.getLocalVisibleRect(rect);
int[] location = new int[2];
nextChild.getLocationOnScreen(location);
Log.d(TAG, "X = " + location[0] + " Y = " + location[1]);
}
上面的代码给出了正确的气泡数,但是将它们的坐标恢复为0,0。
答案 0 :(得分:1)
在onSingleTapConfirmed函数中,尝试以下操作来迭代BubbleViews并传递事件X和Y坐标。
for(int i=0;i<mFrame.getChildCount();i++){
BubbleView bubbleThis = (BubbleView) mFrame.getChildAt(i);
if (bubbleThis.intersects(event.getX(),event.getY())){
bubbleThis.stop(true);
return true;
}
}
如果X和Y落在其边界内,则BubbleView中的函数应该返回true。我将在BubbleView中的intersects函数中添加函数作为说明:
private synchronized boolean intersects(float x, float y) {
if ( (x>mXPos && x<(mXPos+mScaledBitmapWidth)) && (y>mYPos && y<(mYPos+mScaledBitmapWidth)) ) {
return true;
}
return false;
}
答案 1 :(得分:0)
如果您想知道用户是否点按了气泡,请设置其onClickListener
。如果您想知道用户是否只是触摸了它,请覆盖其onTouchEvent
并查找ACTION_DOWN
。
答案 2 :(得分:0)
如何实现SimpleOnGestureListener的onDown()方法?
请看看这些答案: Gesture Detector not working
Android GestureDetector with SimpleOnGestureListener within SurfaceView
Detect which View was tapped in the onSingleTapConfirmed method
答案 3 :(得分:0)
气泡是圆形的,所以你只需要将它的半径与气泡中心和位置之间的距离进行比较。
mRadius =气泡半径
mDistance =(event.getX(),event.getY())和气泡中心之间的距离(mXPos + mRadius,mYPos + mRadius)