2017-04-04 2 views
0

Ich habe ein Problem, wenn ich meine Android App laufen lasse. Der Shake-Listener kann nicht aufgerufen werden, wenn ich auflege. Meine Logik ist „Nachricht senden, wenn ich Schütteln und Taste gleichzeitig aufsetzt. Aber es scheint, dass nicht für meine Zuhörer Teil arbeiten kann. Aber das Android-Studio kann nicht mir sagen, wo ist der Fehler oder Code falsch.Warum kann ich Schüttel-Listener nicht im Otouch-Ereignis verwenden?

Hier Code meine Taste

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(); 
} 

Hier Detektor Code meinen Anteil

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(); 
} 
} 
+0

Funktioniert ShakeDetector ohne die onTouch()? –

+0

Es kann funktionieren. Ich habe versucht, Teil von Knopf zu schütteln, und es kann Nachricht senden. Es funktioniert jedoch nicht, wenn ich die Codes wieder in den Button-Teil lege. –

Antwort

0

Wie Sie die ShakeDetector sagte funktioniert, wenn Sie es vor dem onTouch() ich schlage vor, die folgenden beginnen.

1) Erstellen Sie einen Parameter in Ihrer Aktivität/Fragment:

bool vibrateOnShake = false; 

2) Init Ihre ShakeDetector außerhalb des OnTouch():

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; 
     } 
    } 
}); 

3) Aktualisieren Sie Ihre OnTouch():

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

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