YouTube API在全屏模式下变为空白 - Android

时间:2015-03-05 06:28:01

标签: android video youtube landscape android-fullscreen

我正在使用YouTube API v3并且List的缩略图视频效果很好,当您点击列表中的视频时,它会弹出播放视频的列表上的视频框。这部分有效。但视频框是作为API库的一部分创建的(我假设),因此单击框中的全屏按钮可将其全屏显示。但是,当我转到全屏时,视频会消失并且显示为空白。没有崩溃或任何事情,只是空白。我的初始化工作正常。我记录时得到errorReason SUCCESS的值YouTube API。所以我不知道还有什么可能导致这个空白。

在我发现的其他一些Intent代码中,他们使用YouTube进入全屏模式,但这不是YouTube示例中的视频列表类所使用的,所以我不知道是否需要以某种方式。 UI示例完美地作为列表工作,它显示视频列表,然后当您单击视频框上的小扩展按钮时,无缝地进入全屏(横向)模式。

Video box over list items

看起来我错过了什么吗?请注意,视频框和全屏模式都是片段,并且是以编程方式创建的,而不是UI中创建的。在我的xml中,您将看到片段占位符,其中引用了创建package org.azurespot.cutelinks.cutevideos; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.ListFragment; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.youtube.player.YouTubeApiServiceUtil; import com.google.android.youtube.player.YouTubeInitializationResult; import com.google.android.youtube.player.YouTubePlayer; import com.google.android.youtube.player.YouTubePlayer.OnFullscreenListener; import com.google.android.youtube.player.YouTubePlayer.Provider; import com.google.android.youtube.player.YouTubePlayerFragment; import com.google.android.youtube.player.YouTubeThumbnailLoader; import com.google.android.youtube.player.YouTubeThumbnailView; import org.azurespot.R; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; public class VideosActivity extends ActionBarActivity implements OnFullscreenListener { /** The duration of the animation sliding up the video in portrait. */ private static final int ANIMATION_DURATION_MILLIS = 300; /** The padding between the video list and the video in landscape orientation. */ private static final int LANDSCAPE_VIDEO_PADDING_DP = 5; protected static final int RECOVERY_DIALOG_REQUEST = 1; /** The padding between the video list and the video in landscape orientation. */ private VideoListFragment listFragment; private VideoFragment videoFragment; private View videoBox; private View closeButton; private boolean isFullscreen; private boolean isPortrait; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_videos); getSupportActionBar().setDisplayUseLogoEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); listFragment = (VideoListFragment) getFragmentManager(). findFragmentById(R.id.list_fragment); videoFragment = (VideoFragment) getFragmentManager().findFragmentById (R.id.video_fragment_container); videoBox = findViewById(R.id.video_box); closeButton = findViewById(R.id.close_button); videoBox.setVisibility(View.INVISIBLE); layout(); checkYouTubeApi(); } private void checkYouTubeApi() { YouTubeInitializationResult errorReason = YouTubeApiServiceUtil.isYouTubeApiServiceAvailable(this); Log.e("ERROR RESULT", "Error initialization result is " + errorReason); if (errorReason.isUserRecoverableError()) { errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show(); } else if (errorReason != YouTubeInitializationResult.SUCCESS){ String errorMessage = String.format(getString(R.string.error_player), errorReason.toString()); Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RECOVERY_DIALOG_REQUEST) { // Recreate the activity if user performed a recovery action recreate(); } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); layout(); } @Override public void onFullscreen(boolean isFullscreen) { this.isFullscreen = isFullscreen; layout(); } /** * Sets up the layout programatically for the three different states. Portrait, landscape or * fullscreen+landscape. This has to be done programmatically because we handle the orientation * changes ourselves in order to get fluent fullscreen transitions, so the xml layout resources * do not get reloaded. */ private void layout() { isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; listFragment.getView().setVisibility(isFullscreen ? View.GONE : View.VISIBLE); listFragment.setLabelVisibility(isPortrait); closeButton.setVisibility(isPortrait ? View.VISIBLE : View.GONE); if (isFullscreen) { videoBox.setTranslationY(0); // Reset any translation that was applied in portrait. setLayoutSize(videoFragment.getView(), MATCH_PARENT, MATCH_PARENT); setLayoutSizeAndGravity(videoBox, MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START); } else if (isPortrait) { setLayoutSize(listFragment.getView(), MATCH_PARENT, MATCH_PARENT); setLayoutSize(videoFragment.getView(), MATCH_PARENT, WRAP_CONTENT); setLayoutSizeAndGravity(videoBox, MATCH_PARENT, WRAP_CONTENT, Gravity.BOTTOM); } else { videoBox.setTranslationY(0); // Reset any translation that was applied in portrait. int screenWidth = dpToPx(getResources().getConfiguration().screenWidthDp); setLayoutSize(listFragment.getView(), screenWidth / 4, MATCH_PARENT); int videoWidth = screenWidth - screenWidth / 4 - dpToPx(LANDSCAPE_VIDEO_PADDING_DP); setLayoutSize(videoFragment.getView(), videoWidth, WRAP_CONTENT); setLayoutSizeAndGravity(videoBox, videoWidth, WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL); } } public void onClickClose(@SuppressWarnings("unused") View view) { listFragment.getListView().clearChoices(); listFragment.getListView().requestLayout(); videoFragment.pause(); ViewPropertyAnimator animator = videoBox.animate() .translationYBy(videoBox.getHeight()) .setDuration(ANIMATION_DURATION_MILLIS); runOnAnimationEnd(animator, new Runnable() { @Override public void run() { videoBox.setVisibility(View.INVISIBLE); } }); } private void runOnAnimationEnd(ViewPropertyAnimator animator, final Runnable runnable) { if (Build.VERSION.SDK_INT >= 21) { animator.withEndAction(runnable); } else { animator.setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { runnable.run(); } }); } } /** * A fragment that shows a static list of videos. */ public static class VideoListFragment extends ListFragment{ private static final List<VideoEntry> VIDEO_LIST; static { List<VideoEntry> list = new ArrayList<VideoEntry>(); list.add(new VideoEntry("Corgi Puppy Cam", "kvxJNEl6OD4")); list.add(new VideoEntry("Husky Puppy Cam", "wo04ZWLAnvo")); list.add(new VideoEntry("Yorkie Puppy Cam", "Fen9ZXNS2Ug")); list.add(new VideoEntry("Schnauzer Puppy Live Cam", "i2-MnWWoL6M")); list.add(new VideoEntry("Relaxing Bird Feeder", "jMbtQLQoWZ8")); list.add(new VideoEntry("Guy Gets Smothered by Bunnies on Japan's Rabbit Island!", "pY-GncsZ-UE")); list.add(new VideoEntry("キツネ100匹! - Fox Village", "tMo9FWwKoiA")); list.add(new VideoEntry("Cute Alpacas!", "bwL7xUC6LqQ")); list.add(new VideoEntry("Cute Pygmy Goats!", "ScCa7fZ-xPA")); list.add(new VideoEntry("Cute Peruvian Hairless Dogs!", "le8yAr7PlSE")); list.add(new VideoEntry("Cute Baby Boar Piglets!", "Ww9zBgvxt80")); list.add(new VideoEntry("The Red Pandas of Darjeeling District, India.", "Cn3tk-rUl5Q")); list.add(new VideoEntry("Smart and Clever Animals", "V7BVUjB93ew")); list.add(new VideoEntry("Animal Odd Couples 1of2", "k9pzi8W8At0")); list.add(new VideoEntry("Pets Interrupting Yoga", "QQYK5vT9TBI")); list.add(new VideoEntry("Two Chinchillas, One Sock!", "e56I_syIMwk")); VIDEO_LIST = Collections.unmodifiableList(list); } private PageAdapter adapter; private View videoBox; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); adapter = new PageAdapter(getActivity(), VIDEO_LIST); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); videoBox = getActivity().findViewById(R.id.video_box); getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); setListAdapter(adapter); } @Override public void onListItemClick(ListView l, View v, int position, long id) { String videoId = VIDEO_LIST.get(position).videoId; VideoFragment videoFragment = (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container); videoFragment.setVideoId(videoId); // The videoBox is INVISIBLE if no video was previously selected, so we need to show it now. if (videoBox.getVisibility() != View.VISIBLE) { if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // Initially translate off the screen so that it can be animated in from below. videoBox.setTranslationY(videoBox.getHeight()); } videoBox.setVisibility(View.VISIBLE); } // If the fragment is off the screen, we animate it in. if (videoBox.getTranslationY() > 0) { videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS); } } @Override public void onDestroyView() { super.onDestroyView(); adapter.releaseLoaders(); } public void setLabelVisibility(boolean visible) { adapter.setLabelVisibility(visible); } } private static final class PageAdapter extends BaseAdapter { private final List<VideoEntry> entries; private final List<View> entryViews; private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap; private final LayoutInflater inflater; private final ThumbnailListener thumbnailListener; private boolean labelsVisible; public PageAdapter(Context context, List<VideoEntry> entries) { this.entries = entries; entryViews = new ArrayList<>(); thumbnailViewToLoaderMap = new HashMap<>(); inflater = LayoutInflater.from(context); thumbnailListener = new ThumbnailListener(); labelsVisible = true; } public void releaseLoaders() { for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) { loader.release(); } } public void setLabelVisibility(boolean visible) { labelsVisible = visible; for (View view : entryViews) { view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE); } } @Override public int getCount() { return entries.size(); } @Override public VideoEntry getItem(int position) { return entries.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; VideoEntry entry = entries.get(position); // There are three cases here if (view == null) { // 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView. view = inflater.inflate(R.layout.you_tube_row_item, parent, false); YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail); thumbnail.setTag(entry.videoId); thumbnail.initialize(DeveloperKey.DEVELOPER_KEY, thumbnailListener); } else { YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail); YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail); if (loader == null) { // 2) The view is already created, and is currently being initialized. We store the // current videoId in the tag. thumbnail.setTag(entry.videoId); } else { // 3) The view is already created and already initialized. Simply set the right videoId // on the loader. thumbnail.setImageResource(R.drawable.loading_thumbnail); loader.setVideo(entry.videoId); } } TextView label = ((TextView) view.findViewById(R.id.text)); label.setText(entry.text); label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE); return view; } private final class ThumbnailListener implements YouTubeThumbnailView.OnInitializedListener, YouTubeThumbnailLoader.OnThumbnailLoadedListener { @Override public void onInitializationSuccess( YouTubeThumbnailView view, YouTubeThumbnailLoader loader) { loader.setOnThumbnailLoadedListener(this); thumbnailViewToLoaderMap.put(view, loader); view.setImageResource(R.drawable.loading_thumbnail); String videoId = (String) view.getTag(); loader.setVideo(videoId); } @Override public void onInitializationFailure( YouTubeThumbnailView view, YouTubeInitializationResult loader) { view.setImageResource(R.drawable.no_thumbnail); } @Override public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) { } @Override public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) { view.setImageResource(R.drawable.no_thumbnail); } } } public static class VideoFragment extends YouTubePlayerFragment implements YouTubePlayer.OnInitializedListener { YouTubePlayer player; private String videoId; public static VideoFragment newInstance() { return new VideoFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initialize(DeveloperKey.DEVELOPER_KEY, this); newInstance(); } @Override public void onDestroy() { if (player != null) { player.release(); } super.onDestroy(); } public void setVideoId(String videoId) { if (videoId != null && !videoId.equals(this.videoId)) { this.videoId = videoId; if (player != null) { player.cueVideo(videoId); } } } public void pause() { if (player != null) { player.pause(); } } @Override public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean restored) { this.player = player; player.addFullscreenControlFlag(YouTubePlayer. FULLSCREEN_FLAG_CUSTOM_LAYOUT); player.setOnFullscreenListener((VideosActivity) getActivity()); if (!restored && videoId != null) { player.cueVideo(videoId); } } @Override public void onInitializationFailure(Provider provider, YouTubeInitializationResult result) { this.player = null; } } private static final class VideoEntry { private final String text; private final String videoId; public VideoEntry(String text, String videoId) { this.text = text; this.videoId = videoId; } } // Utility methods for layouting. private int dpToPx(int dp) { return (int) (dp * getResources().getDisplayMetrics().density + 0.5f); } private static void setLayoutSize(View view, int width, int height) { ViewGroup.LayoutParams params = view.getLayoutParams(); params.width = width; params.height = height; view.setLayoutParams(params); } private static void setLayoutSizeAndGravity(View view, int width, int height, int gravity) { RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams(); params.width = width; params.height = height; view.setLayoutParams(params); } // @Override // public boolean onCreateOptionsMenu(Menu menu) { // // Inflate the menu; this adds items to the action bar if it is present. // getMenuInflater().inflate(R.menu.menu_webcams, menu); // return true; // } @Override public boolean onOptionsItemSelected(MenuItem item) { // Makes the UP caret go back to the previous fragment MakeCuteFragment switch (item.getItemId()) { case android.R.id.home: android.app.FragmentManager fm = getFragmentManager(); fm.popBackStack(); finish(); return true; default: return super.onOptionsItemSelected(item); } } } 的类。

感谢您的帮助。

VideosActivity.java

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#2198bb">

        <fragment
            class="org.azurespot.cutelinks.cutevideos.VideosActivity$VideoListFragment"
            android:id="@+id/list_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="15dp"
            android:background="@drawable/button_border"/>

        <LinearLayout
            android:id="@+id/video_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_margin="15dp"
            android:orientation="vertical"
            android:background="@drawable/button_border">

            <ImageButton
                android:id="@+id/close_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:src="@android:drawable/btn_dialog"
                android:onClick="onClickClose"/>

            <fragment
                class="org.azurespot.cutelinks.cutevideos.VideosActivity$VideoFragment"
                android:id="@+id/video_fragment_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>
    </RelativeLayout>
</merge>

activity_videos.xml

{{1}}

1 个答案:

答案 0 :(得分:3)

问题在于onInitializationSuccess()方法中的标志。 YouTube示例附带的标记为FULLSCREEN_FLAG_CUSTOM_LAYOUT,根据YouTube API docs,它实际上会禁用全屏视图,以便您可以手动编写视图代码。由于此标志适用于YouTube的样本,我不知道我必须手动更改它。所以我只需要改变标志,选择FULLSCREEN_FLAG_ALWAYS_FULLSCREEN_IN_LANDSCAPE,然后从视频框进入全屏模式(如上图所示),它进入全屏模式并继续播放视频。嗯,实际上它被编码为暂停,当你改变方向时,你可以按下播放它可以工作。