我们一直在努力为我们现有的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);
}
}
答案 0 :(得分:1)
在我的一个项目中,我使用以下结构来完成ArFragment的集成。也许这会给您一些新的提示。
我有一个根布局,其中第一个元素是称为“ body”的FrameLayout。
此“ body”用作占位符,以将现有的3 Fragment切换到应用程序中。 这三个中的一个称为“ SimulationFragment”,它扩展了Sceneform的ArFragment。 相应的布局由具有某些元素的根FrameLayout和另一个称为“ ar_frameLayout”的嵌套FrameLayout组成。
在运行时,我通过直接调用super.onCreateView()更改了SimulationFragment的onCreateView的实现,该调用为我提供了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;
}
答案 1 :(得分:0)
ItemOneFragment扩展了ArFragment,但重写了它的onCreateView方法以扩展自己的布局文件。我认为这就是问题所在。 ArFragment无法找到其ArSceneView和其他代码元素,也无法正常工作。
答案 2 :(得分:0)
当我尝试将ArFragment动态添加到活动中时,我遇到了同样的情况。 之所以崩溃,是因为我提交了当时似乎为空的片段后立即尝试访问ArSceneView。
对我有用的解决方案是实现一个完成侦听器,当片段完成对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;
}
}
答案 3 :(得分:0)
我真的很喜欢@kdroider的解决方案,但是他忘记删除对onDetach()
中活动的引用,这可能非常重要。另外,重新编写Kotlin中的代码:
import android.content.Context
import com.google.ar.core.Config
import com.google.ar.core.Session
import com.google.ar.sceneform.ux.ArFragment
class AsyncArFragment : ArFragment() {
private var onArReadyListener: OnArReadyListener? = null
interface OnArReadyListener {
fun onArReady()
}
override fun getSessionConfiguration(session: Session): Config {
onArReadyListener?.onArReady()
return super.getSessionConfiguration(session)
}
override fun onAttach(context: Context) {
super.onAttach(context)
try {
onArReadyListener = context as OnArReadyListener
} catch (e: ClassCastException) {
throw ClassCastException(context.toString() + " must implement OnArReadyListener")
}
}
override fun onDetach() {
super.onDetach()
onArReadyListener = null
}
}
不要忘记实现OnArReadyListener
接口。
警告。用交易替换片段
AnotherFragment -> AsyncArFragment
正常工作AsyncArFragment -> AnotherFragment -> AsyncArFragment
由于某种原因而无法工作(onResume(),然后立即调用onDestroy())。如果您知道如何解决,请在评论中写。 答案 4 :(得分:0)
对于任何通过谷歌来到这里的人(像我一样):
根据您的用例,可能不需要覆盖 ArFragment - 只需确保在调用 arFragment.setOnSessionInitializationListener
后访问场景。