3

几个月来,我们一直致力于将 AR 功能添加到我们现有的 APP 中,但进展有限。非常兴奋地阅读了谷歌关于 sceneForm 和 arFragment 的最新进展。我们当前的 APP 包含三个 Fragment,其中一个需要 AR 功能。

它对我们来说是直截了当的,所以我们用 arFragment 替换了我们 APP 中的 Fragment。构建成功并在运行期间停止,几乎没有调试信息。关于我们从 Fragment 升级到 arFragment 的正确步骤有什么建议吗?或者我在这里错过了 arFragment 的要点?

为了在不让您查看我们的长度代码(但对我们很有价值)的情况下显示问题,我们基于 Google 的示例项目构建了一个虚拟项目:HelloSceneform。基本上,我们将静态 Fragment 更改为动态 Fragment。只修改了两个文件,增加了两个文件,后面附上。修改后的项目可以构建成功,但是开始运行时就停止了。

谢谢

彼得

/////// 文件修改,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);
  }

}

4

5 回答 5

3

当我尝试将 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;
   }

}
于 2019-05-14T06:09:42.423 回答
1

在我的一个项目中,我使用以下结构来完成 ArFragment 的集成。也许这会给你一些新的提示。

我有一个根布局,第一个元素是名为“body”的 FrameLayout。

这个“body”用作占位符,将存在的 3 个 Fragment 切换到应用程序中。这 3 个中的一个称为“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;
}
于 2019-03-25T12:00:58.387 回答
0

对于通过谷歌来到这里的任何人(比如我):

根据您的用例,可能不需要覆盖 ArFragment - 只需确保在arFragment.setOnSessionInitializationListener调用后访问场景即可。

于 2021-01-10T22:04:20.930 回答
0

ItemOneFragment 扩展了 ArFragment 但覆盖了它的 onCreateView 方法来扩充它自己的布局文件。我认为这就是问题所在。ArFragment 找不到它的 ArSceneView 和其他代码元素,因此无法正常工作。

于 2018-05-24T05:33:18.943 回答
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接口。

警告。用事务替换片段

  1. AnotherFragment -> AsyncArFragment工作正常
  2. AsyncArFragment -> AnotherFragment -> AsyncArFragment由于某种原因不起作用(onResume() 然后立即 onDestroy() 被调用)。如果您知道如何解决它,请在评论中写下。
于 2019-08-15T12:08:45.587 回答