Showing/hiding the grid with tilt-up gestures

Back in the early days of Cardboard, you had one button. That was all. The one button and head tracking were the only ways for the user to interact with the app. And because the button was a nifty magnet thing, you couldn't even press and hold the one button. With Cardboard 2.0, the screen turned into the button, and we also realized that we could briefly take the box off of our face, tilt the phone up, put it back on, and interpret that as a gesture. Thus, a second input was born! At the time of writing, the sample Cardboard apps use this as a back gesture.

We will be using tilt-up to show and hide the grid and arrows so that you can fully immerse yourself in the selected photosphere. Since it's less work, we'll also let the user do this anytime, and not just while looking at photospheres. As with the vibration feedback, this is actually a pretty painless feature to add. Most of the hard work is done by an OrientationEventListener class.

At the top of the MainActivity class, add a variable for the state of the grid, the orientation event listener, and ones for a tilt detection timer, as follows:

      static boolean setupComplete = false;

      boolean interfaceVisible = true;
      OrientationEventListener orientationEventListener;
      int orientThreshold = 10;
      boolean orientFlip = false;
      long tiltTime;
      int tiltDamper = 250;

First, we can write a method that toggles the thumbnail grid menu on/off. Check whether there are less images than planes since empty ones are already disabled in updateThumbnails:

    void toggleGridMenu() {
        interfaceVisible = !interfaceVisible;
        if (up != null)
            up.enabled = !up.enabled;
        if (down != null)
            down.enabled = !down.enabled;
        int texCount = thumbOffset;
        for (Thumbnail thumb : thumbnails) {
            if (texCount < images.size() && thumb != null) {
                thumb.setVisible(interfaceVisible);
            }
            texCount++;
        }
    }

Next, write a setupOrientationListener helper method, which provides a callback function when the device orientation changes. If the orientation gets close to vertical after being in landscape mode, we can call our toggle function, and once the device returns to landscape and goes vertical again, we toggle again:

    void setupOrientationListener() {
        orientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
            @Override
            public void onOrientationChanged(int orientation) {
                if(gridUpdateLock || !setupComplete)
                    return;
           if(System.currentTimeMillis() - tiltTime > tiltDamper) {
                    if(Math.abs(orientation) < orientThreshold || Math.abs(orientation - 180) < orientThreshold){   //"close enough" to portrait mode
                        if(!orientFlip) {
                            Log.d(TAG, "tilt up! " + orientation);
                            vibrator.vibrate(25);
                            toggleGridMenu();
                        }
                        orientFlip = true;
                    }
                    if(Math.abs(orientation - 90) < orientThreshold || Math.abs(orientation - 270) < orientThreshold) {    //"close enough" to landscape mode
                        orientFlip = false;
                    }
                          tiltTime = System.currentTimeMillis();
                }
            }
        };
        if(orientationEventListener.canDetectOrientation())
            orientationEventListener.enable();
    }

Then, add it to onCreate:

    protected void onCreate(Bundle savedInstanceState) {
        ...
        setupOrientationListener();
    }

The setupComplete flag prevents the grid from being toggled while it is still being created. Let's reset the complete flag after updateThumbnails:

    void updateThumbnails() {
        . . .
                cancelUpdate = false;
                gridUpdateLock = false;
                setupComplete = true;

It's prudent to destroy it in onDestroy:

    @Override
    protected void onDestroy(){
        super.onDestroy();
        orientationEventListener.disable();
    }

The onOrientationChanged callback will fire whenever the phone changes orientation. We'll only be interested in the times when it changes from landscape to portrait, and we also want to make sure that it doesn't happen too often, hence the tilt damper feature. You might want to tweak the value (currently 250 milliseconds) to your liking. Too short, and you might falsely register two changes in a row. Too long, and the user might try to tiltup twice within the cutoff time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset