B L Λ C K
B L Λ C K

Reputation: 642

How to check if a Fragment is visible in a ViewPager?

First, none of the solution worked provided on stackoverflow because of either change in the Android or my problem was totally different.

What I want to achive - I want to detect when my view (for example - ThirdFragment) comes in focus and becomes visible to user. Also, it should detect when user swipes away from the current view to next view or previous view.

Why I want to do that? - Well, I am creating a media player in one of the view as shown in the example fragment code and user can play any music listed in the view by tapping on the music in the list but when user swipes to next screen it should stop.

What is the problem? - The problem is mediaplayer doesn't stop right after switching from the view but [***] if I swipe two step away, it stops but not cleanly, it jitters in the background.

What I have tried before - I have tried this setUserVisibleHint but it wasn't working because it has been depricated. onPause, onDetach, onStop none is working as mentioned here[***]

/*------Home ViewPager----- */

public class HomeFragment extends Fragment {

    private ViewPager viewPager; 

    private String[] titles = {"First","Second","Third","Fourth"};

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

    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        TextView subtitle = getActivity().findViewById(R.id.toolbar_right_subtitle);
        subtitle.setText(titles[0]);
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

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

        /* pages */
        viewPager = view.findViewById(R.id.interfaces);
        InterfaceAdapter interfacePagerAdapter = new InterfaceAdapter(getActivity().getSupportFragmentManager(),0);
        viewPager.setAdapter(interfacePagerAdapter);
        viewPager.setCurrentItem(0);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                TextView subtitle = getActivity().findViewById(R.id.toolbar_right_subtitle);
                subtitle.setText(titles[position]); 
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    } 
}

    /*---------- My Fragment Adapter --------- */

    public class InterfaceAdapter extends FragmentStatePagerAdapter {

        public InterfaceAdapter(@NonNull FragmentManager fm, int behavior) {
            super(fm, behavior);
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            switch (position){
                case 0:
                    return new FirstFragment();
                case 1:
                    return new SecondFragment();
                case 2:
                    return new ThirdFragment();
                case 3:
                    return new FourthFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return 4;
        }
    }


/*---------- One of my Fragment --------- */

public class ThirdFragment extends Fragment {

    //------Media Player ----------
    private MusicAdapter musicAdapter;
    private List<SongData> songsList;
    private ListView listView;
    private static MediaPlayer mediaPlayer;
    private Handler handler = new Handler();
    private Runnable runnable;
    private ImageView playButton, prevButton, nextButton;
    private SeekBar seekbarPayer;
    private TextView playerTime,songTitle;
    private int pos = 0;

    public ThirdFragment() {
        // Required empty public constructor
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
        eventViewModels = new ViewModelProvider((FragmentActivity) getContext()).get(EventViewModels.class);
        mediaPlayer = new MediaPlayer();
        getAllSongs();
        return inflater.inflate(R.layout.fragment_focus, container, false);
    }

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

        //--------Music Player---------------
        mediaPlayer = new MediaPlayer();
        playButton = view.findViewById(R.id.playpause_player);
        prevButton = view.findViewById(R.id.prev_player);
        nextButton = view.findViewById(R.id.next_player);
        seekbarPayer = view.findViewById(R.id.seekbar_player);
        playerTime = view.findViewById(R.id.playertime);
        songTitle = view.findViewById(R.id.songname);
        songTitle.setSelected(true);

        songsList = new ArrayList<>();
        musicAdapter = new MusicAdapter(getActivity(), songsList);
        listView = view.findViewById(R.id.songList);
        listView.setAdapter(musicAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                pos = position;
                playMusicFile(songsList.get(position).getUri(),songsList.get(position).getTitle());
            }
        });

        //play or pause music
        playButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playPause();
            }
        });

        //next music
        nextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (pos < songsList.size() - 1) {
                    pos++;
                } else {
                    pos = 0;
                }
                playMusicFile(songsList.get(pos).getUri(),songsList.get(pos).getTitle());
            }
        });

        //next music
        prevButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (pos > 0) {
                    pos--;
                } else {
                    pos = songsList.size() - 1;
                }
                playMusicFile(songsList.get(pos).getUri(),songsList.get(pos).getTitle());
            }
        });
    } 

     @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        eventViewModels.getTrigger().observe((LifecycleOwner) getContext(), new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable final Integer val) {
                assert val!=null;
                Log.d("ObserverValue",val+"");
            }
        });
    }




    @Override
    public void onStart() {
        super.onStart();
        getAllSongs();
        Log.d("SystemStatus","Start"); 
    } 

    @Override
    public void onResume() {
        super.onResume();
        getAllSongs();
        Log.d("SystemStatus","Resume"); 
    } 

    @Override
    public void onStop() {
        super.onStop();
        stopPlayer();
        Log.d("SystemStatus","Stop"); 
    }

    @Override
    public void onDetach() {
        super.onDetach();
        stopPlayer();
        Log.d("SystemStatus","Detach");
    }

    @Override
    public void onPause() {
        super.onPause();
        stopPlayer();
        Log.d("SystemStatus","Pause");   



    if (eventViewModels != null && eventViewModels.getTrigger().hasObservers()) {
     eventViewModels.getTrigger().removeObservers(this);
 } 
        }

    //---Media Player-----

    private void getAllSongs() {
       /*
        * get all songs and add it into songlist
        */
    }

    private void playMusicFile(String filePath,final String title){
        if(mediaPlayer!=null) {
            mediaPlayer.reset();
            try {
                mediaPlayer.setDataSource(filePath);
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mp.start(); 
                    }
                });
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) { 
                        stopPlayer();
                    }
                }); 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 

    private void playPause() {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start(); 
        }else {
            mediaPlayer.pause(); 
        }
    }

    private void stopPlayer() {
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
            mediaPlayer.reset(); 
        }
    } 

}

Edit:

Thanks to @ianhanniballake for providing the solution.

It solved my problem "partially". I can stop the mediaplayer but I can't stop my observer observing the event on pause. code update

Upvotes: 1

Views: 2712

Answers (1)

ianhanniballake
ianhanniballake

Reputation: 200120

You're passing in 0 as the behavior, which corresponds to the deprecated BEHAVIOR_SET_USER_VISIBLE_HINT. By using that behavior, setUserVisibleHint() will be called with true when your fragment becomes the current page and false when it is not.

If you switch to the not deprecated BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, then only the current page will get onResume(). When the page changes, that Fragment will get a callback to onPause() and the newly active fragment will get a call to onResume().

Upvotes: 4

Related Questions