使用setCurrentItem打开幻灯片时,ViewPager2转场中途停滞

该应用程序使用Android viewpager2(androidx.viewpager2:viewpager2:1.0.0-beta04)来显示幻灯片。每张幻灯片的上半部分都有视频,下半部分有文字。每张幻灯片都是使用相同的片段类构建的(代码如下所示)

如果一个接一个地滑动,幻灯片放映完全正常,但是,如果尝试打开‘setCurrentItem’,有时幻灯片会在切换过程中中途中断,如下图所示。

演示活动

myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
    myViewPager2.setAdapter(myAdapter);
    myViewPager2.setOffscreenPageLimit(3);

    myViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            if (mLoadedFragment != null) {
                mLoadedFragment.pauseMedia();
            }
        }

        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);

            try {
                rvSlideIndex.invalidate();
                adapterSlideIndex.updateSelectedSlide(position);
                //setTitle(mSlides.get(position).getTitle());
                setScreenTitle(mSlides.get(position).getTitle());

                mLoadedFragment = ((PresentationSlideFragment) myAdapter.createFragment(position));
                mLoadedFragment.startVideo();

            } catch (Exception e) {

            }

        }

        @Override
        public void onPageScrollStateChanged(int state) {
            super.onPageScrollStateChanged(state);

            if (mLoadedFragment != null && state == ViewPager2.SCROLL_STATE_SETTLING) {
                mLoadedFragment.clearMediaPlayer();
            }
        }
    });

 public void onClick(final int position) {
    drawerLayout.closeDrawer(GravityCompat.START);
    //myAdapter.notifyDataSetChanged();

    myViewPager2.postDelayed(new Runnable() {

        @Override
        public void run() {
            myViewPager2.setCurrentItem(position); <--- **Here is problem**
        }
    }, 200);

}

演示活动XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_marginTop="80dp"
            android:id="@+id/rl_slide_index"
            android:layout_width="280dp"
            android:layout_height="wrap_content" />

    </com.google.android.material.navigation.NavigationView>

</androidx.drawerlayout.widget.DrawerLayout>

ViewPagerAdapter

import androidx.viewpager2.adapter.FragmentStateAdapter;

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

    private ArrayList<Fragment> slides = new ArrayList<>();

    public ViewPagerFragmentAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

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

    @Override
    public int getItemCount() {
        return slides.size();
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return slides.get(position);
    }
}

幻灯片片段

public class PresentationSlideFragment extends Fragment {

    // Class variables and constructors

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout containing a title and body text.
        ViewGroup rootView = (ViewGroup) inflater
                .inflate(R.layout.fragment_slide, container, false);

        String slideId = getArguments().getString("slideId", null);


        if (slideId != null) {

            mPresentationSlide = PresentationSlideData.getSlideById(slideId);
            mTvtitle = rootView.findViewById(R.id.tv_title);
            linearLayout = rootView.findViewById(R.id.linear);


            videoView = rootView.findViewById(R.id.videoView);

            videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    ViewGroup.LayoutParams lp = videoView.getLayoutParams();
                    lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
                    videoView.setLayoutParams(lp);
                }
            });

            videoView.postDelayed(new Runnable() {

                @Override
                public void run() {
                    videoView.setVideoURI(Uri.parse("android.resource://com.ts.appname/" + mPresentationSlide.getVideo()));
                }
            }, 50);
            //mMediaController = new MediaController(getContext());
            //videoView.setMediaController(mMediaController);

            // Binded text here---
        }

        return rootView;
    }

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

    @Override
    public void onPause() {
        super.onPause();
        pauseMedia();
    }

    public MediaController getMediaController() {
        return mMediaController;
    }

    public MediaController startVideo() {

        try {

            videoView.postDelayed(new Runnable() {

                @Override
                public void run() {

                    try {
                        videoView.start();
                        mMediaController.hide();

                    } catch (Exception e) {
                        e.printStackTrace();

                    }
                }
            }, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return mMediaController;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        clearMediaPlayer();
    }

    public void clearMediaPlayer() {
        videoView.stopPlayback();
    }

    public void pauseMedia() {
        if (videoView != null && videoView.isPlaying()) {
            videoView.pause();
        }
    }
}

幻灯片片段XML

<?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"
    android:orientation="vertical">


    <RelativeLayout
        android:id="@+id/rl_video_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
       >

        <VideoView
            android:foregroundGravity="center"
            android:id="@+id/videoView"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_gravity="center" />

        <FrameLayout
            android:id="@+id/controllerAnchor"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/videoView" />

    </RelativeLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="20dp"
        android:layout_marginTop="-10dp"
        android:layout_below="@id/rl_video_container"
        android:background="@drawable/rounded_top_gray_card_border"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:textColor="@color/colorPrimary"
            android:fontFamily="@font/fs_joey_bold"
            android:textStyle="bold"
            android:textSize="22dp" />

        <LinearLayout
            android:id="@+id/linear"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="vertical"></LinearLayout>

    </LinearLayout>
</RelativeLayout>

发生此问题时收到的警告

V/MediaPlayer:lean DrmObj:mDrmObj=空mDrmSessionID=空 V/MediaPlayer:Reset DrmState:mDrmInfo=NULL mDrmProvisioningThread=NULL mPrepareDrmInProgress=False mActiveDrmSolutions=FALSE V/MediaPlayer:lean DrmObj:mDrmObj=空mDrmSessionID=空 V/MediaPlayer:Reset DrmState:mDrmInfo=NULL mDrmProvisioningThread=NULL mPrepareDrmInProgress=False mActiveDrmSolutions=FALSE V/MediaPlayer:lean DrmObj:mDrmObj=NULL mDrmSessionID=NULL

W/View: requestLayout() improperly called by androidx.recyclerview.widget.RecyclerView{2ccd53e VFED..... ......ID 0,160-560,1424 #7f0a009d app:id/rl_slide_index} during layout: running second layout pass
W/View: requestLayout() improperly called by androidx.appcompat.widget.AppCompatTextView{623df9f V.ED..... ......ID 68,0-555,49 #7f0a002d app:id/action_bar_title} during layout: running second layout pass

欢迎所有提高代码质量或应用程序性能的建议:)


解决方案

在我的例子中,这是因为我的片段中的animateLayoutChanges属性。 因此,如果有任何animateLayoutChanges="true"删除

相关文章