问题
The app uses android viewpager2 (androidx.viewpager2:viewpager2:1.0.0-beta04) to show slides. Each slide have video on its top half and text on its bottom half. Each slide is built using same fragment class (code given below)
If slided one by one, slide show works absolutely fine, however if attempted opening 'setCurrentItem', SOMETIMES slide stucks halfway in transistion as shown in image below.
Presentation Activity
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);
}
Presenation activity 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);
}
}
Slide fragment
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();
}
}
}
Slide fragment 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>
Warnings that I got when this issue occur
V/MediaPlayer: cleanDrmObj: mDrmObj=null mDrmSessionId=null V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false V/MediaPlayer: cleanDrmObj: mDrmObj=null mDrmSessionId=null V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false V/MediaPlayer: cleanDrmObj: 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
All suggestions to improve code quality or app performance is appreciated :)
来源:https://stackoverflow.com/questions/58152334/viewpager2-transistion-stuck-halfway-when-slide-opened-using-setcurrentitem