问题描述
该应用程序使用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=NULLW/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"删除