如何 refresh/repaint 在 Android Sceneform 中渲染一个 TextView?

How to refresh/repaint a TextView rendered in Android Sceneform?

我的目的是在 Android Sceneform 应用的增强图像中使用 TextView ("info card") 显示动态传感器读数。

我使用 SceneForm 的 AugmentedImage 示例作为基础。我从 Solarsystem 示例中复制了信息卡概念,最后(经过几天令人沮丧的努力)设法想出了一种从 lambda 函数中获取 TextView 的方法,这样我就可以在主函数中使用 setText activity(自从我之前的 java 1.2 体验以来已经有一段时间了)。我现在可以使用时间戳值将 setText() 成功设置到 TextView(使用 getText() 调试),但稍后会尝试更改它以通过 HTTP 或 MQTT 获取值。

问题是,一旦使用正确显示的第一个值启动视图,我就无法在屏幕上重新绘制 TextView/(信息卡)。我曾尝试使 TextView 实例无效,并尝试使用其他一些方法来重新绘制节点,但均未成功。

在 AugmentedImageActivity 中:

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

    arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
    fitToScanView = findViewById(R.id.image_view_fit_to_scan);

    LinearLayout mainLayout = (LinearLayout) findViewById(R.layout.activity_main);
    LayoutInflater inflater = getLayoutInflater();
    View infoCardLayout = inflater.inflate(R.layout.info_card_view, mainLayout, false);
    textView = (TextView) infoCardLayout.findViewById(R.id.textView);

    arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
}

在 AugmentedImageActivity 中:

private void onUpdateFrame(FrameTime frameTime) {
    Frame frame = arFragment.getArSceneView().getArFrame();
    Log.d("TW_onUpdateFrame","onUpdateFrame");
    String t = String.valueOf(System.currentTimeMillis());
    t = t.substring(t.length()-6);
    textView.setText(t);

在 AugmentedImageNode.java 中 setImage:

  ...
  localPosition.set(0.0f, 0.0f, -0.8f * image.getExtentZ());
  infoCard = new Node();
  infoCard.setParent(this);
  infoCard.setEnabled(true);
  infoCard.setLocalPosition(localPosition);
  infoCard.setLocalRotation(new Quaternion(new Vector3(1.0f,0.0f,0.0f),-90));

  ViewRenderable.builder()
          .setView(context, R.layout.info_card_view)
          .build()
          .thenAccept(
                  (renderable) -> {
                      infoCard.setRenderable(renderable);
                      TextView textView = (TextView) renderable.getView();
                      textView.setText("Value from setImage");
                  })
          .exceptionally(
                  (throwable) -> {
                      throw new AssertionError("Could not load info card view.", throwable);
                  });

如何以及在何处重新绘制信息卡的 TextView?还考虑到将来需要通过 HTTP 异步获取值吗?这个 ViewRenderable.builder() 和 thenAccept 的 lambda 函数让我哭了:)

您通过在构造函数中膨胀它然后让 ViewRenderable 构建器再次膨胀它来创建视图两次。您保存的不是实际渲染的那个。

您只构建一次 ViewRenderable,因此 thenAccept 的回调只被调用一次。您需要将在那里获得的视图保存到 AugmentedImageNode 中的某个变量,然后使用 getter 函数公开它,以便您可以在 AugmentedImageActivity 中检索它。然后,您将像以前一样在 onUpdateFrame 中调用 setText

另外请记住,renderable.getView() 为您提供了布局视图,您仍然需要调用 findViewById 来获取文本视图。