лучшая практика для интеграции arFragment (sceneForm) с существующим приложением Fragment

Мы работали над добавлением функций AR в наше существующее приложение в течение нескольких месяцев с ограниченным прогрессом. Очень рад прочитать недавнюю разработку Google в отношении sceneForm и arFragment. наше текущее приложение состоит из трех фрагментов, и одному из них потребуются функции дополненной реальности.

Для нас это выглядит прямолинейно, поэтому мы заменили фрагмент в нашем приложении на arFragment. Сборка выполнена успешно и остановлена ​​во время работы с небольшим количеством информации для отладки. какие-нибудь предложения о том, как нам правильно перейти с 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);
  }

}


person Peter Yin    schedule 18.05.2018    source источник
comment
Можете поделиться в чем проблема? Это не так много информации, чтобы понять ваш вопрос.   -  person Clayton Wilkinson    schedule 18.05.2018
comment
Привет, Клейтон, спасибо за ответ. чтобы показать проблему, не просматривая наш код длины (но ценный для нас), мы создали фиктивный проект на основе примера проекта из Google: HelloSceneform. По сути, мы изменили статический фрагмент на динамический фрагмент. Изменяются только два файла и добавляются два файла, которые затем прикрепляются. Модифицированный проект может быть успешно собран, но остановлен при запуске.   -  person Peter Yin    schedule 19.05.2018
comment
Где вы можете этого добиться?   -  person KARUNESH PALEKAR    schedule 30.07.2021


Ответы (5)


Я испытал то же самое, когда пытался динамически добавить ArFragment в свою деятельность. Он дает сбой, потому что я пытался получить доступ к ArSceneView сразу после фиксации фрагмента, который на тот момент казался нулевым.

Решение, которое сработало для меня, состояло в том, чтобы реализовать прослушиватель завершения, который обеспечит обратный вызов в действии, когда фрагмент завершит настройку ARSession.

Ниже представлена ​​основная идея.

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;
   }

}
person kdroider    schedule 14.05.2019

В одном из моих проектов я использовал следующую структуру для интеграции ArFragment. Возможно, это даст вам новые подсказки.

У меня есть корневой макет с первым элементом FrameLayout, который называется «тело».

Это «тело» используется в качестве заполнителя для переключения трех существующих фрагментов в приложение. Один из этих 3 называется «SimulationFragment» и расширяет ArFragment формы сцены. Соответствующий макет состоит из корневого FrameLayout с некоторыми элементами и еще одним вложенным FrameLayout, называемым «ar_frameLayout».

Во время выполнения я изменил реализацию onCreateView для SimulationFragment с прямым вызовом super.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;
}
person TomD88    schedule 25.03.2019

ItemOneFragment расширяет ArFragment, но переопределяет его метод onCreateView для создания собственного файла макета. Я думаю, это проблема. ArFragment не может найти свой ArSceneView и другие элементы кода и просто не будет работать.

person Steven Mohr    schedule 24.05.2018
comment
Спасибо, Стивен, за ваш ответ. Плохая новость заключается в том, что мы до сих пор не можем заставить его работать после вашей подсказки. мы здесь новички, и документация НЕ очень ясна. Хорошая новость в том, что мы получили то, что нам нужно. Мы не использовали фреймворк из ArSenceView, мы использовали фреймворк из демонстрации hello_ar_java и переключали отображение между одним представлением и двумя фрагментами. Для меня это уродливая структура. но мы останемся с ним на некоторое время до тех пор :-) - person Peter Yin; 02.06.2018
comment
Если вам нужна дополнительная помощь, просто отправьте мне электронное письмо. Мою контактную информацию можно найти здесь: smartasapps.de/en/contact-us - person Steven Mohr; 02.06.2018

Мне очень понравилось решение @kdroider, но он забыл убрать ссылку на активность в onDetach(), что может быть очень важно. Также переписал код на Котлине:

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()). Если вы знаете, как это исправить, пожалуйста, напишите в комментариях.
person soshial    schedule 15.08.2019

Для тех, кто приходит сюда через Google (например, я):

В зависимости от вашего варианта использования может не потребоваться переопределение ArFragment — просто убедитесь, что вы получили доступ к сцене после вызова arFragment.setOnSessionInitializationListener.

person tobitobitobi    schedule 10.01.2021