2013-04-04 5 views
5

Ich versuche, ein YouTubePlayerSupportFragment in einem ListView Element zu verwenden. Das ListView ist in einem Fragment das ist in einem Activity. Da es verschachtelte Fragmente gibt, verwende ich die Methode getChildFragmentManager(), um das Fragment aus dem XML-Layout zu finden. Hier ist der Code.YouTubePlayerSupportFragment im ListView-Objekt ist 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> 

Das Problem ist, dass, wenn ich versuche, das Fragment zu erzeugen, indem findFragmentById() tut es aus dem XML zu bekommen, es gibt null zurück, und das ist, was auf die Stapelverfolgung gebucht wird.

Ich versuche, den YouTube-API-Beispielen zu folgen und die erforderlichen Änderungen für verschachtelte Fragmente vorzunehmen, aber ich kann nicht herausfinden, was das Problem verursacht.

+0

Kann teilen Sie die Ausgabe dieses Befehls 'adb shell dumpsys Aktivität '? Es enthält die Liste der aktiven und hinzugefügten Fragmente. –

+0

Verwenden Sie Fragmente der Support-Bibliothek? – Yuraj

+0

Ja. Ich habe Support-Bibliothek Fragmente. –

Antwort

3

Es gibt Probleme mit dem ganzen Ansatz, den Sie gemacht haben.

Zuerst wird untergeordnetes Kindfragmente direkt von einem XML-Code not supported. Wenn Sie Fragmente verschachteln, müssen Sie sie dynamisch hinzufügen, indem Sie getChildFragmentManager im übergeordneten Fragment verwenden.

Zweitens, selbst wenn es funktioniert hat (und es könnte in einigen Fällen), haben Sie die Ansicht aufgebläht, aber nicht zum Layout des tatsächlichen Fragments hinzugefügt. Genau dafür steht die second and third parameters in der inflate Methode. Die FragmentManager sucht nach einem Fragment in seinem aktuellen Layout oder Ereignis im Backstack, kann aber keine Fragmente finden, die in einem zufälligen XML-Format aufgebläht sind und niemals verwendet werden.

Schließlich, und am wichtigsten, sollten Sie keine Fragmente als Elemente in einem ListView hinzufügen. Fragmente erwarten einen Lebenszyklus, der an die Aktivität gebunden ist, in der sie sich befinden, während eine ListView oder eine beliebige AdapterView im Allgemeinen ihre Kinder nach Bedarf erstellt, zerstört und recycelt.

Mögliche Lösungen:

  • Wie viele Videos haben Sie auf Ihrer Liste benötigen? Wenn es nicht viele von ihnen gibt, könnte ein ScrollView + LinearLayout tatsächlich die einfachste Lösung sein.

  • Wenn Sie View-Recycling wirklich benötigen, können Sie in jeder Zeile auf Live-Video verzichten? Erwägen Sie, in Ihren Zeilen einen YouTubeThumbnailView zu verwenden und dann Ihren Benutzer zu einer anderen Aktivität umzuleiten/ein Video in einem einzelnen YoutubeFragment zu laden, das sich außerhalb der Liste in Ihrem Layout befindet.

  • Wenn Sie möchten, dass Videos direkt in jeder Zeile in der Liste abgespielt werden, müssen Sie YoutubePlayerView anstelle von Fragmenten in Ihrem Zeilenlayout verwenden. Lesen Sie in diesem Fall die Dokumentation sorgfältig durch, da Sie die Videoinitialisierung durchführen und das Recycling selbst anzeigen müssen.

+0

Ich habe versucht, YouTubePlayerView in der Listenansicht zu verwenden, aber es ist ein Problem bei der Initialisierung für jede einzelne Zeile aufgetreten. Dann habe ich auch listview mit dem YouTubePlayerSupportFragment ausprobiert, aber genauso, wenn das Video in der Warteschlange die Position des geladenen Videos ändert. Es wird nicht in jeder Zeile geladen. können Sie ein beliebiges Beispiel für jede Zeile Live-Video abspielen. –

1

Ihre Anwendung zum Absturz Wenn Sie versuchen Ansicht aufzublasen mit gleichem Fragment jedes ListView Elemente (Wie Vervielfältigung in Fragment-ID wie diese quiz)

Es Zwei-Lösung (einer von ihnen aus @ivagarz Antwort):

1- Sie können nur ein youtube Video YouTubePlayerView über die ListView in Ihr Activity Layout Aber Ihr Activity Must erstreckt YouTubeBaseActivity Wie YouTube Android Player API Doc (I Verwendung anzuzeigen Denkens Diese Lösung wird Sie Ihr Problem)

2- lösen dir nicht helfen, YouTubeThumbnailView können youtube Minibild von Video für jeden Artikel in ListView mit YouTube-Player-Taste über youtube Minibild verwendet, um die Anzeige von Videos angezeigt werden soll.

Wie Das nächste Bild:

enter image description here

Wenn Benutzer auf youtube Player-Taste, haben Sie zwei Möglichkeiten:

Erste Option YouTubePlayerSupportFragment: Sie können YouTubeThumbnailView ersetzen mit YouTubePlayerSupportFragment Wenn Sie diese Option nehmen, müssen Sie:

A- hinzufügen YouTubePlayerSupportFragment programmatisch auf dem Fly (zur Vermeidung von Doppelarbeit in Fragment Id).

B- Nur ein Video in Ihr ListView anzeigen Als answer of this Question.

Ex:

list_item.xml Layout für ListView Artikel:

<?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> 

in getView Mehtod von ListView Adapter:

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) { 

      } 
     }); 
} 

ich meine eigenen erstellt wurde Fragment von YouTubePlayerSupportFragment erweitert:

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

Zweite Option YouTubeStandalonePlayer oder Erstellen Ihrer eigenen Activity erstreckt YouTubeBaseActivity: Nur wenn Benutzer auf YouTube-Player-Taste können Sie eine Intent erstellen neue Aktivität zu öffnen Video anzuzeigen Sie

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

Super +100, du bist eine großartige Erklärung für Punkt 1 –