2013-04-04 2 views
5

Я пытаюсь использовать YouTubePlayerSupportFragment в элементе ListView. ListView находится внутри Fragment, который находится в Activity. Поскольку есть вложенные фрагменты, я использую метод getChildFragmentManager(), чтобы попытаться найти фрагмент из XML-макета. Вот код.YouTubePlayerSupportFragment в элементе ListView имеет значение null

Java

convertView = inflater.inflate(R.layout.youtube_post_layout, null); 
YouTubePlayerSupportFragment youTubePlayerFragment = (YouTubePlayerSupportFragment) getChildFragmentManager().findFragmentById(R.id.youtube_video); 
if (youTubePlayerFragment == null) { 
    Log.i("YouTube", "player is null"); 
} else { 
    Log.i("YouTube", youTubePlayerFragment.toString()); 
} 

XML

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" > 

    <include layout="@layout/post_base_layout" /> 

    <fragment 
     android:name="com.google.android.youtube.player.YouTubePlayerSupportFragment" 
     android:id="@+id/youtube_video" 
     android:layout_width="match_parent" 
     android:layout_height="240dp" 
     android:layout_marginLeft="62dp" 
     android:layout_marginRight="32dp" 
     android:background="@color/light_grey" 
     android:cropToPadding="true" 
     android:padding="1dp" 
     android:scaleType="centerCrop" /> 

    <include layout="@layout/post_bottom_layout" /> 

</LinearLayout> 

Проблема заключается в том, что, когда я пытаюсь создать фрагмент, делая findFragmentById(), чтобы получить его из XML, он возвращает нуль, и это то, что отправлено на трассировку стека.

Я пытаюсь следовать образцам API YouTube и вносить изменения, необходимые для вложенных фрагментов, но я не могу выяснить, что вызывает проблему.

+0

Может вам поделиться выходом этой команды 'adb shell dumpsys activity '? Он содержит активный и добавленный список фрагментов. –

+0

Вы используете фрагменты библиотеки поддержки? – Yuraj

+0

Да. У меня есть фрагменты библиотеки поддержки. –

ответ

3

Есть проблемы со всем подходом, который вы приняли.

Во-первых, раздувание дочерних фрагментов непосредственно из XML: not supported. При вложении фрагментов вы должны добавить их динамически, используя getChildFragmentManager в родительском фрагменте.

Во-вторых, даже если это сработало (и это может быть в некоторых случаях), вы завысили представление, но не добавили его в макет фактического фрагмента. Вот что такое second and third parameters в методе inflate. FragmentManager будет искать фрагмент в своем текущем макете или событии в backstack, но не может найти фрагменты, завышенные в случайном XML и никогда не использовать.

Наконец, и самое главное, вы никогда не должны добавлять фрагменты в качестве элементов в ListView. Фрагменты ожидают, что жизненный цикл привязан к активности, в которой они находятся, в то время как ListView или любой AdapterView в целом будут создавать, уничтожать и перерабатывать свои дети по мере необходимости.

Возможные решения:

  • Сколько видео вам нужно в вашем списке? Если их немного, ScrollView + LinearLayout может быть самым простым решением.

  • Если вам действительно нужно View recycling, возможно, вы можете обойтись без живого видео в каждом ряду? Рассмотрите возможность использования YouTubeThumbnailView в своих рядах, затем перенаправление вашего пользователя на другую активность/загрузку видео в одном YoutubeFragment, расположенном за пределами списка на вашем макете.

  • Если вы определенно хотите, чтобы видео воспроизводилось непосредственно в каждой строке списка, вам нужно будет использовать YoutubePlayerView вместо фрагментов в макете строк. В этом случае внимательно прочитайте документацию, потому что вам нужно будет обрабатывать инициализацию видео и просматривать свою переработку самостоятельно.

+0

Я попытался использовать YouTubePlayerView внутри listview, но возникла проблема инициализации для каждой строки. Затем я также попробовал listview с помощью YouTubePlayerSupportFragment, но так же, когда в очереди видео он меняет позицию на загруженное видео. Это не загрузка в каждой строке. можете ли вы поделиться каким-либо примером для каждой прямой трансляции видео в реальном времени. –

1

ваше приложение будет врезаться При попытке раздуть вид с таким же Fragment каждого ListView элемента (как дублирование в фрагмент идентификатора, как этот quiz)

Там два решения (один из них с @ivagarz ответа):

1 Вы можете отобразить только один Youtube видео с помощью YouTubePlayerView выше вашего ListView в ваш Activity макет Но ваш Activity Must расширяет YouTubeBaseActivity Like YouTube Android Player API Doc (I Think это решение не поможет решить вашу проблему)

2- вы можете использовать YouTubeThumbnailView для отображения YouTube миниатюры видео для каждого элемента в ListView с помощью кнопки проигрывателя YouTube через YouTube миниатюрного изображения используется для отображения видео.

Как Следующая фотография:

enter image description here

Когда пользователь нажимает на кнопку проигрывателя YouTube, у вас есть два пути:

Первый вариант с использованием YouTubePlayerSupportFragment: вы можете заменить YouTubeThumbnailView с YouTubePlayerSupportFragment Если вы воспользуетесь этой опцией, вы должны:

A- добавить YouTubePlayerSupportFragment программно на лету (чтобы избежать дублирования в Fragment Id).

B- Показать только одно видео в вашем ListView As answer of this Question.

