I want to play videos on different fragments in viewpager. I use multiple mediaplayers and surfaceviews for each fragment. When I swipe left or right, I want to pause and start videos as well. Swipe to next video has no problem at all but when i swipe to previous video(that is already playing) surfaceviews overlap. Meanwhile, I can play and pause videos without problem.
I tried almost all possible combinations of setZorderMedia and setZOrderonTop but I failed.
In short, the problem is that surfaceviews overlap in viewpager. Here are the problem related codes, layouts and a screenshot of the problem.
Layout of the activity that contains viewpager
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_tweet_activity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".TweetActivity" >
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager_tweet"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Fragment layout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/image_avatar"
android:layout_width="80dip"
android:layout_height="80dip" />
<TextView
android:id="@+id/text_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/image_avatar"
android:layout_marginLeft="18dp"
android:layout_toRightOf="@+id/image_avatar"
android:text="TextView"
android:textSize="7pt" />
<TextView
android:id="@+id/text_tweet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/image_avatar"
android:layout_below="@+id/image_avatar"
android:text="TextView"
android:textSize="7pt" />
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical"
android:layout_below="@+id/text_tweet" >
<FrameLayout
android:id="@+id/videoSurfaceContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<SurfaceView
android:id="@+id/videoSurface"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</RelativeLayout>
</RelativeLayout>
Fragment.class
private Context context=getActivity();
private View rootView;
private Typeface type;
private SurfaceView videoSurface;
private MediaPlayer player;
private VideoControllerView controller;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_tweet, container, false);
context=getActivity();
videoSurface = (SurfaceView) rootView.findViewById(R.id.videoSurface);
//videoSurface.setZOrderMediaOverlay(false);
//videoSurface.setZOrderOnTop(true);
SurfaceHolder videoHolder = videoSurface.getHolder();
videoHolder.addCallback(this);
player = new MediaPlayer();
controller = new VideoControllerView(context);
RelativeLayout videoView=(RelativeLayout) rootView.findViewById(R.id.video_container);
videoView.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
controller.show();
return false;
}
});
try {
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(context, Uri.parse("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"));
player.setOnPreparedListener(this);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return rootView;
}
// Implement SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
player.setDisplay(holder);
player.prepareAsync();
isSurfaceCreated=true;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
player.release();
}
// End SurfaceHolder.Callback
// Implement MediaPlayer.OnPreparedListener
@Override
public void onPrepared(MediaPlayer mp) {
controller.setMediaPlayer(this);
controller.setAnchorView((FrameLayout) rootView.findViewById(R.id.videoSurfaceContainer));
//player.start();
}
// End MediaPlayer.OnPreparedListener
// Implement VideoMediaController.MediaPlayerControl
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public int getCurrentPosition() {
return player.getCurrentPosition();
}
@Override
public int getDuration() {
return player.getDuration();
}
@Override
public boolean isPlaying() {
return player.isPlaying();
}
@Override
public void pause() {
player.pause();
}
@Override
public void seekTo(int i) {
player.seekTo(i);
}
@Override
public void start() {
player.start();
}
@Override
public boolean isFullScreen() {
return false;
}
@Override
public void toggleFullScreen() {
}
// End VideoMediaController.MediaPlayerControl
My VideoControllerView
My activity that contains viewpager (again the problem related part in onCreate method of the activity)
currentFragment=pager.getCurrentItem();
pager.setOnPageChangeListener(new OnPageChangeListener(){
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int index) {
TweetFragment current=pagerAdapter.getItem(currentFragment);
current.pause();
TweetFragment selected=pagerAdapter.getItem(index);
selected.start();
currentFragment=index;
}
});
Swipe to next video has no problem;
Swipe back to a video that is paused before;
If there is anymore necessary information, please ask.
I think your problem is that you are using a SurfaceView for your video.
Try using a TextureView instead.
From documentation:
Unlike SurfaceView, TextureView does not create a separate window but behaves as a regular View. This key difference allows a TextureView to be moved, transformed, animated, etc.
Edit
I don't know why the negative vote, a SurfaceView
will create a new window to draw its content.
(This is an independent window from the window of the activity, see here ).
Also note that the zOrder calls need to be called before the surface view's containing window is attached to the window manager so you cant rearrange the zOrder of your SurfaceViews
after they are created and attached.
If you really want to use multiple SurfaceViews
at the same time you could try calling setVisibility (int visibility)
on your SurfaceView
when you switch pages.
Make your videoSurface
variable public and call current.setVisibility(View.GONE)
after current.pause()
and current.setVisibility(View.VISIBLE)
after current.start()
.
I'm not sure if that will work though..
Your best bet would be to either create/destroy the SurfaceViews
each time you change a page, or try using a TextureView
as I mentioned before.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With