为什么我不能在ontouch事件中使用摇动监听器?

时间:2017-04-04 16:48:09

标签: android accelerometer

我在运行Android应用时遇到问题。 当我触地时,无法调用摇动监听器。 我的逻辑是“当我摇晃时发送信息并同时按下按钮。但似乎这对我的听众部分不起作用。 但android工作室无法告诉我错误或代码在哪里错误。

这是我的按钮代码。

shakeitBtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    Toast.makeText(getBaseContext(), "Shake!", Toast.LENGTH_SHORT).show();
                    mShakeDetector = new ShakeDetector(new ShakeDetector.OnShakeListener() {

                        public void onShake() {
                            Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                            v.vibrate(300);
                            status = RELEASE_TO_SEND;
                        }
                    });
                    break;
                case MotionEvent.ACTION_UP:
                    if (status == RELEASE_TO_CANCEL) {
                        Toast.makeText(getBaseContext(), "Shake canceled", Toast.LENGTH_SHORT).show();
                    } else {
                        if (status == RELEASE_TO_SEND) {
                            DatabaseReference childRoot = rootRoomName.push();
                            Map<String, Object> map = new HashMap<String, Object>();
                            map.put("name", userName);
                            map.put("message", "I AM BUSY!!!".toString());
                            childRoot.updateChildren(map);
                        }
                        else{}
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (event.getY() < 0) {
                        status = RELEASE_TO_CANCEL;
                    } else {
                    }

                    break;
                default:
                    break;
            }
            return true;
        }
    });
    @Override
    public void onResume() {
    chat_room.super.onResume();
    mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}

    @Override
    public void onPause() {
    mSensorManager.unregisterListener(mShakeDetector);
    chat_room.super.onPause();
}

这是我的共享检测器代码

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;

public class ShakeDetector implements SensorEventListener {

// Minimum acceleration needed to count as a shake movement
private static final int MIN_SHAKE_ACCELERATION = 5;

// Minimum number of movements to register a shake
private static final int MIN_MOVEMENTS = 2;

// Maximum time (in milliseconds) for the whole shake to occur
private static final int MAX_SHAKE_DURATION = 500;

// Arrays to store gravity and linear acceleration values
private float[] mGravity = {0.0f, 0.0f, 0.0f};
private float[] mLinearAcceleration = {0.0f, 0.0f, 0.0f};

// Indexes for x, y, and z values
private static final int X = 0;
private static final int Y = 1;
private static final int Z = 2;

// OnShakeListener that will be notified when the shake is detected
private OnShakeListener mShakeListener;

// Start time for the shake detection
long startTime = 0;

// Counter for shake movements
int moveCount = 0;

// Constructor that sets the shake listener
public ShakeDetector(OnShakeListener shakeListener) {
    mShakeListener = shakeListener;
}

@Override
public void onSensorChanged(SensorEvent event) {
    // This method will be called when the accelerometer detects a change.

    // Call a helper method that wraps code from the Android developer site
    setCurrentAcceleration(event);

    // Get the max linear acceleration in any direction
    float maxLinearAcceleration = getMaxCurrentLinearAcceleration();

    // Check if the acceleration is greater than our minimum threshold
    if (maxLinearAcceleration > MIN_SHAKE_ACCELERATION) {
        long now = System.currentTimeMillis();

        // Set the startTime if it was reset to zero
        if (startTime == 0) {
            startTime = now;
        }

        long elapsedTime = now - startTime;

        // Check if we're still in the shake window we defined
        if (elapsedTime > MAX_SHAKE_DURATION) {
            // Too much time has passed. Start over!
            resetShakeDetection();
        } else {
            // Keep track of all the movements
            moveCount++;

            // Check if enough movements have been made to qualify as a shake
            if (moveCount > MIN_MOVEMENTS) {
                // It's a shake! Notify the listener.
                mShakeListener.onShake();

                // Reset for the next one!
                resetShakeDetection();
            }
        }
    }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Intentionally blank
}

private void setCurrentAcceleration(SensorEvent event) {
    /*
     *  BEGIN SECTION from Android developer site. This code accounts for
     *  gravity using a high-pass filter
     */

    // alpha is calculated as t / (t + dT)
    // with t, the low-pass filter's time-constant
    // and dT, the event delivery rate

    final float alpha = 0.8f;

    // Gravity components of x, y, and z acceleration
    mGravity[X] = alpha * mGravity[X] + (1 - alpha) * event.values[X];
    mGravity[Y] = alpha * mGravity[Y] + (1 - alpha) * event.values[Y];
    mGravity[Z] = alpha * mGravity[Z] + (1 - alpha) * event.values[Z];

    // Linear acceleration along the x, y, and z axes (gravity effects removed)
    mLinearAcceleration[X] = event.values[X] - mGravity[X];
    mLinearAcceleration[Y] = event.values[Y] - mGravity[Y];
    mLinearAcceleration[Z] = event.values[Z] - mGravity[Z];

    /*
     *  END SECTION from Android developer site
     */
}

private float getMaxCurrentLinearAcceleration() {
    // Start by setting the value to the x value
    float maxLinearAcceleration = mLinearAcceleration[X];

    // Check if the y value is greater
    if (mLinearAcceleration[Y] > maxLinearAcceleration) {
        maxLinearAcceleration = mLinearAcceleration[Y];
    }

    // Check if the z value is greater
    if (mLinearAcceleration[Z] > maxLinearAcceleration) {
        maxLinearAcceleration = mLinearAcceleration[Z];
    }

    // Return the greatest value
    return maxLinearAcceleration;
}

private void resetShakeDetection() {
    startTime = 0;
    moveCount = 0;
}

// (I'd normally put this definition in it's own .java file)
public interface OnShakeListener {
    public void onShake();
}
}

1 个答案:

答案 0 :(得分:0)

正如你所说,如果你在onTouch() bool vibrateOnShake = false; 之前启动ShakeDetector,我建议如下:

1)在您的活动/片段中创建一个参数:

mShakeDetector = new ShakeDetector(new ShakeDetector.OnShakeListener() {
    public void onShake() {
        if (vibrateOnShake) {
            Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            v.vibrate(300);
            status = RELEASE_TO_SEND;
        }
    }
});

2)在onTouch()之外启动ShakeDetector:

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();

    switch (action) {
        case MotionEvent.ACTION_DOWN:
            vibrateOnShake = true;
            ...
            break;
        ...
    }
}

3)更新你的onTouch():

y = y++;