片段在ViewPager

时间:2018-02-10 17:42:03

标签: android android-fragments android-viewpager

我正在制作音乐播放器。有两项活动。第一个活动是ViewPager,其中包含四个片段(所有歌曲,播放列表,专辑和艺术家)。另一个Activity用于列出特定播放列表的歌曲。当从ViewPager中的第一个片段(即所有歌曲)播放音乐时,一切正常。现在,当我从第二个片段打开播放列表时,它会打开新的Activity列出该播放列表中的歌曲。当我点击播放时,它播放正常。但是,当我回到上一个活动(即ViewPager)并尝试在第一个片段中播放一首歌曲(即所有歌曲)时,它会播放前一个播放列表中的歌曲,该歌曲来自之前的{{ 1}}。似乎Activity失去了它的焦点,尽管它是可见的,它的Fragment点击不起作用。它适用于之前的版本,可能是因为它为RecyclerView使用相同的适配器类。我不知道我在这里做错了什么。请帮忙。

这是我的ViewPager代码。

RecyclerView

所有歌曲片段:我正在编写public class Home extends AppCompatActivity { ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.container); mViewPager.setAdapter(mSectionsPagerAdapter); TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(mViewPager); Intent service = new Intent(this, MyMusicPlayerService.class); bindService(service, serviceConnection, Context.BIND_AUTO_CREATE); } public class SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { Fragment fragment = null; switch (position) { case 0: fragment = new MyMusic(); break; case 1: fragment = new PlayList(); break; case 2: fragment = new Albums(); break; case 3: fragment = new Artist(); break; } return fragment; } @Override public int getCount() { return 4; } @Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return getResources().getString(R.string.title1); case 1: return getResources().getString(R.string.title2); case 2: return getResources().getString(R.string.title3); case 3: return getResources().getString(R.string.title4); } return null; } } } 方法onCreateView()的第一个片段。

ViewPager

第二项活动:这是第二项活动的@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_my_music, container, false); storage = new Storage(getActivity()); rvAdapter = new RVAdapter(musics, getActivity(), "all"); layoutManager = new LinearLayoutManager(getActivity()); recycler = (RecyclerView) view.findViewById(R.id.recycler); recycler.setLayoutManager(layoutManager); rvAdapter.setOnItemClickListener(new RVAdapter.OnRvItemClickListener() { @Override public void onRvItemClickListener(ArrayList<String> data, int position) { storage.storeSongs(musics); //stores all musics of the current list in an Array, in case of next and prev mListener.onFragmentInteraction(position); } }); rvAdapter.setOnOptionClickListener(new RVAdapter.OnOptionClickListener() { @Override public void onOptionClick(String mode, ArrayList<String> data) { processOption(mode, data); } }); populate(); // function to populate recyclerview recycler.setAdapter(rvAdapter); return view; } 方法,列出了第一项活动中第二个标签(播放列表)中打开的特定播放列表的歌曲。

onCreate()

1 个答案:

答案 0 :(得分:1)

这太难以回答了。但是,我想我可以让你深入了解问题的解决方案,因此我正在写一个答案。

根据我的理解,Home活动会托管Fragment中的四个ViewPager。所有这四个片段都包含RecyclerView以列出不同的内容。但是因此点击这四个RecyclerView中的任何一个Fragment中的任何项目都会显示包含歌曲列表的SecondActivity。据我所知,你可以从两个不同的地方播放歌曲。一个是Fragment中标记为所有歌曲的第一个ViewPager,另一个是SecondActivity中列出的所有其他三个Fragment中的ViewPager Fragment

现在,我想建议一个设计流程,它可以帮助您控制正在播放的歌曲。

您需要在Home活动中托管两个FragmentViewPagerContainerFragmentSecondFragment,另一个为SecondActivity。将您的SecondFragment转换为ViewPager,并将Home相关代码从您的ViewPagerContainerFragment活动转移到ViewPagerContainerFragment。默认情况下,在Home活动的片段容器中设置Home

让我们在托管这两个Fragment的{​​{1}}活动中拥有一个公共函数。我只是给你一个样品,请根据你的要求修改功能参数。

public void playSong (List<Music> musics, int position, ArrayList<String> data) {
    storage.storeSongs(musics); //stores all musics of the current list in an Array, in case of next and prev
    Intent intent = new Intent(Constants.ACTION.PLAY_INFO);
    intent.putExtra("title", data.get(0));
    intent.putExtra("artist", data.get(1));
    intent.putExtra("playStatus", "play");
    LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
    storage.storeAudioIndex(position);
    Intent intent2 = new Intent(getBaseContext(), MyMusicPlayerService.class);
    intent2.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
    startService(intent2); //play music

    updateBottom();
}

我不知道你在使用storagedata做了什么,但想法是将必要的参数传递给playSong函数来播放特定的歌曲并处理从特定列表中正确播放下一首和上一首歌曲。如果您只需在playSong函数中传递列表名称和该列表中歌曲的索引,那就太棒了。这样我们就可以从一个地方播放这首歌。

现在,正如您在playSong活动中完美地编写了函数Home,该活动处理播放歌曲并维护上一首和下一首歌以及歌曲播放所在的特定列表,问题几乎解决了。尝试保留Service意图的静态变量,以便每次不重新初始化MyMusicPlayerService类。

下一步将删除除了我们现在playSong活动中的Home功能以外的其他地方播放歌曲的代码。

AllSongsFragment修改RecyclerView上的点击操作,就像这样。

rvAdapter.setOnItemClickListener(new RVAdapter.OnRvItemClickListener() {
    @Override
    public void onRvItemClickListener(ArrayList<String> data, int position) {
        ((Home) getActivity()).playSong(...); // Call the public function that you have declared in Home activity. 
        mListener.onFragmentInteraction(position);
    }
});

SecondFragment调用playSong()功能的方式与播放该歌曲的方式相同。

另一种方法

我可以考虑另一种方法,而不会将SecondActivity更改为Fragment并保持当前结构。这可以使用LocalBroadcastReceiver来解决。您可以考虑在BroadcastReceiver活动中使用Host,并在收到来自SecondActivityAllSongsFragment的广播发送时,它会从一个地方相应地播放该歌曲。如果您想了解BroadcastReceiver的工作原理,可以查看my answer here以便更好地理解。这个想法是从一个静态的地方播放和跟踪歌曲。