2

I am having an issue with VideoView when using with VerticalViewPager.

When I scroll/swipe the ViewPager the VideoView becomes black. Actually here VideoView is getting disappeared the black color is the background of the ViewPager.

I don't have this issue when using horizontal ViewPager even with current custom VerticalViewpager set to horizontal. When I scroll, VideoView disappears and when I lift my finger from screen VideoView appears back again.

I have tried many VerticalViewpager libraries and almost all of them have this same issue.

Have anyone faced this issue before? How to fix this?

These are the screenshots:

VideoView when not swiping:

**When not swiping**

VideoView when swiping vertically:

**When starts swiping**

Here is my code

VerticalViewpager.java

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class VerticalViewpager extends ViewPager {
    public VerticalViewpager(Context context) {
        super(context);
        init();
    }

    public VerticalViewpager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // The majority of the magic happens here
        setPageTransformer(true, new VerticalPageTransformer());
        // The easiest way to get rid of the overscroll drawing that happens on the left and right
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                view.setAlpha(1);

                // Counteract the default slide transition
                view.setTranslationX(view.getWidth() * -position);

                //set Y position to swipe in from top
                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    /**
     * Swaps the X and Y coordinates of your touch event.
     */
    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev){
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev); // return touch coordinates to original reference frame for any child views
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }
}

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {

    MyPagerAdapter adapterViewPager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        VerticalViewpager vpPager = (VerticalViewpager) findViewById(R.id.vpPAger);
        adapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
        vpPager.setAdapter(adapterViewPager);


        for (int i = 0; i < 2; i++) {
            adapterViewPager.addFragment(FragmentWithOneImage.newInstance("Frag "+ i,R.drawable.jackie));
        }

        vpPager.setAdapter(adapterViewPager);
    }

    public static class MyPagerAdapter extends FragmentStatePagerAdapter {
        private final List<Fragment> mFragments = new ArrayList<>();

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        public void addFragment(Fragment fragment) {
            mFragments.add(fragment);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }

        @Override
        public int getCount() {
            return mFragments.size();
        }

        @Override
        public float getPageWidth(int position) {
            return super.getPageWidth(position);
        }
    }
}

FragmentWithOneImage.java

import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.VideoView;

public class FragmentWithOneImage extends Fragment {
    private String title;
    private int image;


    public static FragmentWithOneImage newInstance(String title, int resImage) {
        FragmentWithOneImage fragment = new FragmentWithOneImage();
        Bundle args = new Bundle();
        args.putInt("image", resImage);
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        image = getArguments().getInt("image", 0);
        title = getArguments().getString("title");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_one_img, container, false);

        ImageView imageView = (ImageView) view.findViewById(R.id.imgMain);
        imageView.setImageResource(image);

        Uri uri = Uri.parse("http://abhiandroid-8fb4.kxcdn.com/ui/wp-content/uploads/2016/04/videoviewtestingvideo.mp4");
        VideoView simpleVideoView = (VideoView) view.findViewById(R.id.simpleVideoView); // initiate a video view
        simpleVideoView.setVideoURI(uri);
        simpleVideoView.start();
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
    }
}

activiy_main.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="match_parent"
    android:orientation="vertical">

    <com.example.sudheeshm.verticalviewpager.VerticalViewpager
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/vpPAger"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:swipe_orientation="vertical"
        android:background="@android:color/black"/>

</LinearLayout>

fragment_one_img.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    >

    <VideoView
        android:id="@+id/simpleVideoView"
        android:layout_width="match_parent"
        android:layout_height="300dp" />
    <ImageView
        android:layout_below="@+id/simpleVideoView"
        android:id="@+id/imgMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="VerticalViewpager" >
        <attr name="swipe_orientation" format="enum" >
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
        </attr>
    </declare-styleable>
</resources>
Sudheesh Mohan
  • 2,560
  • 3
  • 21
  • 38
  • You want a new instance of the video to be played or a new video in the same instance ? For this second case, I think you could use a ScrollView so you could swipe under the video instance – Ionut J. Bejan Nov 17 '17 at 13:40
  • @IonutJ.Bejan I am just swiping the Viewpager vertically and VideoView disappears. Why I need to use scrollview here? – Sudheesh Mohan Nov 17 '17 at 13:44
  • Ok, sorry I was thinking about something else. So, on each item of the viewpager you have a `NEW` instance of the video ? – Ionut J. Bejan Nov 17 '17 at 13:46
  • Yes. Each item contains fragment and in fragment there is VideoView. – Sudheesh Mohan Nov 17 '17 at 13:50
  • Is the VideoView being partially scrolled off screen? Maybe when the view detects it's scrolling, it could temporarily pause and resume when being visible. Maybe that's why when you lift your finger it resumes. – cincy_anddeveloper Nov 17 '17 at 14:07
  • Its not scrolled off the screen, when a swipe event starts it immediately disappears. Its actually the issue happening when transforming page while using PageTransformer. – Sudheesh Mohan Nov 17 '17 at 14:16
  • Read the links in my answer. It explains that SurfaceView doesn't like to be translated and exhibits weird behavior when transforming the view. VideoView is based on SurfaceView. – cincy_anddeveloper Nov 17 '17 at 14:23

1 Answers1

1

It has to do with VideoView being based on SurfaceView and this view is not optimized for tranlations (scrolling in a ViewPager). Check out these answers related to VideoViews in a ViewPager at these following links: post 1, 2.

Maybe you can find a solution to your issue.

cincy_anddeveloper
  • 1,140
  • 1
  • 9
  • 19
  • 1
    simpleVideoView.setZOrderOnTop(true); will solve the issue. But I am having a problem like this in my main project which Google Cardboard View is used(GVrView). In that there is no option for getting surfaceview from GvrView class to set zOrderOnTop(true). Anyways thanks for your answer. – Sudheesh Mohan Nov 22 '17 at 10:26
  • @SudheeshMohan The reason there is no method for modifying the Z order is because that functionality is specific to SurfaceView and how it draws content on your screen. Normally, SurfaceViews are drawn under you app's window and and "hole" is punched into your app's window to reveal the content of the Surface. GVrView doesn't not extend SurfaceView and thus more than likely has an entirely different composition. – cincy_anddeveloper Nov 22 '17 at 16:25