我们在Android API 4.0上运行了一个Android应用程序。其中一个活动的布局将屏幕分为两部分。在左侧,我们有一个带有一些按钮的静态部分。在右侧,我们有一个FrameLayout,它将根据按下的按钮切换到相应的片段。
问题: 右侧的一个片段包含VideoView。当用户点击按钮显示这个片段时,会显示片段并且视频立即开始播放:在渲染此片段时,整个屏幕以黑色闪烁,这非常烦人。
以下是VideoFragment类的一些代码:
public class VideoFragment extends Fragment {
public VideoView videoView;
private ExternalVideo mVideo;
private boolean mVideoExists;
private String mDestination;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDestination = ApplicationParams.MEDIA_STORAGE_PATH + "videos/"
+ FilenameUtils.getBaseName(((DetailActivity)getActivity()).getProduct().getVideoUrl())
+ "."
+ FilenameUtils.getExtension(((DetailActivity) getActivity()).getProduct().getVideoUrl());
File file = new File(mDestination);
mVideoExists = file.exists() && file.isFile();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view;
if (mVideoExists) {
getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);
view = inflater.inflate(R.layout.video, null);
mVideo = new ExternalVideo(mDestination);
videoView = (VideoView) view.findViewById(R.id.video_video);
MediaController mediaController = new MediaController(getActivity());
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setVideoPath(mVideo.getFullPath());
videoView.requestFocus();
videoView.setVisibility(View.VISIBLE);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
videoView.start();
}
});
} else {
TextView textView = new TextView(getActivity());
textView.setText(getActivity().getString(R.string.videofragment_video_coming_soon));
textView.setPadding(50, 50, 50, 50);
view = textView;
}
return view;
}
}
以下是视频片段的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView android:id="@+id/video_video"
android:layout_width="fill_parent"
android:layout_alignParentRight="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_height="fill_parent"/>
</RelativeLayout>
有没有人知道在渲染包含VideoView的片段时可能导致这个闪烁问题?一个解决方案将不胜感激!
EDIT1:如果我点击屏幕上VideoView所在的片段,则会在开头闪烁。然后,当我导航到anoter片段并返回到包含VideoView的片段时,闪烁消失了。
答案 0 :(得分:44)
我能够通过在片段的父活动的布局中添加0px by 0px SurfaceView来解决这个问题:
<SurfaceView
android:layout_width="0px"
android:layout_height="0px" />
答案 1 :(得分:12)
KennyDs是对的,但更好的是确保隐藏SurfaceView,否则如果你动画碎片你将会有非常奇怪的行为,那么除了动画片段之外你什么都看不到黑屏。幸运的是,这个抵押品问题也很容易解决:
<SurfaceView
android:layout_width="0px"
android:layout_height="0px"
android:visibility="gone" />
答案 2 :(得分:4)
如果您想知道为什么添加零大小的SurfaceView可以解决问题,您可以查看此问题SurfaceView flashes black on load。它解释得很好。
引自Evos的回答
当表面视图第一次出现在窗口中时,它通过调用私有IWindowSession.relayout(..)方法来请求窗口的参数更改。此方法“为您提供”新的框架,窗口和窗口表面。我认为屏幕在那一刻闪烁。解决方案非常简单:如果你的窗口已经有适当的参数,它将不会刷新所有窗口的东西,屏幕也不会闪烁。最简单的解决方案是将0px高度的普通SurfaceView添加到活动的第一个布局中。这将在屏幕上显示活动之前重新创建窗口,当您设置第二个布局时,它将继续使用带有当前参数的窗口。
这是解决这个问题的一种更简洁的方法,在调用setContentView()之前调用它,只是在我的ViewPager上测试了一些包含VideoView的片段,它的效果与添加零大小的SurfaceView一样好:
getWindow().setFormat(PixelFormat.TRANSLUCENT);