Выявление фрагмента в действии для Android ViewManager

Я пытаюсь обернуть API Android для Android в качестве компонента пользовательского интерфейса для React Native. Я был успешным в конфигурации Android вещей (получение onInitializationSuccess), однако я не могу понять, как вернуть YouTubePlayerView в свое приложение React Native.

Согласно документам, они рекомендуют использовать YouTubePlayerFragment, если вы не можете расширить YouTubeBaseActivity. Поскольку React Native на Android не использует макеты на основе XML, я попытался создать представления программно. Однако, когда я возвращаю wrapping View (я пытался как FrameLayout, но не уверен, что это правильный выбор), я создал его, ничего не отображая в приложении.

Я хочу, чтобы это было очень просто, вот необходимые бит кода:

YouTubeManager.java

public class YouTubeManager extends SimpleViewManager<FrameLayout>  implements YouTubePlayer.OnInitializedListener {
// ...
@Override
    protected FrameLayout createViewInstance(ThemedReactContext reactContext) {
        this.reactContext = reactContext;

        FrameLayout view = new FrameLayout(reactContext);
        view.setId(View.generateViewId());


        FragmentManager fragmentManager = activity.getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        YouTubePlayerFragment fragment = new YouTubePlayerFragment();
        fragmentTransaction.add(view.getId(), fragment);

        fragmentTransaction.commit();

        fragment.initialize("SECRET_KEY", this);

        return view;
    }
// ... 
}

YouTube.js

class YouTube extends Component {
    render () {
        return <YouTubeAndroid {...this.props}/>;
    }
};

var iface = {
    name : 'YouTube',
    propTypes : {
        ...View.propTypes
    },
};


var YouTubeAndroid = requireNativeComponent('YouTube', iface);

module.exports = YouTube;

index.android.js

var YouTube = require('./YouTube');

class YouTubePlayer extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>hello</Text>
        <YouTube />
      </View>
    );
  }
}

Любая помощь будет действительно оценена, спасибо!

Ответ 1

У меня нет фактического решения для фрагмента YouTube, но я использовал некоторое обходное решение для отображения вида YouTube в RN.

(Возможно, сначала вы можете попробовать взломать 3. в своем фрагменте.)

  • Создайте свой собственный ReactActivity, который расширяет YouTubeBaseActivity, и пусть MainActivity расширяет его.

    public abstract class ReactActivity extends YouTubeBaseActivity implements DefaultHardwareBackBtnHandler {
      // copy & paste RN ReactActivity.java source
    
  • Сделайте YoutubeManager класс для YouTubePlayerView.

    Он должен взять экземпляр Activity из createViewManagers, когда вы реализуете ReactPackage.

    public class YoutubeManager extends SimpleViewManager<YouTubePlayerView> implements YouTubePlayer.OnInitializedListener, YouTubePlayer.PlayerStateChangeListener,  YouTubePlayer.PlaybackEventListener {
    
      public static final String REACT_CLASS = "RCTYoutube";
      private static final String YOUTUBE_API_KEY = "<YOUR_OWN_KEY>";
    
      private YouTubeBaseActivity mActivity = null;
      private YouTubePlayerView mYouTubePlayerView = null;
    
      public YoutubeManager(Activity activity) {
        super();
        mActivity = (YouTubeBaseActivity) activity;
      }
    
      @Override
      public String getName() {
        return REACT_CLASS;
      }
    
      @Override
      public YouTubePlayerView createViewInstance(ThemedReactContext context) {
        mContext = context;
    
        mYouTubePlayerView = new YouTubePlayerView(mActivity);
        mYouTubePlayerView.initialize(YOUTUBE_API_KEY, this);
    
        return mYouTubePlayerView;
      }
    

    и создайте для него модуль js.

    module.exports = requireNativeComponent('RCTYoutube', iface);
    
  • Теперь вы можете отображать вид на YouTube, но он кажется пустым. Вам нужно немного взломать его.

    componentDidMount() {
      this.setState({
        width: this.props.style.width,
        height: this.props.style.height - 1
      })
      this.timer = setInterval(()=>{
        this.setState({
          width: this.props.style.width,
          height: this.props.style.height + Math.floor(Math.random() * 2)
        })
      }, 500)
    }
    
    render() {
      return (<YoutubeView style={[style, { width: this.state.width, height: this.state.height }]} />)
    }
    
    componentWillUnmount() {
      if(this.timer) clearTimeout(this.timer);
    }
    

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

https://play.google.com/store/apps/details?id=kr.dobbit.sharehows