如何 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
来获取文本视图。
我的目的是在 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
来获取文本视图。