Ex:

list_item.xml макет для ListView пункт:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/parent_relativeLayout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <com.google.android.youtube.player.YouTubeThumbnailView 
      android:id="@+id/youtube_thumbnail" 
      android:layout_width="fill_parent" 
      android:layout_height="250dp" 
      android:scaleType="centerCrop" 
      android:visibility="gone"/> 

    <RelativeLayout android:id="@+id/relativeLayout_over_youtube_thumbnail" 
     android:layout_width="fill_parent" 
     android:layout_height="250dp" 
     android:background="@color/color_background_transparent" 
     android:visibility="gone"> 

     <ImageView android:id="@+id/btnYoutube_player" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:scaleType="center" 
      android:src="@drawable/youtube_player"/> 

    </RelativeLayout> 

</RelativeLayout> 

в getView mehtod из ListView адаптера:

public View getView(int position, View convertView, ViewGroup parent) { 

    convertView = inflator.inflate(R.layout.list_item.xml, parent, false); 
    final RelativeLayout relativeLayoutOverYouTubeThumbnailView = (RelativeLayout) convertView.findViewById(R.id.relativeLayout_over_youtube_thumbnail); 
    final YouTubeThumbnailView youTubeThumbnailView = (YouTubeThumbnailView) convertView.findViewById(R.id.youtube_thumbnail); 

    // get parent relative layout 
    RelativeLayout parentRelativeLayout = (RelativeLayout) convertView.findViewById(R.id.parent_relativeLayout); 
    // then create dynamic FrameLayout 
    FrameLayout.LayoutParams dynamicFrameLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); 
    final FrameLayout dynamicFrameLayout = new FrameLayout(ctx); 
     dynamicFrameLayout.setId(Different_ID); 
     dynamicFrameLayout.setLayoutParams(dynamicFrameLayoutParams); 
    // then add dynamic FrameLayout as children in parent relative layout 
    parentRelativeLayout.addView(dynamicFrameLayout); 

    ImageView youtubePlayerButton = (ImageView) convertView.findViewById(R.id.btnYoutube_player); 
    youtubePlayerButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      View parentView = (View) v.getParent().getParent(); 
      YouTubeThumbnailView youTubeThumbnailView = (YouTubeThumbnailView) parentView.findViewById(R.id.youtube_thumbnail); 
      RelativeLayout relativeLayoutOverYouTubeThumbnailView = (RelativeLayout) parentView.findViewById(R.id.relativeLayout_over_youtube_thumbnail); 
      youTubeThumbnailView.setVisibility(View.GONE); 
      relativeLayoutOverYouTubeThumbnailView.setVisibility(View.GONE); 
      YouTubeFragment youTubeFragment = new YouTubeFragment(); 
       youTubeFragment.youTubeFragmentInitialize(VideoID, youTubeFragment, parentView); 

      getSupportFragmentManager() 
       .beginTransaction() 
        .replace(dynamicFrameLayout.getId(), youTubeFragment) 
        .commit(); 

     } 
    }); 

    final YouTubeThumbnailLoader.OnThumbnailLoadedListener onThumbnailLoadedListener = new YouTubeThumbnailLoader.OnThumbnailLoadedListener(){ 
     @Override 
     public void onThumbnailError(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader.ErrorReason errorReason) { 

     } 

     @Override 
     public void onThumbnailLoaded(YouTubeThumbnailView youTubeThumbnailView, String s) { 
      loadingImage.setVisibility(View.GONE); 
      youTubeThumbnailView.setVisibility(View.VISIBLE); 
      relativeLayoutOverYouTubeThumbnailView.setVisibility(View.VISIBLE); 
     } 
    }; 

    youTubeThumbnailView.initialize(API_KEY, new YouTubeThumbnailView.OnInitializedListener() { 
      @Override 
      public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader youTubeThumbnailLoader) { 

       youTubeThumbnailLoader.setVideo(VideoID); 
       youTubeThumbnailLoader.setOnThumbnailLoadedListener(onThumbnailLoadedListener); 
      } 

      @Override 
      public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) { 

      } 
     }); 
} 

Я создал свой собственный Fragment простирается от YouTubePlayerSupportFragment:

public class YouTubeFragment extends YouTubePlayerSupportFragment { 

    public void youTubeFragmentInitialize(final String videoId, final YouTubeFragment fragment, final View parent) { 

     fragment.initialize(apiKey, new YouTubePlayer.OnInitializedListener() { 
      @Override 
      public void onInitializationSuccess(YouTubePlayer.Provider provider, final YouTubePlayer youTubePlayer, boolean wasRestored) { 

      youTubePlayer.setShowFullscreenButton(false); 
       if (!wasRestored) { 
        youTubePlayer.loadVideo(videoId); 
       } 
      } 

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

       Log.e("app", youTubeInitializationResult.toString()); 
      } 
     }); 
    } 
} 

Второй вариант использования YouTubeStandalonePlayer или создавая свой собственный Activity расширяет YouTubeBaseActivity: Просто, когда пользователь нажимает на кнопку проигрывателя YouTube, вы можете создать Намерение открыть новый вид деятельности для отображения видео

Intent intent = YouTubeStandalonePlayer.createVideoIntent(context, YOUR_DEVELOPER_KEY, VIDEO_ID); 
startActivity(intent); 
+0

Awesome +100, вы отличное объяснение для пункта 1 –

Смежные вопросы