package com.reactnativenavigation.screens; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.widget.FrameLayout; import com.reactnativenavigation.R; import com.reactnativenavigation.params.ScreenParams; import com.reactnativenavigation.utils.ViewUtils; import com.reactnativenavigation.views.ContentView; import com.reactnativenavigation.views.LeftButtonOnClickListener; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; @SuppressWarnings("ResourceType") public class FragmentScreen extends Screen { private static final String CONTRACT_GET_FRAGMENT = "getFragment"; private static final String CONTRACT_GET_SUPPORT_FRAGMENT = "getSupportFragment"; private FrameLayout content; private ContentView contentView; public FragmentScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener leftButtonOnClickListener) { super(activity, screenParams, leftButtonOnClickListener); } @Override public ContentView getContentView() { return contentView; } @Override protected void createContent() { content = new FrameLayout(getContext()); content.setId(R.id.fragment_screen_content); addContent(); addFragment(); } private void addContent() { contentView = new ContentView(getContext(), screenParams.screenId, screenParams.navigationParams); addView(contentView, 0, 0); LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT); if (screenParams.styleParams.drawScreenBelowTopBar) { params.addRule(BELOW, topBar.getId()); } addView(content, params); } private void addFragment() { try { Fragment fragment = tryGetFragment(); if (fragment != null) { addFragment(fragment); return; } android.support.v4.app.Fragment supportFragment = tryGetSupportFragment(); if (supportFragment != null) { addSupportFragment(supportFragment); return; } throw new RuntimeException("must provide public static method " + CONTRACT_GET_FRAGMENT + " or " + CONTRACT_GET_SUPPORT_FRAGMENT); } catch (Exception e) { throw new RuntimeException(e); } } private void addFragment(Fragment fragment) { FragmentManager fm = activity.getFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); transaction.add(R.id.fragment_screen_content, fragment); transaction.commitAllowingStateLoss(); } private void addSupportFragment(android.support.v4.app.Fragment supportFragment) { android.support.v4.app.FragmentManager fm = activity.getSupportFragmentManager(); android.support.v4.app.FragmentTransaction transaction = fm.beginTransaction(); transaction.add(R.id.fragment_screen_content, supportFragment); transaction.commitAllowingStateLoss(); } @Nullable private Fragment tryGetFragment() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException { try { String className = screenParams.fragmentCreatorClassName; Class<?> fragmentCreatorClass = Class.forName(className); Method method = fragmentCreatorClass.getMethod(CONTRACT_GET_FRAGMENT, Bundle.class); return (android.app.Fragment) method.invoke(null, screenParams.fragmentCreatorPassProps); } catch (NoSuchMethodException noSuchMethod) { return null; } } @Nullable private android.support.v4.app.Fragment tryGetSupportFragment() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException { try { String className = screenParams.fragmentCreatorClassName; Class<?> fragmentCreatorClass = Class.forName(className); Method method = fragmentCreatorClass.getMethod(CONTRACT_GET_SUPPORT_FRAGMENT, Bundle.class); return (android.support.v4.app.Fragment) method.invoke(null, screenParams.fragmentCreatorPassProps); } catch (NoSuchMethodException noSuchMethod) { return null; } } @Override public void unmountReactView() { contentView.unmountReactView(); } @Override public String getNavigatorEventId() { return screenParams.getNavigatorEventId(); } @Override public void setOnDisplayListener(final OnDisplayListener onContentViewDisplayedListener) { ViewUtils.runOnPreDraw(content, new Runnable() { @Override public void run() { onContentViewDisplayedListener.onDisplay(); } }); } }