Parth Anjaria
Parth Anjaria

Reputation: 3971

Video turns blank while scrolling view pager

I am trying to use video in viewpager. This is the viewpager I am using :

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

And this is one of the page in viewpager where I am using the videoview:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_gravity="center_horizontal"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/lato_bold"
        android:textSize="24sp"
        android:textColor="@color/passive_orange"
        android:id="@+id/passive_steps_tv"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="16dp"
        android:text="@string/passive_steps"
        />

    <VideoView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/video_player"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/passive_steps_tv"
        app:layout_constraintDimensionRatio="1.77"
        android:layout_marginTop="24dp"
        android:src="@drawable/passive_education_screen_1_image_1"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/step_collected_tv"
        android:textSize="16dp"
        android:textColor="@color/greyish_brown_two"
        android:text="@string/passive_edu_2_title"
        android:fontFamily="@font/lato_bold"
        android:layout_marginTop="36dp"
        android:id="@+id/title"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="45dp"
        android:text="3159"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/video_player"
        android:id="@+id/step_count_tv"
        android:fontFamily="@font/lato_bold"
        android:textColor="@color/greyish_brown_two"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18dp"
        android:text="@string/steps_collected"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/step_count_tv"
        android:id="@+id/step_collected_tv"
        android:fontFamily="@font/lato_regular"
        android:textColor="@color/greyish_brown_two"
        />


    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@id/left_guideline"
        app:layout_constraintRight_toRightOf="@id/right_guideline"
        app:layout_constraintTop_toBottomOf="@id/title"
        android:textSize="12dp"
        android:textColor="@color/greyish_brown_two"
        android:text="@string/passive_edu_2_text"
        android:fontFamily="@font/lato_regular"
        android:layout_marginTop="6dp"
        android:gravity="center"
        />

    <android.support.constraint.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.11"
        android:id="@+id/left_guideline"
        />

    <android.support.constraint.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.89"
        android:id="@+id/right_guideline"
        />


</android.support.constraint.ConstraintLayout>

This is the class :

public class PassiveEducationScreenItemFragment extends Fragment {

    private int position;
    ImageView image2;
    VideoView videoPlayer;
    TextView stepCountTv;
    boolean counterStarted = false;

    public static PassiveEducationScreenItemFragment newInstance(int position) {
        PassiveEducationScreenItemFragment fragment = new PassiveEducationScreenItemFragment();
        Bundle args = new Bundle();
        args.putInt("position", position);
        fragment.setArguments(args);
        return fragment;
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view;
        switch (position)
        {
            case 0 :
                view = inflater.inflate(R.layout.fragment_passive_education_screen_item_1,
                        container, false);
                break;
            case 1 :
                view = inflater.inflate(R.layout.fragment_passive_education_screen_item_2,
                        container, false);
                break;
            case 2 :
                view = inflater.inflate(R.layout.fragment_passive_education_screen_item_3,
                        container, false);
                break;
            default:
                view = inflater.inflate(R.layout.fragment_passive_education_screen_item_1,
                        container, false);

        }

        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView(view);
    }

    private void initView(View view) {
        if(position!=1) {
            image2 = view.findViewById(R.id.image_2);
            image2.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.pulse));
        }else {
            videoPlayer = view.findViewById(R.id.video_player);
            stepCountTv = view.findViewById(R.id.step_count_tv);
            setVideoToVideoPlayer();
            startStepCounter();
        }
    }

    private void startStepCounter() {
        if(!counterStarted) {
            handler.sendEmptyMessageDelayed(0, 600);
            counterStarted = true;
        }
    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            counterStarted = true;
            int stepCount = Integer.parseInt(stepCountTv.getText().toString());
            stepCount +=1;
            stepCountTv.setText(stepCount+"");
            handler.sendEmptyMessageDelayed(0,600);
        }
    };

    @Override
    public void onResume() {
        super.onResume();
        if(position==1)
        setVideoToVideoPlayer();
    }

    private void setVideoToVideoPlayer() {

        videoPlayer.setBackgroundColor(Color.TRANSPARENT);
        videoPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.setLooping(true);
            }
        });
        videoPlayer.setVideoPath("android.resource://xxx.xxx.xxx/" + R.raw.xxx);
        videoPlayer.requestFocus();
        videoPlayer.start();
    }

}

Now the issue I am facing is that when I scroll the page the video becomes blank, and when the page is loaded the video starts loading. This issue is resolved by using this link of code : videoPlayer.setZOrderOnTop(true); But then what happens is that now the video comes above the system bottom navigation buttons. So now how can I solve the issue. I want the video not to become blank when scrolling and the video not to overlap the bottom navigation buttons.

Upvotes: 0

Views: 498

Answers (2)

AndrewStone
AndrewStone

Reputation: 587

If you look at the VideoView source code, when the display surface is created/destroyed it "hides" (stops) the mediacontroller (https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/VideoView.java#697).

It appears to try to restart when the display surface is recreated, but that seems to not work (bug?).

A workaround that works for me (for RecyclerView lists) is to call stopPlayback() when the view is detached from the window (override fun onViewDetachedFromWindow) and call start() when the view is attached.

This handles the case where the item is scrolled off the screen and back on. But the case where you switch away and then back to this activity is not handled...

Upvotes: 0

Piyush
Piyush

Reputation: 18923

You should go through some changes in xml and java file.

Your xml file should be

 <FrameLayout
        android:id="@+id/frameLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" >
        <VideoView
            android:id="@+id/videoView"
            android:layout_gravity="center"
            android:layout_marginTop="16dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <FrameLayout
            android:id="@+id/placeholder"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        </FrameLayout>
    </FrameLayout>

Now in your setOnPreparedListener method change

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(final MediaPlayer mp) {
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    if (mp.getCurrentPosition() != 0) {
                        View placeholder = findViewById(R.id.placeholder);
                        placeholder.setVisibility(View.GONE);
                    } else {
                        new Handler().postDelayed(this, 50);
                    }
                }
            });

        }
    });

Upvotes: 0

Related Questions