实现文本放大镜

尝试使用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何在 Compose 中使用文本。

放大镜微件在 Android 9(API 级别 28)及更高版本中提供,这是一个虚拟放大镜,通过代表镜头的叠加窗格来显示 View 的放大副本。此功能可改善文本插入和选择用户体验。将该放大镜应用于文本时,用户可以通过查看窗格内跟随他们手指移动的放大文本来精确定位光标或选择手柄。

图 1 展示了放大镜如何帮助选择文本。放大镜 API 不与文本绑定,您可以在各种用例中使用此微件,例如阅读小文本或放大地图上难以看清的地名。

一张图片,显示了在抓取正确的选择手柄后放大镜的显示方式
图 1.放大文本。当用户拖动正确的选择 手柄后,系统会弹出放大镜来帮助准确定位。

放大镜已与 TextViewEditTextWebView 等平台微件集成。它可在各种应用上提供一致的文本操纵体验。 该微件附带一个简单的 API,可用于根据应用的情境放大任何 View

API 用量

您可以使用编程方式在任意视图上使用放大镜,如下所示:

Kotlin

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

Java

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

假设视图层次结构具有第一个布局,则放大镜会显示在屏幕上,并包含一个在视图内的给定坐标居中的区域。 该窗格会出现在要复制的内容的中心点上方。放大镜会持续显示,直到用户将其关闭为止。

以下代码段展示了如何更改放大视图的背景:

Kotlin

view.setBackgroundColor(...)

Java

view.setBackgroundColor(...);

假设背景颜色在该放大镜中可见,该放大镜的内容现已过时,因为系统仍显示使用旧背景的视图区域。如需刷新内容,请使用 update() 方法,如下所示:

Kotlin

view.post { magnifier.update() }

Java

view.post(magnifier::update);

完成后,通过调用 dismiss() 方法关闭放大镜:

Kotlin

magnifier.dismiss()

Java

magnifier.dismiss();

在用户互动时放大

放大镜的常见用例是让用户通过触摸来放大视图区域,如图 2 所示。

图 2. 放大镜随用户的触摸移动。它应用于 ViewGroup,其中左侧包含一个 `ImageView`,右侧包含一个 TextView

为此,您可以根据视图接收到的触摸事件来更新该放大镜,如下所示:

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

放大文本时的其他注意事项

对于平台文本微件,请务必了解具体的放大镜行为,并在整个 Android 平台以一致的方式为您的自定义文本视图启用放大镜。请注意以下几点:

  • 当用户抓取插入或选择手柄时,会立即触发放大镜。
  • 在水平方向,放大镜始终顺畅地随用户手指移动,而在垂直方向,放大镜则固定在当前文本行的中心。
  • 水平移动时,该放大镜仅在当前行的左右边界之间移动。此外,当用户的触摸离开这些边界,且触摸与最近边界之间的水平距离大于放大镜内容原始宽度的一半时,放大镜会被关闭,因为光标在放大镜内不再可见。
  • 当文本字体过大时,放大镜绝不会被触发。如果文本字体的下沉和上浮之间的距离大于放入该放大镜的内容的高度,系统会将此文本视为过大。 在这种情况下触发放大镜不会增加价值。