我们一直在努力为我们现有的APP添加AR功能几个月,但进展有限。非常高兴能从google在sceneForm和arFragment上阅读最近的开发。我们当前的APP包含三个片段,其中一个需要AR功能。
它看起来很直接,所以我们用arFragment替换了APP中的Fragment。构建成功并在运行期间停止,几乎没有调试信息。关于我们从Fragment升级到arFragment的正确步骤的任何建议?或者我在这里错过了arFragment的观点?
为了显示问题而不通过我们的长度代码(对我们有价值),我们基于Google的示例项目构建了一个虚拟项目:HelloSceneform。基本上,我们将静态片段更改为动态片段。只更改了两个文件,并添加了两个文件,这些文件随后附加。修改后的项目可以成功构建,但在开始运行时会停止。
谢谢
彼得
///////文件已修改,HelloSceneformActivity.java:
import android.support.v4.app.FragmentTransaction;
// private ArFragment arFragment;
private ItemOneFragment arFragment;
//arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
arFragment = ItemOneFragment.newInstance();
//Manually displaying the first fragment - one time only
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, arFragment);
transaction.commit();
///////文件已修改,activity_ux.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HelloSceneformActivity">
</FrameLayout>
//////文件添加了fragment_item_one.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ItemOneFragment">
</FrameLayout>
///////文件已添加,ItemOneragment.java:
package com.google.ar.sceneform.samples.hellosceneform;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.ar.sceneform.ux.ArFragment;
public class ItemOneFragment extends ArFragment {
public static ItemOneFragment newInstance() {
ItemOneFragment fragment = new ItemOneFragment();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_item_one, container, false);
}
}
在我的一个项目中,我使用了以下结构来完成ArFragment的集成。也许这会给你一些新的提示。
我有一个根布局,第一个元素是一个名为“body”的FrameLayout。
这个“body”用作占位符来切换存在于应用程序中的3 Fragment。其中一个称为“SimulationFragment”,并扩展了Sceneform的ArFragment。相应的布局由根FrameLayout和一些元素以及另一个名为“ar_frameLayout”的嵌套FrameLayout组成。
在运行时我通过直接调用super.onCreateView()改变了onCreateView for SimulationFragment的实现,它给了我ArFragment的基本视图(这个调用也从getArSceneView()。getScene()开始初始化场景。之后我将这个视图添加到我之前膨胀的模拟片段的容器视图中,然后返回它。像这样的东西:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View containerView = inflater.inflate(R.layout.fragment_simulation, container, false);
FrameLayout arCoreFrameLayout = containerView.findViewById(R.id.ar_core_frame_layout);
// Inflate the layout for this fragment
View view = super.onCreateView(inflater, container, savedInstanceState);
arCoreFrameLayout.addView(view);
return containerView;
}
ItemOneFragment扩展了ArFragment,但重写了它的onCreateView方法以扩展自己的布局文件。我认为这就是问题所在。 ArFragment找不到它的ArSceneView和其他代码元素,只是不起作用。
当我尝试将ArFragment动态添加到我的活动时,我也遇到了同样的问题。它正在崩溃,因为我在提交片段后立即尝试访问ArSceneView,该片段在该点似乎为null。
对我有用的解决方案是实现一个完成侦听器,当片段完成配置ARSession时,它将在Activity中提供回调。
以下是基本想法。
public class MyActivity implements MyArFragment.OnCompletionListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().add(R.id.fragment_holder, new
MyArFragment(), "my_arfragment").commit();
}
@Override
public void onComplete() {
ArFragment arFragment = (ArFragment) getSupportFragmentManager().findFragmentByTag("my_arfragment");
ArSceneView view = arFragment.getArSceneView();
Scene scene = view.getScene();
scene.addOnUpdateListener(this::onUpdateFrame);
}
}
片段:
public class MyFragment extends ArFragment{
public static interface OnCompleteListener {
public abstract void onComplete();
}
private OnCompleteListener mListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
this.mListener = (OnCompleteListener)context;
}
catch (final ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement
OnCompleteListener");
}
}
@Override
protected Config getSessionConfiguration(Session session) {
//Update session config...
mListener.onComplete();
return config;
}
}