我正在制作音乐播放器。有两项活动。第一个活动是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()
答案 0 :(得分:1)
这太难以回答了。但是,我想我可以让你深入了解问题的解决方案,因此我正在写一个答案。
根据我的理解,Home
活动会托管Fragment
中的四个ViewPager
。所有这四个片段都包含RecyclerView
以列出不同的内容。但是因此点击这四个RecyclerView
中的任何一个Fragment
中的任何项目都会显示包含歌曲列表的SecondActivity
。据我所知,你可以从两个不同的地方播放歌曲。一个是Fragment
中标记为所有歌曲的第一个ViewPager
,另一个是SecondActivity
中列出的所有其他三个Fragment
中的ViewPager
Fragment
。
现在,我想建议一个设计流程,它可以帮助您控制正在播放的歌曲。
您需要在Home
活动中托管两个Fragment
。 ViewPagerContainerFragment
为SecondFragment
,另一个为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();
}
我不知道你在使用storage
和data
做了什么,但想法是将必要的参数传递给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
,并在收到来自SecondActivity
和AllSongsFragment
的广播发送时,它会从一个地方相应地播放该歌曲。如果您想了解BroadcastReceiver
的工作原理,可以查看my answer here以便更好地理解。这个想法是从一个静态的地方播放和跟踪歌曲。