lightbulb_outline Please take our October 2018 developer survey. Start survey

Magnifier widget

Available in Android 9 (API level 28) and higher, the magnifier widget is a virtual magnifying glass that displays an enlarged copy of a chosen View through an overlay pane that represents the lens. The feature improves the text insertion and selection user experience: when applying the magnifier to text, a user can precisely position the cursor or the selection handles by viewing the magnified text in a pane that follows their finger. Figure 1 below showcases the way the magnifier facilitates selecting text. The magnifier APIs are not tied to text, and this widget can be used in a variety of use cases, such as reading small type or enlarging hard-to-see place names on maps.

The magnifier is already integrated with platform widgets such as TextView, EditText, or WebView. It provides consistent text manipulation across applications. The widget comes with a simple API and can be used to magnify any View depending on your application’s context.

the magnifier appears after grabbing the right selection handle

Figure 1. Magnifying text. After the user grabs the right selection handle, the magnifier pops up to help with accurate placement.

API usage

The magnifier can be programmatically used on an arbitrary view as follows:

Kotlin

val view: View = findViewById(R.id.view)
val magnifier = Magnifier(view)
magnifier.show(view.width / 2.0f, view.height / 2.0f)

Java

View view = findViewById(R.id.view);
Magnifier magnifier = new Magnifier(view);
magnifier.show(view.getWidth() / 2, view.getHeight() / 2);

Assuming that the view hierarchy already had the first layout, the magnifier is displayed on the screen and contains a region centered on the given coordinates within the View. The pane appears above the center point of the content being copied. The magnifier persists indefinitely until the user dismisses it.

Suppose that we want to change the background of the magnified view:

Kotlin

view.setBackgroundColor(...)

Java

view.setBackgroundColor(...);

Assuming that the background color is visible within the magnifier, the magnifier’s content is now stale, as a region of the view with the old background is still displayed. To refresh the content, use the update() method:

Kotlin

view.post { magnifier.update() }

Java

view.post(new Runnable() {
    magnifier.update();
});

When finished, close the magnifier by calling the dismiss() method:

Kotlin

magnifier.dismiss()

Java

magnifier.dismiss();

Magnify on user interaction

A common use case for the magnifier is to allow the user to enlarge a view region by touching it, as shown in Figure 2 below. You can achieve this by updating the magnifier according to the touch events received by the view:

Kotlin

imageView.setOnTouchListener { v, event ->
  when (event.actionMasked) {
    MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
      val viewPosition = IntArray(2)
      v.getLocationOnScreen(viewPosition)
      magnifier.show(event.rawX - viewPosition[0], event.rawY - viewPosition[1])
    }
    MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
      magnifier.dismiss()
    }
  }
  true
}

Java

imageView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                // Fall through.
            case MotionEvent.ACTION_MOVE: {
                final int[] viewPosition = new int[2];
                v.getLocationOnScreen(viewPosition);
                magnifier.show(event.getRawX() - viewPosition[0],
                               event.getRawY() - viewPosition[1]);
                break;
            }
            case MotionEvent.ACTION_CANCEL:
                // Fall through.
            case MotionEvent.ACTION_UP: {
                magnifier.dismiss();
            }
        }
        return true;
    }
});

the magnifier follows the user's touch

Figure 2. The magnifier follows the user's touch. It is applied to a ViewGroup that contains an ImageView to the left and a TextView to the right.

Additional considerations when magnifying text

For the platform text widgets, it's important to understand specific magnifier behaviors and to enable the magnifier for your custom text view in a consistent way across the entire Android platform. Consider the following:

  • The magnifier is triggered immediately when the user grabs an insertion or selection handle.
  • The magnifier always smoothly follows the user’s finger horizontally, while vertically it is fixed to the center of the current text line.
  • When moving horizontally, the magnifier moves only between the left and right bounds of the current line. Moreover, when the user’s touch leaves these bounds and the horizontal distance between the touch and the closest bound is larger than half of the original width of the magnifier content, the magnifier is dismissed, as the cursor would no longer be visible inside the magnifier.
  • The magnifier is never triggered when the text font is too large. Specifically, text is considered too large when the difference between the font’s descent and ascent is larger than the height of the content that fits in the magnifier. Triggering the magnifier in this case does not add value.