YouTubePlayerFragment 可以在 ViewPager 中使用吗?如果没有替代方案?

Can a YouTubePlayerFragment be used in a ViewPager? Alternatives if not?

我想要一个包含 2 或 3 个 YouTube 视频的小视图,嵌入在更宽的布局中(仅限平板电脑)。用户应该能够在视频之间切换(同时保持在相同的 Activity/screen)。是否可以使用 YouTubePlayerFragment 执行此操作?

到目前为止似乎还没有(这里有一个 relevant bug report,但由于尚未对其发表评论,因此还不是确定的 'no')。

单独使用 YouTubePlayerFragment 工作正常,但我在 ViewPager 中遇到了零星的各种问题(其中:未指定的连接问题,没有 YoutubePlayer 回调发生;每个片段显示相同的缩略图;没有回调的空白视图或其他反馈)。

这是从玩具测试项目中提取的一些代码。我可能为此 post 引入了错误编辑,并且为了清晰起见,我跳过了配置更改处理等:

public class MainActivityFragment extends Fragment {

  private static String API_KEY = "something";

  public MainActivityFragment() {
}

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    final ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.viewPager);
    TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabLayout);
    Adapter adapter = new Adapter(getChildFragmentManager());
    viewPager.setAdapter(adapter);
    tabLayout.setupWithViewPager(viewPager);

    return rootView;
}


class Adapter extends FragmentStatePagerAdapter {

    private String[] getVids(){
        return new String[]{"ORgucLTtTDI", "WzQ2RvSLR4o","dQw4w9WgXcQ"};
    }

    public Adapter(final FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(final int position) {
      YouTubePlayerSupportFragment fragment = new YouTubePlayerSupportFragment();
      fragment.initialize(API_KEY, new YouTubePlayer.OnInitializedListener() {
            @Override
            public void onInitializationSuccess(final YouTubePlayer.Provider provider,
                    final YouTubePlayer youTubePlayer,
                    final boolean b) {
                youTubePlayer.cueVideo(getVids()[position]);
            }

        return fragment;
    }

    @Override
    public int getCount() {
        return getVids().length;
    }

    @Override
    public CharSequence getPageTitle(final int position) {
        return getVids()[position] + " [" + position + "]";
    }
}

}

我想知道的是:

  1. 我是不是做错了什么导致了这些错误?
  2. 如果不是(即 YouTubePlayerFragment 的错误或限制),是否有解决方法?
  3. 如果不是(即我对这种方法一无所知),什么可能是值得探索的替代方案?我正在拉票的一些是:
    • viewpager 的一些更高级的用法。例如。使用单个 YouTubePlayerFragment 实例,在页面切换时将其放入 ViewPager,然后重新调用。
    • 完全跳过 ViewPager。手动实例化 YouTubePlayerFragments 并将其切换为 FrameLayout
    • YouTube 播放器的替代品API。也许是香草 VideoView,或 ExoPlayer(尽管它仅支持 API > 15 可能是一个障碍)

我有一个可行的(如果不是理想的)解决方案。这个问题似乎是由于当 ViewPager 将不同的片段滑入到位时,来自前一个片段的流连接仍然打开。

我的解决办法是切换ViewPager时在旧的YoutubePlayer上调用.reset(),然后在新的YoutubePlayer上再次调用.initialize()。这需要响应 TabLayout 的 onTabSelected 事件,这意味着我不能使用 .setupWithViewPager(它吞噬了 ViewPager 和 TabLayouts 视图更改事件)。这大致是适配器中需要的(initialisePlayershutDownPlayer 被调用以响应选项卡更改,在设置适配器的片段中,ViewPager 和 TabLayout):

        private SparseArray<YouTubePlayerSupportFragment> fragments = new SparseArray<>(3);
        private SparseArray<YouTubePlayer> players = new SparseArray<>(3);

        @Override
        public android.support.v4.app.Fragment getItem(final int position) {
            YouTubePlayerSupportFragment fragment = new YouTubePlayerSupportFragment();
            fragments.put(position, fragment);

            return fragment;
        }

        public void initialisePlayer(final int position) {
            YouTubePlayerSupportFragment fragment = fragments.get(position);
            fragment.initialize(API_KEY, new YouTubePlayer.OnInitializedListener() {
                @Override
                public void onInitializationSuccess(final YouTubePlayer.Provider provider, final YouTubePlayer youTubePlayer, final boolean b) {
                    players.put(position, youTubePlayer);
                    youTubePlayer.cueVideo(getVids()[position]);
                }

                @Override
                public void onInitializationFailure(final YouTubePlayer.Provider provider, final YouTubeInitializationResult youTubeInitializationResult) {
                }
            });

        }

        public void shutDownPlayer(int position) {
            YouTubePlayer player = players.get(position);
            if (player == null) {
                return;
            }
            player.release();
        }

这种方法的缺点:

  • 需要存储对 YouTubePlayerSupportFragments 和 YouTubePlayers 的引用
  • 标签在每个开关上重新初始化

如果出现任何更好的解决方案,我愿意接受。