Zooming In/Out in Samsung DeX Mode

Jakia Sultana

Engineer, Samsung Developer Program

Samsung DeX offers a PC-like experience for your phone app. If an app is compatible with DeX, the user can run it on a PC and enjoy its full features on a big screen. Generally, no additional coding is required to make your app DeX-compatible if the best practices of Android programming are followed during development. However, you must make some features compatible with DeX mode so that the user can fully enjoy the desktop experience.

If your app is a gallery app, a game, or any kind of app where multi-touch is required, this feature needs to be made compatible with DeX mode as well. You can replace the multi-touch action with a mouse wheel up/down action for DeX mode. Today, let’s get into the details of how the mouse wheel up/down action can be used to implement the pinch zoom in/out action in a DeX-compatible app.

Get Started

First, let’s go through an example where an image can be zoomed in/out by using multi-touch. For an Android device, you can achieve this feature by detecting the pinch gesture. For DeX mode, you instead need to detect the mouse wheel up/down event to implement this feature.

To start with, develop an app in which you can zoom in/out on an image. Then, make this feature compatible with DeX by receiving the mouse wheel up/down event.

Detect the Pinch Gesture on a Touch Screen

Create a new project in Android Studio, and then add a layout in an XML file. This layout should contain an image on which you can use the pinch gesture for zooming in/out.

The ScaleGestureDetector class is used to determine the scaling transformation gestures using the supplied MotionEvents. First, a ScaleGestureDetector type variable is declared. Next, implement a scale listener, which extends the SimpleOnScaleGestureListener to listen for a subset of scaling-related events. The onScale() method responds to a scaling event. The scale factor is determined in this method and then the layout is scaled accordingly. The maximum and minimum factor values are set for the layout.

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        scaleFactor *= scaleGestureDetector.getScaleFactor();
        scaleFactor = Math.max(minScaleFactor, Math.min(scaleFactor, maxScaleFactor));
        layout_main.setScaleX(scaleFactor);
        layout_main.setScaleY(scaleFactor);
        return true;
    }
} 

An instance of ScaleGestureDetector is created in the onCreate() method and the reference of the current activity and the ScaleListener instance are passed as arguments.

Next, an onTouchEvent() callback method is implemented to receive the gesture event and pass this event through to the onTouchEvent() method of the ScaleGestureDetector object.

private ScaleGestureDetector scaleGestureDetector;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    layout_main=findViewById(R.id.layout);
    scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
}
 
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
    scaleGestureDetector.onTouchEvent(motionEvent);
    return true;
}

Detect Mouse Wheel Scroll for DeX

The MotionEvent object is used to report movement events such as mouse movement. The mouse wheel up/down event is received by the MotionEvent.ACTION_SCROLL action. This action is always delivered to the window or view under the mouse pointer.

The setOnGenericMotionListener event is set on the layout where the implementation of the zoom in/out action should be done. View.OnGenericMotionListener is invoked before the generic motion event is given to the view. The onGenericMotion(View v, MotionEvent event) method is called when a generic motion event is dispatched to a view. It returns true if the listener has consumed the event, false otherwise.

AXIS_VSCROLL is the vertical scroll axis of a motion event. For a mouse, the value is normalized to a range from -1.0 (wheel down) to 1.0 (wheel up).

layout_main=findViewById(R.id.layout);

layout_main.setOnGenericMotionListener(new View.OnGenericMotionListener() {
    @Override
    public boolean onGenericMotion(View v, MotionEvent event) {
        int action = event.getAction();
            if (action == MotionEvent.ACTION_SCROLL) {
                float wheelY = event.getAxisValue(MotionEvent.AXIS_VSCROLL);

                if (wheelY > 0.0f)
                {
                    scaleFactor=  Math.min(maxScaleFactor, scaleFactor*2);

                    Log.d("Mouse_Wheel","up");
                    // write the code to zoom in
                    layout_main.setScaleX(scaleFactor);
                    layout_main.setScaleY(scaleFactor);
                }
                else
                {
                    scaleFactor=  Math.max(minScaleFactor, scaleFactor/2);
                    Log.d("Mouse_Wheel","down");
                    // write the code to zoom out
                    layout_main.setScaleX(scaleFactor);
                    layout_main.setScaleY(scaleFactor);
                }
                return true;
            }
        return true;
   }
});

If the layout supports using the mouse wheel for scrolling, then Ctrl + Mouse wheel up/down can be used for the zoom in/out action. You can implement this by following the steps below:

1. Check the status of Ctrl key. The onKeyDown() and onKeyUp() methods are called when the Ctrl key is pressed or released, respectively.

private boolean ctrlKeyPressed;

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_CTRL_LEFT:
        case KeyEvent.KEYCODE_CTRL_RIGHT:
            ctrlKeyPressed = true;
            break;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_CTRL_LEFT:
        case KeyEvent.KEYCODE_CTRL_RIGHT:
            ctrlKeyPressed = false;
            break;
    }
    return super.onKeyUp(keyCode, event);
}

2. Execute the zoom in/out action if the Ctrl key is pressed and the mouse wheel is scrolled.

if ((action == MotionEvent.ACTION_SCROLL)&& ctrlKeyPressed) {
    
    float wheelY = event.getAxisValue(MotionEvent.AXIS_VSCROLL);

        if (wheelY > 0.0f){}
        else {}
    return true;
}

Testing

Run the sample app in an Android phone to zoom the image in and out with the pinch in/out gesture. To check the mouse wheel zoom in/out feature, run the app in DeX mode. The source code of the sample app is attached at the end of this article. Feel free to download it and experiment on your own.

Conclusion

This is a basic introduction to mouse wheel interaction in Samsung DeX. There are many things you can do by enabling the mouse and mouse-wheel actions in your app. If you want to add more keyboard functionality, refer to the Android guide for Handling Keyboard Actions.

Additional Resource

Download the Source Code of Sample App