2014-02-05 59 views

回答

1

目前用於滾動使用傳感器列表(其實沒有本地GDK UI元素,根據this issue ,使用ListView似乎不鼓勵)。

但是,我能夠在my app中得到以下相當好的工作。我的列表固定爲4個元素(這有助於確定發生多少滾動),因此您可以相應地調整它(請參閱評論)。

import com.google.android.glass.media.Sounds; 
import com.google.android.glass.touchpad.Gesture; 
import com.google.android.glass.touchpad.GestureDetector; 

import android.content.Context; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorEventListener; 
import android.hardware.SensorManager; 
import android.media.AudioManager; 
import android.view.MotionEvent; 
import android.widget.ListView; 

/** 
* Implements sensor-based scrolling of a ListView 
*/ 
public class SensorListController implements SensorEventListener, GestureDetector.BaseListener { 

    static final String TAG = "SensorListController"; 

    Context mContext; 

    ListView mList; 

    SensorManager mSensorManager; 

    private float[] mRotationMatrix = new float[16]; 

    private float[] mOrientation = new float[9]; 

    private float[] history = new float[2]; 

    private float mHeading; 

    private float mPitch; 

    boolean mActive = true; 

    GestureDetector mGestureDetector; 

    public SensorListController(Context context, ListView list) { 
     this.mContext = context; 
     this.mList = list; 
     history[0] = 10; 
     history[1] = 10; 
     mGestureDetector = new GestureDetector(mContext); 
     mGestureDetector.setBaseListener(this); 
    } 

    /** 
    * Receive pass-through of event from View 
    */ 
    public boolean onMotionEvent(MotionEvent event) { 
     return mGestureDetector.onMotionEvent(event); 
    } 

    @Override 
    public boolean onGesture(Gesture gesture) { 
     switch (gesture) { 
      case TWO_LONG_PRESS: 
       // Toggle on and off accelerometer control of the list by long press 
       playSuccessSound(); 
       toggleActive(); 
       return true; 
      case TWO_TAP: 
       // Go to top of the list 
       playSuccessSound(); 
       scrollToTop(); 
       return true; 
     } 
     return false; 
    } 

    /** 
    * Should be called from the onResume() of Activity 
    */ 
    public void onResume() { 
     mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); 
     mSensorManager.registerListener(this, 
      mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR), 
      SensorManager.SENSOR_DELAY_UI); 
    } 

    /** 
    * Should be called from the onPause() of Activity 
    */ 
    public void onPause() { 
     mSensorManager.unregisterListener(this); 
    } 

    /** 
    * Toggles whether the controller modifies the view 
    */ 
    public void toggleActive() { 
     mActive = !mActive; 
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     if (mList == null || !mActive) { 
      return; 
     } 

     if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { 
      SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values); 
      SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, 
       SensorManager.AXIS_Z, mRotationMatrix); 
      SensorManager.getOrientation(mRotationMatrix, mOrientation); 

      mHeading = (float) Math.toDegrees(mOrientation[0]); 
      mPitch = (float) Math.toDegrees(mOrientation[1]); 

      float xDelta = history[0] - mHeading; // Currently unused 
      float yDelta = history[1] - mPitch; 

      history[0] = mHeading; 
      history[1] = mPitch; 

      float Y_DELTA_THRESHOLD = 0.13f; 

//   Log.d(TAG, "Y Delta = " + yDelta); 

      int scrollHeight = mList.getHeight() 
       /19; // 4 items per page, scroll almost 1/5 an item 

//   Log.d(TAG, "ScrollHeight = " + scrollHeight); 

      if (yDelta > Y_DELTA_THRESHOLD) { 
//    Log.d(TAG, "Detected change in pitch up..."); 
       mList.smoothScrollBy(-scrollHeight, 0); 
      } else if (yDelta < -Y_DELTA_THRESHOLD) { 
//    Log.d(TAG, "Detected change in pitch down..."); 
       mList.smoothScrollBy(scrollHeight, 0); 
      } 
     } 
    } 

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

    private void scrollToTop() { 
     mList.smoothScrollToPosition(0); 
    } 

    private void playSuccessSound() { 
     // Play sound to acknowledge action 
     AudioManager audio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 
     audio.playSoundEffect(Sounds.SUCCESS); 
    } 
} 

我在ListActivity中使用了上述方法。我初始化它在onCreate(),這裏是初始化它的方法:

private void initListController() { 
    mListView = getListView(); 
    mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); 
    mListView.setSelector(android.R.color.transparent); 
    mListView.setClickable(true); 

    mListController = new SensorListController(this, mListView); 
} 

這也通過使透明去除視圖選擇指示符。

上述控制器還使用兩個手指按壓來暫停/恢復滾動,兩個手指點擊滾動到列表頂部(並用聲音確認這兩個動作)。請注意,這些手勢來工作,你需要重寫onGenericMotionEvent()在您的活動,並通過活動,如:

@Override 
public boolean onGenericMotionEvent(MotionEvent event) { 
    // We need to pass events through to the list controller 
    if (mListController != null) { 
     return mListController.onMotionEvent(event); 
    } 
    return false; 
} 

該解決方案提供完整的源代碼可以看出on Github和APK可以下載here